Java 访问权限修饰符详解
在 Java 中,访问权限修饰符用于控制类、属性、方法的可见范围,是封装特性的核心实现手段。合理使用访问权限可以隐藏内部实现细节、保护数据安全,并降低代码耦合度。Java 提供四种访问权限,从最大到最小依次为:public、protected、包访问权限(default,无修饰符)、private。
包(Package):访问权限的基础
包是类的组织单位,用于避免类名冲突并划分访问边界。一个类的全名是 “包名 + 类名”(如 java.util.ArrayList)。通过 import 语句可以简化类的使用(如 import java.util.ArrayList)。
- 同包类:位于同一包下的类,默认具有包访问权限。
- 不同包类:位于不同包下的类,需通过
public 或 protected 权限才能访问。
四种访问权限详解
1. public(公共权限)
- 可见范围:所有类(本类、同包类、子类、非子类)均可访问。
- 适用场景:暴露给外部的接口(如
java.util.List 的 add 方法)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| public class PublicDemo { public String publicField = "公共属性"; public void publicMethod() { System.out.println("公共方法"); } }
public class OtherClass { public static void main(String[] args) { PublicDemo demo = new PublicDemo(); System.out.println(demo.publicField); demo.publicMethod(); } }
|
2. protected(保护权限)
- 可见范围:本类、同包类、子类(无论是否同包)可访问,非子类不可访问。
- 适用场景:仅允许子类继承或同包类协作的成员(如模板方法中的辅助方法)。
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
| package com.example.parent; public class ProtectedDemo { protected String protectedField = "保护属性"; protected void protectedMethod() { System.out.println("保护方法"); } }
package com.example.parent; public class SamePackageClass { public static void main(String[] args) { ProtectedDemo demo = new ProtectedDemo(); System.out.println(demo.protectedField); } }
package com.example.child; import com.example.parent.ProtectedDemo; public class SubClass extends ProtectedDemo { public void test() { System.out.println(protectedField); protectedMethod(); } }
package com.example.other; import com.example.parent.ProtectedDemo; public class OtherClass { public static void main(String[] args) { ProtectedDemo demo = new ProtectedDemo(); } }
|
3. 包访问权限(default,无修饰符)
- 可见范围:仅本类和同包类可访问,子类(不同包)和非子类不可访问。
- 适用场景:包内部的辅助类或成员,不对外暴露(如工具类的内部方法)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| package com.example.pkg; class DefaultDemo { String defaultField = "包访问属性"; void defaultMethod() { System.out.println("包访问方法"); } }
package com.example.pkg; public class SamePackageClass { public static void main(String[] args) { DefaultDemo demo = new DefaultDemo(); System.out.println(demo.defaultField); } }
package com.example.other; import com.example.pkg.DefaultDemo; public class OtherClass { }
|
4. private(私有权限)
- 可见范围:仅本类可访问,其他任何类(包括同包类和子类)均不可访问。
- 适用场景:类的内部状态(属性)或私有方法,完全隐藏实现细节(如封装中的
private 属性)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| public class PrivateDemo { private String privateField = "私有属性"; private void privateMethod() { System.out.println("私有方法"); } public void accessPrivate() { System.out.println(privateField); privateMethod(); } }
public class OtherClass { public static void main(String[] args) { PrivateDemo demo = new PrivateDemo(); demo.accessPrivate(); } }
|
访问权限对比表
| 修饰符 |
本类 |
同包类 |
不同包子类 |
不同包非子类 |
public |
✔️ |
✔️ |
✔️ |
✔️ |
protected |
✔️ |
✔️ |
✔️ |
❌ |
| 包访问(default) |
✔️ |
✔️ |
❌ |
❌ |
private |
✔️ |
❌ |
❌ |
❌ |
使用原则与最佳实践
最小权限原则:尽可能使用小的访问权限(如能 private 就不 protected),减少外部依赖。
属性私有化:类的属性通常用private修饰,通过public的getter/setter方法暴露必要的访问,便于添加校验逻辑。
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| public class User { private String name; public String getName() { return name; } public void setName(String name) { if (name == null || name.isEmpty()) { throw new IllegalArgumentException("姓名不能为空"); } this.name = name; } }
|
接口方法公开:对外提供的接口方法用 public,内部辅助方法用 private 或包访问权限。
谨慎使用 protected:protected 成员会增加类之间的耦合,仅在需要被子类继承时使用。
避免滥用 public:类的内部实现细节(如临时变量、辅助方法)不应设为 public,防止外部依赖导致后续修改困难