Java中只读属性通过私有字段、无setter、可选final实现;需注意返回不可变副本、构造初始化及boolean用isXxx()规范。

Java 中设计只读属性,核心是**阻止外部修改字段值,同时允许安全读取**。这不是靠语法强制“锁住”,而是通过封装机制组合访问控制与语义约定来实现。关键在于:字段私有化 + 不提供 setter + 合理使用 final(可选但推荐)。
只提供 getter 方法
这是最基础、最符合 JavaBean 规范的做法。只要一个字段只有 public 的 getter,没有对应名称的 setter,它在 JavaBean 语义中就被视为只读属性。
- 字段声明为 private,杜绝直接访问
- 提供 public String getName() 这类 getter 方法
- 完全不定义 setName(...) 方法
- 框架(如 Spring、JSP EL、Jackson)会自动识别该属性为只读,不会尝试写入
配合 final 字段增强不可变性
仅靠不写 setter 是逻辑层面的只读;加上 final 可在编译期和运行期双重加固,防止对象内部意外修改。
- 字段声明为 private final String id;
- 必须在构造方法或声明处完成初始化
- 即使类内部也无法重新赋值,彻底杜绝状态变更可能
- 适合 ID、创建时间、配置常量等真正不应变化的字段
避免常见陷阱
只读不等于“绝对安全”,需注意几个易忽略点:
立即学习“Java免费学习笔记(深入)”;
- 不要返回可变对象的引用:如果只读字段是 List 或 Date 等可变类型,getter 直接 return this.list 会导致外部修改影响内部状态。应返回副本,例如 return new ArrayList(this.items); 或 Collections.unmodifiableList(this.items);
- 构造过程要完整:final 字段若依赖计算或外部参数,确保所有路径都完成赋值,否则编译报错
- boolean 属性用 isXxx() 更规范:如 isArchived() 而非 getArchived(),符合 JavaBean 约定,多数框架能正确识别
实际效果示例
以下是一个典型只读属性设计:
public class Order {private final long orderId;
private String status;
public Order(long orderId) {
this.orderId = orderId;
}
public long getOrderId() {
return orderId; // 只读,final + 无 setter
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status; // status 仍可修改
}
}
其中 orderId 是真正的只读属性,status 是可读写属性。这种混合设计很常见,按业务语义灵活控制。


















