Java 中有 四种访问修饰符(access modifiers),它们从访问权限最大到最小依次是:
public > protected > default(包访问权限 / friendly / 无修饰符) > private
权限对照表(最常用、最清晰的总结方式)
| 修饰符 | 当前类 | 同包其他类 | 不同包的子类(继承) | 不同包的普通类 | 常用场景举例 |
|---|---|---|---|---|---|
| public | √ | √ | √ | √ | API 接口、工具类、主类、对外暴露的方法 |
| protected | √ | √ | √ | × | 模板方法模式、框架基类给子类用的钩子方法 |
| default | √ | √ | × | × | 包内工具类、包内协作的实现类、内部状态 |
| private | √ | × | × | × | 内部实现细节、辅助方法、私有字段 |
√ = 可访问 × = 不可访问
详细说明 + 代码示例
- public(公开的)
- 任何地方都能访问(只要类本身可见)
- 最常用于:主类、接口、公共方法、常量
public class UserService {
public void register(String username) { … }
}
- protected(受保护的)
- 同包所有类都能访问
- 不同包的子类也能通过继承访问(这是与 default 最大的区别)
- 不能修饰外部类(top-level class),但可以修饰内部类
// com.company.base
public class BaseEntity {
protected Long id; // 子类常用
protected void init() { … } // 给子类重写用的钩子
}
// com.company.user 不同包
public class User extends BaseEntity {
public void someMethod() {
this.id = 100L; // 可以访问
this.init(); // 可以调用
}
}
- default(包访问权限 / friendly / package-private)
- 没有写任何修饰符时就是 default
- 只能在同一个包内访问
- 非常适合做包级别的封装(比 public 更安全,比 private 更灵活)
// com.company.dao
class UserDao { // 注意:这里故意不写 public
void save(User user) { … } // 只有本包能调用
}
// 其他包的类无法直接 new UserDao() 或调用 save()
- private(私有的)
- 只能在当前类内部访问
- 最严格,用于隐藏实现细节
- 常用于:私有字段 + getter/setter、私有辅助方法
public class Account {
private BigDecimal balance; // 外部不能直接修改
private void checkBalance() { … }
public void deposit(BigDecimal amount) {
checkBalance(); // 内部可调用
balance = balance.add(amount);
}
}
常见面试/易错点速查
| 问题 | 答案 |
|---|---|
| default 能修饰外部类吗? | 可以(不写 public 就是 default) |
| protected 能被不同包的非子类访问吗? | 不能 |
| private 能修饰构造方法吗? | 可以(单例模式常用 private 构造) |
| 子类能否降低父类方法的访问权限? | 不能(子类重写时访问权限必须 ≥ 父类) |
| 接口中方法默认是什么权限? | public abstract(Java 8 前);默认方法是 public |
| 外部类(top-level class)能用 private/protected 吗? | 不能(编译错误) |
| 内部类(成员内部类)能用这四种吗? | 都能(包括 private/protected) |
实际开发建议(经验之谈)
- public:谨慎使用,只给真正需要对外暴露的 API
- protected:主要用在需要被子类定制/扩展的框架/库基类中
- default:大量使用!包内协作的实现类、服务类、工具类优先用 default
- private:能 private 就 private,尽量把实现细节藏起来
这四种修饰符本质上是 Java 封装性 的核心工具,用得好能让代码边界清晰、维护性强。
有哪部分还想再深入一点吗?比如:
- protected 在继承链中的真实访问规则
- 接口、抽象类、枚举的修饰符规则
- 内部类 / 静态内部类 / 局部类的修饰符组合
- 实际项目中常见的权限设计错误
随时问~