Java权限修饰符深度解析与最佳实践
一、权限修饰符总览
Java提供四种访问控制修饰符,按访问范围从宽到窄排序如下:
修饰符 | 类内部 | 同包类 | 不同包子类 | 全局范围 |
---|---|---|---|---|
public | ✔️ | ✔️ | ✔️ | ✔️ |
protected | ✔️ | ✔️ | ✔️ | ❌ |
默认(无) | ✔️ | ✔️ | ❌ | ❌ |
private | ✔️ | ❌ | ❌ | ❌ |
二、各修饰符详解
1. public(全局可见)
访问范围:所有类均可访问
使用场景:
- API接口方法
- 工具类静态方法
- 常量声明
示例:
public class DataParser {
public static final String DATE_FORMAT = "yyyy-MM-dd";
public void parseData(String input) {
// 核心解析逻辑
}
}
2. protected(继承可见)
访问范围:
- 同包类
- 不同包的子类(通过继承访问)
使用场景:
- 模板方法模式中的可扩展方法
- 需要子类重写的核心方法
示例:
public abstract class BaseDao {
protected void validateEntity(Object entity) {
// 公共校验逻辑
}
}
// 不同包的子类
public class UserDao extends BaseDao {
@Override
protected void validateEntity(Object entity) {
super.validateEntity(entity);
// 扩展校验逻辑
}
}
3. 默认/包级私有(Package-Private)
访问范围:仅同包类可见
使用场景:
- 模块内部工具方法
- 实现类之间协作方法
- 不宜暴露的内部组件
示例:
class DatabaseConfig { // 默认修饰符类
static final String DB_URL = "jdbc:mysql://localhost:3306/mydb";
void loadDriver() { // 默认修饰符方法
// 驱动加载逻辑
}
}
4. private(类内封装)
访问范围:仅本类可见
使用场景:
- 内部实现细节
- 辅助方法
- 敏感数据字段
示例:
public class PaymentService {
private String apiKey = "SECRET_KEY";
private boolean validateSignature(String sign) {
// 签名校验逻辑
}
public void processPayment() {
validateSignature("...");
// 支付处理逻辑
}
}
三、继承场景的特殊规则
1. 方法重写限制
- 子类方法访问权限 不能缩小(可等于或扩大)
- 非法示例:
class Parent {
protected void demo() {}
}
class Child extends Parent {
@Override
void demo() {} // 编译错误:不能缩小为包级私有
}
2. 构造函数访问控制
public class Singleton {
private Singleton() {} // 私有构造器
public static Singleton getInstance() {
return Holder.INSTANCE;
}
private static class Holder {
static final Singleton INSTANCE = new Singleton();
}
}
四、最佳实践指南
-
最小化公开元素
优先使用最严格的访问级别(推荐顺序):
private
→ 默认 →protected
→public
-
数据封装原则
- 字段声明为
private
(通过getter/setter访问) - 避免
public
修饰可变对象字段:
- 字段声明为
// 错误示例
public class Config {
public static final Map<String, String> SETTINGS = new HashMap<>();
}
// 正确示例
public class Config {
private static final Map<String, String> SETTINGS = new HashMap<>();
public static String getSetting(String key) {
return Collections.unmodifiableMap(SETTINGS).get(key);
}
}
3.接口方法规范
接口方法默认public abstract
,即使不显式声明:
interface Logger {
void log(String message); // 实际为public abstract
}