Java 访问权限控制符详解
1. 访问权限控制符概述在 Java 中访问权限控制符Access Modifiers是用于控制类、接口、变量、方法等成员可见性的关键字。它们决定了其他类是否可以访问某个成员是实现面向对象编程中“封装”特性的重要手段。Java 提供了四种访问权限级别从最宽松到最严格依次为public、protected、default包访问权限无关键字和private。2. 四种访问权限详解2.1 public公共的public是限制最宽松的访问级别。被public修饰的成员可以被任何其他类访问无论这些类是否在同一个包中或者是否是子类。// 示例public 类和方法 public class PublicDemo { public String publicField 这是一个公共字段; public void publicMethod() { System.out.println(这是一个公共方法); } } // 在其他任何类中都可以访问 class AnotherClass { public void test() { PublicDemo demo new PublicDemo(); System.out.println(demo.publicField); // 可以访问 demo.publicMethod(); // 可以调用 } }使用场景对外提供的 API 接口、工具类方法、常量等。2.2 protected受保护的protected修饰的成员可以被同一包内的其他类访问也可以被不同包中的子类访问。// 父类在包 com.example package com.example; public class Parent { protected String protectedField 受保护字段; protected void protectedMethod() { System.out.println(受保护方法); } } // 子类在另一个包 com.test package com.test; import com.example.Parent; public class Child extends Parent { public void accessProtected() { System.out.println(protectedField); // 可以访问通过继承 protectedMethod(); // 可以调用 } } // 非子类即使在同一个包也不能直接访问 protected 成员除非通过子类实例 class UnrelatedClass { public void test() { Parent parent new Parent(); // System.out.println(parent.protectedField); // 编译错误 // parent.protectedMethod(); // 编译错误 } }使用场景希望子类能够继承和覆盖但不希望对外完全公开的成员。2.3 default包访问权限当不使用任何访问修饰符时成员具有包访问权限也称为默认访问权限。这意味着它只能被同一个包内的其他类访问。// 在包 com.example 中 package com.example; class DefaultClass { // 默认访问权限的类 String defaultField 默认字段; // 默认访问权限的字段 void defaultMethod() { // 默认访问权限的方法 System.out.println(默认方法); } } // 同一个包内的其他类可以访问 class SamePackageClass { public void test() { DefaultDemo demo new DefaultDemo(); System.out.println(demo.defaultField); // 可以访问 demo.defaultMethod(); // 可以调用 } } // 不同包中的类无法访问 package com.other; import com.example.DefaultDemo; class DifferentPackageClass { public void test() { // DefaultDemo demo new DefaultDemo(); // 编译错误类不可见 // 即使能创建实例也无法访问 default 成员 } }使用场景包内工具类、内部实现细节不希望被包外访问。2.4 private私有的private是限制最严格的访问级别。被private 修饰的成员只能在其定义的类内部访问即使是子类也不能直接访问。public class PrivateDemo { private String privateField 私有字段; private void privateMethod() { System.out.println(私有方法); } // 通过公共方法提供访问封装 public String getPrivateField() { return privateField; } public void setPrivateField(String value) { this.privateField value; } public void callPrivateMethod() { privateMethod(); // 类内部可以调用 } } class TestClass { public void test() { PrivateDemo demo new PrivateDemo(); // System.out.println(demo.privateField); // 编译错误 // demo.privateMethod(); // 编译错误 // 只能通过公共方法访问 System.out.println(demo.getPrivateField()); demo.callPrivateMethod(); } }使用场景类的内部状态、实现细节需要完全隐藏的数据。3. 访问权限总结表访问修饰符同一类中同一包中不同包子类不同包非子类public✅✅✅✅protected✅✅✅❌default✅✅❌❌private✅❌❌❌4. 使用原则与最佳实践4.1 最小权限原则为成员分配尽可能严格的访问权限。如果不确定应该使用哪种权限从private开始然后根据需要逐步放宽。4.2 封装与数据隐藏使用private修饰字段通过公共的 getter 和 setter 方法提供受控的访问这是实现封装的标准做法。public class Student { private String name; private int age; // Getter 和 Setter public String getName() { return name; } public void setName(String name) { if (name ! null !name.trim().isEmpty()) { this.name name; } } public int getAge() { return age; } public void setAge(int age) { if (age 0 age 150) { this.age age; } } }4.3 继承设计如果希望方法被子类覆盖但不希望对外公开使用protected。这为子类提供了扩展点同时隐藏了实现细节。4.4 包设计将功能相关的类放在同一个包中使用default访问权限保护包内实现细节对外只暴露必要的publicAPI。5. 常见问题与注意事项5.1 外部类只能使用 public 或 default顶层类非内部类只能使用public或default访问修饰符不能使用protected或private。5.2 接口成员默认为 public接口中的方法默认是public abstract字段默认是public static final。虽然可以显式指定public但通常省略。5.3 构造函数的访问权限构造函数也可以使用访问修饰符控制对象的创建public任何类都可以创建实例protected同一包或子类可以创建实例default同一包内可以创建实例private常用于单例模式或工具类防止外部实例化5.4 访问权限与继承子类覆盖父类方法时不能降低访问权限可以保持或提高父类public→ 子类必须public父类protected→ 子类可以是protected或public父类default→ 子类可以是default、protected或public但只能在同包中继承父类private→ 不能继承因此也不存在覆盖6. 总结Java 的访问权限控制符是构建健壮、可维护面向对象系统的基石。正确使用这些修饰符可以实现良好的封装、清晰的 API 边界和安全的继承体系。记住从最严格的权限开始只在必要时放宽这是编写高质量 Java 代码的重要原则。