文章目录

  • ​​添加依赖​​
  • ​​注解​​
  • ​​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​​
  • ​​附录 - References​​

添加依赖

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