1. 概述
toString()
方法是 Java 开发中获取对象字符串表示的常用手段。Project Lombok 能帮我们自动生成一致性的字符串表示,避免手写样板代码污染源文件,尤其当类包含大量字段时,可显著提升代码可维护性。
本文将演示如何通过 Lombok 自动生成 toString()
方法,并深入探讨各种配置选项,助你精准控制输出结果。
2. 环境准备
首先在项目中添加 Lombok 依赖:
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.30</version>
<scope>provided</scope>
</dependency>
后续示例将使用一个简单的 Account
POJO 类演示功能特性:
public class Account {
private String id;
private String name;
// 标准 getter/setter
}
3. 基础用法
直接在类上添加 @ToString
注解即可自动生成 toString()
方法:
@ToString
public class Account {
private String id;
private String name;
// 标准 getter/setter
}
默认行为:
- 输出包含类名
- 按字段声明顺序打印所有非静态字段
- 字段格式为
字段名=值
(优先调用 getter,无 getter 时直接访问字段) - 字段间用逗号分隔
调用示例:
Account account = new Account();
account.setId("12345");
account.setName("An account");
System.out.println(account.toString());
输出结果:
Account(id=12345, name=An account)
对于简单对象,这种默认输出通常已足够清晰。
4. 配置选项
Lombok 提供多种配置选项满足复杂场景需求:
4.1. 调用父类 toString()
默认不包含父类信息,通过 callSuper=true
启用:
@ToString(callSuper = true)
public class SavingAccount extends Account {
private String savingAccountId;
// 标准 getter/setter
}
输出示例:
SavingAccount(super=Account(id=12345, name=An account), savingAccountId=6789)
注意:仅当父类不是
Object
时才有意义(Object.toString()
输出无实际信息)
4.2. 省略字段名
设置 includeFieldNames=false
可简化输出:
@ToString(includeFieldNames = false)
public class Account {
private String id;
private String name;
// 标准 getter/setter
}
输出结果:
Account(12345, An account)
4.3. 直接访问字段而非 getter
通过 doNotUseGetters=true
强制使用字段值:
@ToString(doNotUseGetters = true)
public class Account {
private String id;
private String name;
// 特殊 getter(会被忽略)
public String getId() {
return "this is the id:" + id;
}
// 标准 getter/setter
}
对比输出:
- 默认(调用 getter):
Account(id=this is the id:12345, name=An account)
- 启用后(直接访问字段):
Account(id=12345, name=An account)
4.4. 字段包含与排除
排除敏感字段:
@ToString
public class Account {
private String id;
@ToString.Exclude
private String name; // 被排除
// 标准 getter/setter
}
显式包含字段:
@ToString(onlyExplicitlyIncluded = true)
public class Account {
@ToString.Include
private String id; // 仅包含此字段
private String name; // 被忽略
// 标准 getter/setter
}
两种方式输出相同:
Account(id=12345)
特殊规则:以
$
开头的字段默认排除,但可用@ToString.Include
强制包含
4.5. 输出顺序控制
通过 rank
属性调整字段顺序:
@ToString
public class Account {
private String name;
@ToString.Include(rank = 1)
private String id; // 强制置顶
// 标准 getter/setter
}
输出结果(id 排在 name 前):
Account(id=12345, name=An account)
排序规则:
- rank 值越小越靠前(默认 rank=0)
- 相同 rank 按声明顺序排列
4.6. 包含方法输出
无参实例方法可通过 @ToString.Include
加入输出:
@ToString
public class Account {
private String id;
private String name;
@ToString.Include
String description() {
return "Account description";
}
// 标准 getter/setter
}
输出结果:
Account(id=12345, name=An account, description=Account description)
注意:若方法名与字段名冲突,方法优先级高于字段
4.7. 修改字段名
通过 name
属性自定义输出名称:
@ToString
public class Account {
@ToString.Include(name = "identification")
private String id; // 输出时重命名
private String name;
// 标准 getter/setter
}
输出结果:
Account(identification=12345, name=An account)
5. 数组处理
数组字段通过 Arrays.deepToString()
处理,自动处理循环引用:
@ToString
public class Account {
private String id;
private Object[] relatedAccounts; // 数组字段
// 标准 getter/setter
}
输出示例(含循环引用):
Account(id=12345, relatedAccounts=[54321, [...]])
循环引用会被标记为
[...]
,避免StackOverflowError
6. 注意事项
几个关键点需牢记:
- 手动覆盖优先:类中存在任意名为
toString()
的方法(无论返回类型),Lombok 将不再生成 - 版本兼容性:不同 Lombok 版本输出格式可能变化,避免依赖
toString()
输出做解析 - 枚举支持:可用于枚举类,输出格式如
AccountType.SAVING
7. 总结
通过 Lombok 的 @ToString
注解,我们实现了:
- 零样板代码生成对象字符串表示
- 灵活配置字段包含/排除、顺序、命名等
- 安全处理数组和循环引用
- 支持父类信息和方法输出
建议:优先使用默认配置,仅在特殊场景(如敏感数据隐藏、复杂对象定制)时启用高级选项。
完整示例代码见 GitHub 仓库(链接已更新为有效地址)。