官方文档:https://projectlombok.org/features/all
1、Lombok注解
-
@Data
注解在类上,自动为所有字段添加@ToString
,@EqualsAndHashCode
,@Getter
为非final
字段添加@Setter
和@RequiredArgsConstructor
本质上相当于几个注解的综合效果 -
@Getter
注解在属性(类)上,为属性(所有非静态成员变量)提供get()
方法 -
@Setter
注解在属性(类)上,为属性(所有非静态成员变量)提供set()
方法 -
@ToString
该注解的作用是为类自动生成toString()
方法 -
@EqualsAndHashCode
为对象字段自动生成hashCode()
和equals()
实现 -
@AllArgsConstructor
,@RequiredArgsConstructor
,@NoArgsConstructor
顾名思义,为类自动生成对应参数的构造器 -
@Log
,@Log4j
,@Log4j2
,@Slf4j
,@XSlf4j
,@CommonsLog
,@JBossLog
注解在类上,自动为类添加对应的日志支持 -
@NonNull
注解在方法参数上,用于自动生成空值参数检查,自动帮助我们避免空指针 -
@Cleanup
自动帮我们调用close()
方法,作用在局部变量上,在作用域结束时会自动调用close()
方法释放资源,可以关闭流 -
@Builder
注解在类上,被注解的类加个构造者模式 -
Synchronized
注解在类上,加个同步锁 -
@SneakyThrows
等同于try/catch
捕获异常 -
@Value
注解和@Data
类似,区别在于它会把所有成员变量默认定义为private final
修饰,并且不会生成set()
方法
2、@Data
和@Value
的使用
官方说明:All together now:A shortcut for @ToString, @EqualsAndHashCode,@Getter on all fields,@Setter on all non-final fields, and @RequiredArgsConstructor!
- 使用
@Data
后其中@RequiredArgsConstructor
使用了类中的带有@NonNull
注解的或者final
修饰的成员变量,它可以使用@Data(staticConstructor="methodName")
来生成一个静态方法,返回一个调用相应的构造方法产生的对象。 -
@Value
注解和@Data
类似,区别在于它会把所有成员变量默认定义为private final
修饰,并且不会生成set()
方法。
3、@NonNull
的使用
// 使用
public String getName(@NonNull Person person) {
return person.getName;
}
// 不使用
public String getName(Person person) {
if (person == null) {
throw new NullPointerException("person");
}
return person.getName;
}
4、@Cleanup
自动帮我们调用close()
方法
// 使用
public static void main(String[] args) throws IOException {
@Cleanup InputStream in = new FileInputStream(args[0]);
@Cleanup OutputStream out = new FileOutputStream(args[1]);
byte[] b = new byte[10000];
while (true) {
int r = in.read(b);
if (r == -1) break;
out.write(b, 0, r);
}
}
// 不使用
public static void main(String[] args) throws IOException {
InputStream in = new FileInputStream(args[0]);
try {
OutputStream out = new FileOutputStream(args[1]);
try {
byte[] b = new byte[10000];
while (true) {
int r = in.read(b);
if (r == -1) break;
out.write(b, 0, r);
}
} finally {
if (out != null) {
out.close();
}
}
} finally {
if (in != null) {
in.close();
}
}
}
5、@ToString
,@EqualsAndHashCode
使用
- 生成
toString()
,equals()
和hashcode()
方法,同时后者还会生成一个canEqual()
方法,用于判断某个对象是否是当前类的实例,生成方法时只会使用类中的非静态和非transient
成员变量(用transient
关键字标记的成员变量不参与序列化过程),这两个注解同时也可以添加限制条件
// 来排除param1和param2两个成员变量
@ToString(exclude={"param1","param2"})
// 来指定使用param1和param2两个成员变量
@ToString(of={"param1","param2"})
6、@NoArgsConstructor
,@RequiredArgsConstructor
,@AllArgsConstructor
使用
- 这三个注解都是用在类上的,第一个和第三个都很好理解,就是为该类产生无参的构造方法和包含所有参数的构造方法,第二个注解则使用类中所有带有
@NonNull
注解的或者带有final
修饰的成员变量生成对应的构造方法,当然,和前面几个注解一样,成员变量都是非静态的,另外,如果类中含有final
修饰的成员变量,是无法使用@NoArgsConstructor
注解的。
三个注解都可以指定生成的构造方法的访问权限,同时,第二个注解还可以用@RequiredArgsConstructor(staticName="methodName")
的形式生成一个指定名称的静态方法,返回一个调用相应的构造方法产生的对象
// 使用注解
@RequiredArgsConstructor(staticName = "sunsfan")
@AllArgsConstructor(access = AccessLevel.PROTECTED)
@NoArgsConstructor
public class Shape {
private int x;
@NonNull
private double y;
@NonNull
private String name;
}
// 不使用注解
public class Shape {
private int x;
private double y;
private String name;
public Shape(){
}
protected Shape(int x, double y, String name){
this.x = x;
this.y = y;
this.name = name;
}
public Shape(double y, String name){
this.y = y;
this.name = name;
}
public static Shape sunsfan(double y, String name){
return new Shape(y, name);
}
}
7、@SneakyThrows
使用
- 这个注解用在方法上,可以将方法中的代码用
try-catch
语句包裹起来,捕获异常并在catch
中用Lombok.sneakyThrow(e)
把异常抛出,可以使用@SneakyThrows(Exception.class)
的形式指定抛出哪种异常
// 使用注解
public class SneakyThrows implements Runnable {
@SneakyThrows(UnsupportedEncodingException.class)
public String utf8ToString(byte[] bytes) {
return new String(bytes, "UTF-8");
}
@SneakyThrows
public void run() {
throw new Throwable();
}
}
// 不使用注解
public class SneakyThrows implements Runnable {
public String utf8ToString(byte[] bytes) {
try{
return new String(bytes, "UTF-8");
}catch(UnsupportedEncodingException uee){
throw Lombok.sneakyThrow(uee);
}
}
public void run() {
try{
throw new Throwable();
}catch(Throwable t){
throw Lombok.sneakyThrow(t);
}
}
}
8、@Synchronized
使用
- 这个注解用在类方法或者实例方法上,效果和
synchronized
关键字相同,区别在于锁对象不同,对于类方法和实例方法,synchronized
关键字的锁对象分别是类的class
对象和this
对象,而@Synchronized
得锁对象分别是私有静态final
对象lock
和私有final
对象lock
和私有final
对象lock
,当然,也可以自己指定锁对象
// 使用注解
public class Synchronized {
private final Object readLock = new Object();
@Synchronized
public static void hello() {
System.out.println("world");
}
@Synchronized
public int answerToLife() {
return 42;
}
@Synchronized("readLock")
public void foo() {
System.out.println("bar");
}
}
// 不使用
public class Synchronized {
private static final Object $LOCK = new Object[0];
private final Object $lock = new Object[0];
private final Object readLock = new Object();
public static void hello() {
synchronized($LOCK) {
System.out.println("world");
}
}
public int answerToLife() {
synchronized($lock) {
return 42;
}
}
public void foo() {
synchronized(readLock) {
System.out.println("bar");
}
}
}
9、@Log
的使用
- 这个注解用在类上,可以省去从日志工厂生成日志对象这一步,直接进行日志记录,具体注解根据日志工具的不同而不同,同时,可以在注解中使用
topic
来指定生成log
对象时的类名。不同的日志注解总结如下(上面是注解,下面是实际作用)
@CommonsLog
private static final org.apache.commons.logging.Log log = org.apache.commons.logging.LogFactory.getLog(LogExample.class);
@JBossLog
private static final org.jboss.logging.Logger log = org.jboss.logging.Logger.getLogger(LogExample.class);
@Log
private static final java.util.logging.Logger log = java.util.logging.Logger.getLogger(LogExample.class.getName());
@Log4j
private static final org.apache.log4j.Logger log = org.apache.log4j.Logger.getLogger(LogExample.class);
@Log4j2
private static final org.apache.logging.log4j.Logger log = org.apache.logging.log4j.LogManager.getLogger(LogExample.class);
@Slf4j
private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(LogExample.class);
@XSlf4j
private static final org.slf4j.ext.XLogger log = org.slf4j.ext.XLoggerFactory.getXLogger(LogExample.class);