Java中getter/setter需严格遵循JavaBeans规范并兼顾不可变性、线程安全与防御性编程:命名须准确(如isActive而非getActive),参数须校验与深拷贝,返回值须防泄漏,非必要字段不暴露访问器。

Java里getter和setter不是“写不写”的问题,而是“怎么写才不埋雷”的问题——字段类型、可见性、不可变性、线程安全、继承关系,任意一个没对齐,后续就容易出 NullPointerException、ConcurrentModificationException 或子类意外覆写行为。
getter/setter命名必须严格遵循JavaBeans规范
IDE自动生成的通常没问题,但手写或重构时容易错。JVM和主流框架(如Jackson、Spring BeanUtils)都依赖这套命名约定,一旦偏差,序列化或反射赋值就会静默失败。
-
get+ 首字母大写的属性名:如private String userName;→getUserName(),不是getUsername()或getuserName() - 布尔类型优先用
is前缀:如private boolean active;→isActive();若强行写成getActive(),Jackson可能无法识别 - 下划线或驼峰混合字段(如
max_retry_count)不能直接转:应映射为getMaxRetryCount(),而非getMax_retry_count()
setter里必须做参数校验和防御性拷贝
暴露了setter就等于把字段控制权部分交出去,不做校验等于邀请调用方传入 null、非法状态或可变对象引用。
public void setConfig(Mapconfig) { if (config == null) { throw new IllegalArgumentException("config must not be null"); } // 防御性拷贝,避免外部修改影响内部状态 this.config = new HashMap<>(config); }
- 基本类型和不可变类(
String、LocalDateTime)可直接赋值 - 集合、数组、自定义可变对象必须深拷贝或包装为不可修改视图(
Collections.unmodifiableList()) - 不要在setter里触发复杂逻辑(如远程调用、持久化),那属于业务方法,不是setter职责
getter返回值要防止内部状态泄露
看似只读的方法,如果返回了可变对象引用,调用方就能绕过封装直接改你的私有字段。
立即学习“Java免费学习笔记(深入)”;
private Listtags = new ArrayList<>(); // ❌ 危险:返回原始引用 public List getTags() { return tags; // 外部可 add/remove,破坏封装 } // ✅ 安全:返回不可修改副本 public List getTags() { return Collections.unmodifiableList(tags); }
- 集合类一律返回不可修改包装或新副本(
new ArrayList(tags)) - 数组用
Arrays.copyOf()而非直接返回引用 - 若字段是
Optional,getter应返回Optional而非解包后的值,否则空值语义丢失
哪些字段不该配getter/setter
不是所有私有字段都需要暴露访问器。加了反而破坏设计意图,还增加维护成本。
- 纯计算字段(如
getFullName()由firstName和lastName拼接)——应作为普通方法,不对应真实字段 - 仅构造时初始化的不可变字段(
final)——只需getter,禁止setter;且getter不应返回可变内容的引用 - 被注解标记为忽略序列化的字段(如
@JsonIgnore、@Transient)——若同时提供setter,框架可能误用,引发数据不一致 - 内部状态标志(如
isProcessing)——若只在本类内使用,不对外暴露,就不该有getter/setter
真正难的不是写出语法正确的getter/setter,而是在每次添加前问一句:这个访问是否必要?返回的是值还是危险的引用?校验边界是否覆盖了所有非法输入?这些判断比敲键盘花的时间多得多。










