Java 实体类:什么时候走 getter、什么时候直接访问字段
·
Java 实体类:什么时候走 getter、什么时候直接访问字段?
一句话结论:外部代码默认调用 getter,本类内部默认直接访问字段,再结合场景细分。
一、先分清两种访问方式
假设实体:
java
运行
public class User {
// 私有字段
private String username;
// getter
public String getUsername() {
System.out.println("执行了 getUsername()");
return username;
}
// setter
public void setUsername(String username) {
this.username = username;
}
}
- 直接访问字段:
user.username - 调用 getter:
user.getUsername()
二、场景 1:类外部访问(99% 情况走 getter)
1. 普通业务代码 / 自己写的 Java 代码
字段被 private 修饰,外部根本无法直接访问,只能调用 getter。
java
运行
// 外部类
User user = new User();
// user.username; // 编译报错!private 外部不可见
user.getUsername(); // 必须走 getter
2. 框架 / 工具自动取值(最常用场景)
主流框架默认优先调用 getter,不会直接读字段:
- Spring MVC / Spring Boot(参数绑定、返回 JSON)
- Jackson / Fastjson / Gson(序列化 JSON)
- MyBatis / Hibernate(ORM 数据库映射)
- Lombok、BeanUtils、反射工具
举例:JSON 序列化
java
运行
User user = new User();
user.setUsername("张三");
// Jackson 底层调用 getUsername()
String json = new ObjectMapper().writeValueAsString(user);
控制台会打印:执行了 getUsername()
只有特殊配置,框架才会改为直接访问字段。
三、场景 2:类内部访问(默认直接读字段)
在 User 类自己的方法里:
java
运行
public class User {
private String username;
public String getUsername() {
return username;
}
// 本类内部方法
public void test() {
// 1. 直接访问字段(不走 getter)
String s1 = this.username;
// 2. 主动调用 getter(才会执行方法逻辑)
String s2 = this.getUsername();
}
}
规则:
- 本类内写
字段名→ 直接读内存字段 - 本类内写
getXxx()→ 才会执行 getter 方法
特例:Lombok @Data / @Getter
Lombok 只是自动生成 getter/setter,访问规则不变:
- 外部:只能 getter
- 内部:默认直读字段
四、哪些情况框架会「直接访问字段」不走 getter?
框架可以通过配置绕过 getter,直接反射读取字段:
1. Jackson 全局 / 单独配置直接访问字段
java
运行
// 类上加注解:强制序列化直接读字段,不走 getter
@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY,
getterVisibility = JsonAutoDetect.Visibility.NONE)
public class User {
private String username;
public String getUsername(){...}
}
2. MyBatis 配置 accessType="FIELD"
xml
<result property="username" column="name" accessType="FIELD"/>
MyBatis 会直接反射赋值 / 取值,跳过 getter/setter。
3. 纯反射代码(手动反射字段)
java
运行
// 手动反射获取字段,不走 getter
Field field = User.class.getDeclaredField("username");
field.setAccessible(true);
String val = (String) field.get(user);
五、高频面试 / 踩坑点
1. getter 里加了业务逻辑(格式化、默认值、计算)
外部框架取值一定会执行这段逻辑,内部直读字段不会。
java
运行
public String getUsername() {
return username == null ? "匿名用户" : username;
}
- JSON 序列化、前端接收 → 看到「匿名用户」
- 本类方法里
this.username→ 拿到原始null
2. 字段 public 公开了
java
运行
public String username;
- 外部代码可以二选一:
user.username或user.getUsername() - 不推荐:破坏封装,业务混乱。
3. 继承场景
子类访问父类 private 字段:依然只能用父类 getter。
六、极简总结表
表格
| 访问位置 | 默认行为 |
|---|---|
| 类 外部 普通代码 | 只能调用 getter(private 限制) |
| 类 内部 自身方法 | 直接读取字段,不走 getter |
| JSON/ORM 等框架(默认) | 调用 getter |
| 手动反射字段 / 框架特殊配置 | 直接读字段,跳过 getter |
补充小建议
- 业务逻辑不要在 getter/setter 写复杂业务,容易因「访问方式不同」出现诡异 bug;
- 实体字段一律
private,严格遵循 Java 封装; - 如果需要统一格式化,放在业务层 / 工具类,而非 getter。
更多推荐

所有评论(0)