Lombok插件使用
原创
©著作权归作者所有:来自51CTO博客作者Jaemon的原创作品,请联系作者获取转载授权,否则将追究法律责任
文章目录
- val & var
- @NonNull
- @Cleanup
- @Getter and @Setter
- @ToString
- @EqualsAndHashCode
- @NoArgsConstructor, @RequiredArgsConstructor, @AllArgsConstructor
- @Data
- @Value
- @Builder
- @SneakyThrows
- @Synchronized
- @Getter(lazy=true)
- @Log (and friends)
- @Delegate
- @Accessors
添加依赖
Maven添加依赖 pom.xml 文件
<dependencies>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.6</version>
</dependency>
</dependencies>
Gradle添加依赖 build.gradle 文件
dependencies {
compileOnly "org.projectlombok:lombok:1.18.6"
}
注解
val & var
import lombok.val;
import java.util.HashMap;
import java.util.Map;
public class AnswerAIL {
public static void main(String[] args) {
withLombok();
System.out.println("\n##############################\n");
withoutLombok();
}
private static void withLombok() {
val map = new HashMap<String, String>();
map.put("name", "answer");
map.put("email", "answer_ljm@163.com");
map.put("address", "pt");
// val 声明的局部变量为 final 类型, 因此以下代码编译会出错
// 把 val map = ... 替换成 var map = ... 以下代码编译就不会出错
map = new HashMap<String, String>();
for (String key: map.keySet()) {
System.out.println(String.format("key[%s]\t\tvalue[%s]", key, map.get(key)));
}
}
private static void withoutLombok() {
Map<String, String> map = new HashMap<>();
map.put("name", "answer");
map.put("email", "answer_ljm@163.com");
map.put("address", "pt");
for (String key: map.keySet()) {
System.out.println(String.format("key[%s]\t\tvalue[%s]", key, map.get(key)));
}
}
}
说明: var 和 val 功能类似(作为局部变量声明的类型), 异同点: val 声明出来的局部变量为 final 类型
@NonNull
import lombok.Data;
import lombok.NonNull;
public class AnswerAIL {
public static void main(String[] args) {
withLombok();
System.out.println("\n##############################\n");
withoutLombok();
}
private static void withLombok() {
WithNonNull withLombok = new WithNonNull("answer");
// 编译出错, 因为 name 字段被 @NonNull 修饰, 不可为空
withLombok = new WithNonNull();
}
private static void withoutLombok() {
WithoutNonNull withoutLombok = new WithoutNonNull("answer");
}
}
@Data
class WithNonNull {
@NonNull
private String name;
private String email;
private String address;
}
@Data
class WithoutNonNull {
private String name;
private String email;
private String address;
public WithoutNonNull(String name) {
this.name = name;
}
}
import lombok.Getter;
import lombok.NonNull;
import lombok.Setter;
public class AnswerAIL {
public static void main(String[] args) {
// withLombok();
System.out.println("\n##############################\n");
withoutLombok();
}
private static void withLombok() {
WithNonNull withNonNull = new WithNonNull(null);
}
private static void withoutLombok() {
WithoutNonNull withoutNonNull = new WithoutNonNull(null);
}
}
class WithNonNull {
@Getter
@Setter
private String name;
public WithNonNull(@NonNull String name) {
this.name = name;
}
}
class WithoutNonNull {
@Getter
@Setter
private String name;
public WithoutNonNull(String name) {
if (name == null) {
throw new NullPointerException("name is marked @NonNull but is null");
}
this.name = name;
}
}
@Cleanup
import lombok.Cleanup;
import java.io.*;
public class AnswerAIL {
public static void main(String[] args) {
// withLombok();
System.out.println("\n##############################\n");
withoutLombok();
}
private static void withLombok() {
try {
@Cleanup InputStream in = new FileInputStream("C:/ftpshare/answer.txt");
@Cleanup OutputStream out = new FileOutputStream("C:/ftpshare/copy.txt");
byte[] b = new byte[10000];
while (true) {
int r = in.read(b);
if (r == -1) break;
out.write(b, 0, r);
}
} catch (IOException e) {
e.printStackTrace();
}
}
private static void withoutLombok() {
InputStream in = null;
OutputStream out = null;
try {
in = new FileInputStream("C:/ftpshare/answer.txt");
out = new FileOutputStream("C:/ftpshare/copy.txt");
byte[] b = new byte[10000];
while (true) {
int r = in.read(b);
if (r == -1) break;
out.write(b, 0, r);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (out != null) {
try {
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (in != null) {
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
可以使用 @Cleanup 确保在代码执行路径退出当前作用域之前自动清理给定的资源。
可以使用@Cleanup 注释对任何局部变量声明进行注释。
@Getter and @Setter
import lombok.AccessLevel;
import lombok.Getter;
import lombok.Setter;
public class AnswerAIL {
public static void main(String[] args) {
withLombok();
System.out.println("\n##############################\n");
withoutLombok();
}
private static void withLombok() {
WithLombok withLombok = new WithLombok();
withLombok.setName("answer");
withLombok.setEmail("answer@ljm@163.com");
System.out.println(withLombok.toString());
}
private static void withoutLombok() {
WithoutLombok withoutLombok = new WithoutLombok();
withoutLombok.setName("answer");
withoutLombok.setEmail("answer@ljm@163.com");
System.out.println(withoutLombok.toString());
}
}
class WithLombok {
@Getter
@Setter
private String name;
@Setter(AccessLevel.PROTECTED)
private String email;
@Override
public String toString() {
return String.format("name[%s]\t\temail[%s]", name, email);
}
}
class WithoutLombok {
private String name;
private String email;
@Override
public String toString() {
return String.format("name[%s]\t\temail[%s]", name, email);
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
protected void setEmail(String email) {
this.email = email;
}
}
@ToString
import lombok.ToString;
public class AnswerAIL {
public static void main(String[] args) {
Student student = new Student();
System.out.println(student.toString());
}
}
@ToString
class Person {
private String name = "answer";
private int sex = 1;
}
/**
* # @ToString()
* Student(schoolName=ptwz)
*
* # @ToString(callSuper = true, includeFieldNames = false)
* Student(super=Person(name=answer, sex=1), ptwz)
*
* # @ToString(callSuper = true)
* Student(super=Person(name=answer, sex=1), schoolName=ptwz)
* */
@ToString()
class Student extends Person {
private String schoolName = "ptwz";
// 重写 ToString 方法时, 排除掉 stuNo 字段
@ToString.Exclude
private String stuNo = "100000001";
}
@EqualsAndHashCode
import lombok.EqualsAndHashCode;
public class AnswerAIL {
}
@EqualsAndHashCode
class Person {
private String name = "answer";
private int sex = 1;
}
@EqualsAndHashCode(callSuper = false, of = {"schoolName"})
class Student extends Person {
private String schoolName = "ptwz";
// 此处编译会出错, 因为和 EqualsAndHashCode 中的 of 参数冲突
// @EqualsAndHashCode.Exclude
private String stuNo = "100000001";
}
- 生成
equals(Object other)
和 hashCode()
方法的实现 - 它默认使用所有非静态,非瞬态字段
- 可通过参数
@EqualsAndHashCode.Exclude
排除一些属性 - 可通过参数
of
指定仅使用哪些属性 - 默认仅使用该类中定义的属性且不调用父类的方法, 可通过设置
callSuper = false
来让其生成的方法中调用父类的方法
@NoArgsConstructor, @RequiredArgsConstructor, @AllArgsConstructor
import lombok.AccessLevel;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import lombok.ToString;
public class AnswerAIL {
public static void main(String[] args) {
Person person = Person.answerMethod("answer", 10);
System.out.println(person.toString());
}
}
// 定义静态方法的名称为 answerMethod, 修饰符为 public
@RequiredArgsConstructor(staticName = "answerMethod", access = AccessLevel.PUBLIC)
@ToString
class Person {
@NonNull
private String name;
private final int age;
private String email;
}
/* Output: Person(name=answer, age=10, email=null) */
- RequiredArgsConstructor: 为所有 final 和 @NonNull 修饰的字段生成一个构造方法,
生成的构造方法是private
,如何想要对外提供使用可以使用 staticName
选项生成一个static方法 - NoArgsConstructor: 生成一个无参数的构造方法
- AllArgsConstructor: 生成一个包含所有变量,同时如果变量使用了@NonNull修饰, 会进行是否为空的校验
@Data
import lombok.Data;
import lombok.NonNull;
public class AnswerAIL {
public static void main(String[] args) {
Person person = Person.newInstance("answer", "answer_ljm@163.com");
System.out.println(person.toString());
}
}
@Data(staticConstructor = "newInstance")
class Person {
@NonNull
private String name;
@NonNull
private String email;
}
/* Output: Person(name=answer, email=answer_ljm@163.com) */
说明: @Data 注释已经隐式的包含了 @Getter、@Setter、@ToString、@EqualSandHashCode 以及 @RequiredArgsConstructor 注释
@Value
https://projectlombok.org/features/Value
@Builder
https://projectlombok.org/features/Builder
@SneakyThrows
@SneakyThrows
public void method() {
dataService.queryList();
}
// 反编译后代码
public void method() {
try {
this.dataService.queryList();
} catch (Throwable var2) {
throw var2;
}
}
https://projectlombok.org/features/SneakyThrows
@Synchronized
https://projectlombok.org/features/Synchronized
@Getter(lazy=true)
https://projectlombok.org/features/GetterLazy
@Log (and friends)
@Log
import lombok.extern.java.Log;
// withLombok
@Log
public class AnswerAIL {
// withoutLombok
// private static final java.util.logging.Logger log = java.util.logging.Logger.getLogger(AnswerAIL.class.getName());
public static void main(String[] args) {
log.severe("answer ai l");
log.info("answer ai l");
}
}
@Slf4j
import lombok.extern.slf4j.Slf4j;
// withLombok
@Slf4j
public class AnswerAIL {
// withoutLombok
// private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(AnswerAIL.class.getName());
public static void main(String[] args) {
log.info("answer ai l");
}
}
@CommonsLog
import lombok.extern.apachecommons.CommonsLog;
// withLombok, 指定 topic 值, 默认为 类的全限定名
@CommonsLog(topic = "AnswerLog")
public class AnswerAIL {
// withoutLombok, LogFactory.getLog(AnswerAIL.class);
// private static final org.apache.commons.logging.Log log = org.apache.commons.logging.LogFactory.getLog("AnswerLog");
public static void main(String[] args) {
log.info("answer ai l");
}
}
@Delegate
通过 @Delegate
注释实现代理模式
public interface IUserService {
int insertUser();
List<String> findUserNames();
int updateUser();
int deleteUser();
// 注意此方法对应 UserMapper.findUserIds
List<Long> queryUserIds();
}
@Service
public class UserServiceImpl implements IUserService {
@lombok.experimental.Delegate
private final UserMapper userMapper;
@Autowired
public UserServiceImpl(UserMapper userMapper) {
this.userMapper = userMapper;
}
@Override
public List<Long> queryUserIds() {
return this.userMapper.findUserIds();
}
}
public interface UserMapper {
int insertUser();
List<String> findUserNames();
int updateUser();
int deleteUser();
List<Long> findUserIds();
}
public class UserServiceImpl {
/**
* 代理 userMapper 的所有方法(对外提供的方法名和代理的方法名一致)
* */
@Delegate
private final UserMapper userMapper;
public UserServiceImpl(UserMapper userMapper) {
this.userMapper = userMapper;
}
}
@Accessors
链式风格
@Data
@Accessors(chain = true)
public class OrderDTO {
private String orderNo;
private Double orderAmt;
private Byte orderStatus;
}
OrderDTO order = new OrderDTO();
order.setOrderNo("201912110001").setOrderAmt(12.542).setOrderStatus((byte)10);
它有三个选项:(以 name 成员变量为例)
- fluent: 默认值是 false。如果是 false ,setter 生成的函数是 String setName(String name); 如果是 true, setter 是生成的是 User name(String name) ,返回的是 this,是种链式 Setter,同时 chain 会是 true。
- chain: 默认值是 false。如果是 true,setter 生成的函数是 User setName(String name)。否则的是void setName(String name)
- prefix: 比如成员变量是 gk_name,加上注解 @Accessors(prefix = “gk_”),生成的 Getter 和 Setter 中则没有 gk_ 前缀
附录 - References