Java中public、protected、package - private和private的区别
技术背景
在Java编程中,访问修饰符是实现封装的重要手段,它可以控制类、方法和变量的访问权限,提高代码的安全性和可维护性。Java提供了四种访问修饰符:public
、protected
、package - private
(默认,无修饰符)和private
,了解它们之间的区别对于编写高质量的Java代码至关重要。
实现步骤
1. 明确不同访问修饰符的作用范围
修饰符 | 类内部 | 同一包内 | 不同包的子类 | 全局 |
---|
public | ✔️ | ✔️ | ✔️ | ✔️ |
protected | ✔️ | ✔️ | ✔️ | ❌ |
package - private (无修饰符) | ✔️ | ✔️ | ❌ | ❌ |
private | ✔️ | ❌ | ❌ | ❌ |
2. 不同访问修饰符的详细解释
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| class A { private int data = 40; private void msg() { System.out.println("Hello java"); } }
public class Simple { public static void main(String args[]) { A obj = new A(); System.out.println(obj.data); obj.msg(); } }
|
package - private
(无修饰符):可以被同一包内的其他类访问。例如:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| package pack;
class A { void msg() { System.out.println("Hello"); } }
package mypack; import pack.*;
class B { public static void main(String args[]) { A obj = new A(); obj.msg(); } }
|
protected
:可以被同一包内的类以及不同包的子类访问。例如:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| package pack; public class A { protected void msg() { System.out.println("Hello"); } }
package mypack; import pack.*;
class B extends A { public static void main(String args[]) { B obj = new B(); obj.msg(); } }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| package pack; public class A { public void msg() { System.out.println("Hello"); } }
package mypack; import pack.*;
class B { public static void main(String args[]) { A obj = new A(); obj.msg(); } }
|
核心代码
以下是一个包含不同访问修饰符的完整类示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
| package com.example;
public class MainClass { public int publicField = 1; protected int protectedField = 2; int defaultField = 3; private int privateField = 4;
public void publicMethod() { System.out.println("This is a public method."); }
protected void protectedMethod() { System.out.println("This is a protected method."); }
void defaultMethod() { System.out.println("This is a default method."); }
private void privateMethod() { System.out.println("This is a private method."); }
public static void main(String[] args) { MainClass obj = new MainClass(); System.out.println(obj.publicField); System.out.println(obj.protectedField); System.out.println(obj.defaultField); System.out.println(obj.privateField); obj.publicMethod(); obj.protectedMethod(); obj.defaultMethod(); obj.privateMethod(); } }
|
最佳实践
- 遵循“最小知识原则”,即尽量让成员的可见性最小化。优先使用
private
,仅在必要时增加可见性。 - 如果成员仅在类内部使用,应声明为
private
。 - 如果成员仅在同一包内使用,使用默认(无修饰符)。
- 如果成员需要被子类访问,但不希望全局可访问,使用
protected
。 - 如果成员需要被所有类访问,使用
public
。
常见问题
1. 为什么Java的默认访问修饰符是package - private
?
默认使用package - private
可以在一定程度上限制类的访问范围,提高代码的内聚性和安全性。同一包内的类可以相互协作,而外部包的类无法直接访问这些类的成员。
2. protected
修饰符的复杂情况
protected
修饰符的访问规则比较复杂,例如在不同包的子类中,不能通过父类的引用访问受保护成员,只能通过子类自身的实例或this
、super
关键字访问。
3. 访问修饰符对类和接口的限制
对于顶级类,只能使用public
和package - private
修饰符;protected
和private
不能用于顶级类,因为在包级别使用它们是多余的。接口中的方法默认是public
的,不能使用其他访问修饰符。