1. 概述
本文深入探讨 Java 中的访问修饰符(Access Modifiers),它们用于控制类、变量、方法和构造器的访问级别。
✅ 简单来说,Java 提供了四种访问修饰符:public
、private
、protected
和默认(即不写任何关键字,也叫 package-private)。
⚠️ 需要注意的是:顶层类只能使用 public
或默认访问修饰符;而类的成员(字段、方法等)则可以使用全部四种。
合理使用访问修饰符是实现封装、提升代码安全性和可维护性的关键。踩过坑的人都知道,随便用 public
会导致类的内部细节暴露过多,后期重构寸步难行。
2. 默认访问修饰符(default / package-private)
当你没有显式指定任何访问修饰符时,Java 会自动赋予该成员“默认”访问权限,也称为 包私有(package-private)。
这意味着:
- ✅ 同一个包内的其他类可以访问该成员
- ❌ 不同包的类无法访问
示例代码如下:
package com.example.access;
public class SuperPublic {
static void defaultMethod() {
System.out.println("This is package-private method");
}
}
在同一个包中可以正常调用:
package com.example.access;
public class Public {
public Public() {
SuperPublic.defaultMethod(); // ✅ 合法:同包访问
}
}
但如果尝试从另一个包中访问,编译器就会报错:
package com.example.another;
import com.example.access.SuperPublic;
public class ExternalClass {
public ExternalClass() {
SuperPublic.defaultMethod(); // ❌ 编译错误:不在同一包
}
}
所以,如果你希望某些工具方法只在模块内部使用,又不想写成 private
(因为多个类要用),那默认访问就是最合适的——简单粗暴且安全。
3. public
public
是最开放的访问级别,意味着“对全世界可见”。
一旦一个类、方法或字段被声明为 public
,所有其他包中的类都可以通过导入来访问它。
package com.example.access;
public class SuperPublic {
public static void publicMethod() {
System.out.println("This is a public method");
}
}
在不同包中也能顺利调用:
package com.example.another;
import com.example.access.SuperPublic;
public class AnotherPublic {
public AnotherPublic() {
SuperPublic.publicMethod(); // ✅ 成功调用,跨包访问
}
}
⚠️ 但要注意:public
应谨慎使用,尤其是暴露给外部 API 的接口。一旦发布,就不能轻易修改,否则会破坏兼容性。
📌 小贴士:关于
public
在类、接口、嵌套类中的具体行为,可参考 Java public 关键字详解。
4. private
private
是最严格的访问控制,仅限本类内部访问。
这是实现封装的核心手段。数据隐藏、内部逻辑隔离,都靠它。
package com.example.access;
public class SuperPublic {
static private void privateMethod() {
System.out.println("This is private");
}
private void anotherPrivateMethod() {
privateMethod(); // ✅ 合法:同一类内调用
}
}
任何外部类(包括子类)都无法访问这些成员:
package com.example.another;
import com.example.access.SuperPublic;
public class SubClass extends SuperPublic {
public SubClass() {
SuperPublic.privateMethod(); // ❌ 编译错误:无法访问 private 方法
}
}
✅ 推荐实践:**默认所有字段和辅助方法都声明为 private
**,除非有明确理由需要放宽访问权限。
📌 想了解
private
在字段、构造器、内部类中的更多细节?看这篇 Java private 关键字深度解析。
5. protected
protected
处于 public
和 private
之间,是一种“家族特权”式的访问控制。
它的规则是:
- ✅ 同一个包内的所有类可以访问
- ✅ 不同包中的子类也可以访问(即使不在同一个包)
来看例子:
package com.example.access;
public class SuperPublic {
static protected void protectedMethod() {
System.out.println("This is protected");
}
}
子类即使在不同包中,也能访问该方法:
package com.example.another;
import com.example.access.SuperPublic;
public class AnotherSubClass extends SuperPublic {
public AnotherSubClass() {
SuperPublic.protectedMethod(); // ✅ 合法:子类访问 protected 方法
}
}
但注意:非子类的外部类仍然不能访问:
public class UnrelatedClass {
public UnrelatedClass() {
SuperPublic.protectedMethod(); // ❌ 编译错误:非子类且跨包
}
}
✅ 使用场景:当你希望子类继承并扩展某些功能,但又不想完全公开给所有类时,protected
是最佳选择。
📌 更多关于
protected
在字段、方法、内部类中的行为,请查看 Java protected 访问修饰符详解。
6. 访问级别对比总结
下表清晰地展示了四种访问修饰符的权限范围:
修饰符 | 本类 | 同包 | 子类 | 全世界(跨包非子类) |
---|---|---|---|---|
public |
✅ | ✅ | ✅ | ✅ |
protected |
✅ | ✅ | ✅ | ❌ |
default |
✅ | ✅ | ❌ | ❌ |
private |
✅ | ❌ | ❌ | ❌ |
📌 关键点:
- 所有修饰符都保证“本类可访问”
protected
的“子类访问”能力是其最大特点default
实际上就是“同包可见”private
封闭性最强,适合隐藏实现细节
7. 修饰符的标准顺序(Canonical Order)
虽然 Java 不强制要求修饰符的书写顺序,但 Java 语言规范(JLS)推荐了一套标准顺序,有助于统一代码风格,提升可读性。
✅ 字段修饰符推荐顺序:
- 注解(Annotation)
- 访问修饰符(
public
/protected
/private
) static
final
transient
volatile
示例:
@Id
private static final long ID = 1;
这个写法完全符合 JLS 推荐的 canonical order。
✅ 类修饰符推荐顺序:
- 注解
- 访问修饰符
abstract
static
final
strictfp
✅ 方法修饰符推荐顺序:
- 注解
- 访问修饰符
abstract
static
final
synchronized
native
strictfp
⚠️ 注意:并非所有修饰符都能共存。例如:
public
、protected
、private
三者互斥abstract
和final
不能同时用于类static
和abstract
不能同时用于方法
🔧 实用技巧:像 IntelliJ IDEA 这类主流 IDE,在格式化代码时会自动调整修饰符顺序。只需一键 Ctrl + Alt + L
,立刻合规。
📌 想了解
static final
的正确顺序?参考 Java static final 修饰符顺序规范。
8. 总结
访问修饰符是 Java 面向对象编程的基石之一,合理使用能极大提升代码质量。
✅ 核心建议:
- 优先使用最严格的访问级别,即默认从
private
开始 - 只有真正需要对外暴露的 API 才使用
public
protected
适用于受控继承场景- 包级访问(default)适合模块内部协作
❌ 常见误区:
- 所有方法都写成
public
,导致封装失效 - 忽视修饰符顺序,影响代码一致性
- 对
protected
的跨包子类访问机制理解不清
所有示例代码已上传至 GitHub:https://github.com/example-java/tutorials/tree/master/core-java-modules/core-java-lang-oop-modifiers