博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
2.lombok系列2:lombok注解详解
阅读量:6918 次
发布时间:2019-06-27

本文共 10457 字,大约阅读时间需要 34 分钟。

转自:https://www.imooc.com/article/18157

开篇

看到第一篇《》你可能意犹未尽,本文我们按照场景来介绍一下常用的注解。

未特别说明,均标注在类级别。

lombok.Data

最常用的注解,编译时自动添加Setter、Getter、toString()、equals()和hashCode()。

1 package com.pollyduan; 2  3 import java.util.Date; 4  5 import lombok.Data; 6  7 @Data 8 public class User { 9     private Integer id;10     private String userName;11     private String password;12     private String email;13     private Integer age;14     private Date signupTime;15     public static void main(String[] args) {16            User user=new User();17            user.setId(1001);18            user.setUserName("pollyduan");19            user.setPassword("123456");20            user.setEmail("pollyduan@pollyduan.com");21            user.setAge(30);22            user.setSignupTime(new Date());23            System.out.println(user);24        System.out.println(user.getUserName());25        System.out.println(user.hashCode());26         }27 }

使用场景:

POJO类、hibernate的实体类、json或jaxb的实体类。

lombok.Value

如果我们需要一个不可变的对象类,那么就用该注解。它在编译是自动添加Getter、toString()、equals()、hashCode()以及一个全参的构造器。

注:没有无参构造器。如果需要,自己添加一个,或者增加一个后面介绍的lombok.NoArgsConstructor注解。

1 package com.pollyduan; 2  3 import java.util.Date; 4  5 import lombok.Value; 6  7 @Value 8 public class User { 9     private Integer id;10     private String userName;11     private String password;12     private String email;13     private Integer age;14     private Date signupTime;15 16     public static void main(String[] args) {17         /*18          * User user=new User();//The constructor User() is undefined19          * user.setId(1001);//The method setId(int) is undefined for the type20          * User21          */22         User user = new User(1001, "pollyduan", "123456", "pollyduan@pollyduan.com", 30, new Date());23         System.out.println(user);24         System.out.println(user.getUserName());25         System.out.println(user.hashCode());26     }27 }

如果自定义了自动生成的方法,以自己定义的为准。

lombok.Builder

它把我们的Bean类包装为一个构建者模式,编译时增加了一个Builder内部类和全字段的构造器。

注:没有Getter、Setter、toString()。如需其他方法,可以自己实现或者配合其他注解。

1 package com.pollyduan; 2  3 import java.util.Date; 4  5 import lombok.Builder; 6 import lombok.Data; 7  8 @Builder 9 public class User {10     private Integer id;11     private String userName;12     private String password;13     private String email;14     private Integer age;15     private Date signupTime;16 17     public static void main(String[] args) {18         /*19          * User user=new User();//The constructor User() is undefined20          */21         User user = new User(1001, "pollyduan", "123456", "pollyduan@pollyduan.com", 30, new Date());22         //或者23         user=User.builder()24                 .age(30)25                 .userName("pollyduan")26                 .build();27         System.out.println(user);28     }29 }

构造器注解

提供了三个构造器注解,分别为:

lombok.AllArgsConstructor 增加全参构造器

lombok.NoArgsConstructor 增加无参构造

lombok.RequiredArgsConstructor 增加必选参数构造器

 

该注解可同时标注,以增加不同的构造器。

可以使用access属性定制访问级别,如:”access = AccessLevel.PROTECTED”

前两个比较简单,必选参数构造器需要配合 lombok.NonNull 注解使用,只有标记了 NonNull 注解的字段才会被纳入 RequiredArgsConstructor 构造器中。

1 package com.pollyduan; 2  3 import java.util.Date; 4  5 import lombok.NonNull; 6 import lombok.RequiredArgsConstructor; 7  8 @RequiredArgsConstructor 9 public class User {10     @NonNull11     private Integer id;12     @NonNull13     private String userName;14     @NonNull15     private String password;16     private String email;17     private Integer age;18     private Date signupTime;19 20     public static void main(String[] args) {21         /*22          * User user=new User();23          * User user = new User(1001, "pollyduan", "123456", "pollyduan@pollyduan.com", 30, new Date());24          * //The constructor User() is undefined25          */26         User user=new User(1001, "pollyduan", "123456");//ok27         System.out.println(user);28     }29 }

定制单个方法

lombok.ToString 这个简单,就是增加toString()方法。

类似的还有:

lombok.EqualsAndHashCode 增加equals() 和 hashCode()。

lombok.Getter 增加Getter方法

lombok.Setter 增加Setter方法

lombok.Cleanup

该注解的对象,如Stream对象,如果有close()方法,那么在该对象作用域离开时会自动关闭。

1 package com.pollyduan; 2  3 import lombok.Cleanup; 4  5 public class MyStream { 6     public void close() { 7         System.out.println("close."); 8     } 9 10     public static void main(String[] args) {11         System.out.println("new a mystream object.");12         @Cleanup13         MyStream ms=new MyStream();14         System.out.println("bye.");15     //退出前会自动调用close()16     }17 }

执行后输出:

new a mystream object.

bye.

close.

日志相关注解

lombok提供了一组日志相关注解,标注的类会隐式的定一个了一个名为log的日志对象。如:

1 package com.pollyduan; 2  3 import lombok.extern.java.Log; 4  5 @Log 6 public class User { 7     public static void main(String[] args) { 8         System.out.println(log.getClass()); 9     log.info("app log.");10     }11 }

输出:

class java.util.logging.Logger

五月 19, 2017 1:32:58 下午 com.pollyduan.User main

信息: app log.

该组注解包括:

1 @CommonsLog 2     Creates private static final org.apache.commons.logging.Log log = org.apache.commons.logging.LogFactory.getLog(LogExample.class); 3  4 @JBossLog 5     Creates private static final org.jboss.logging.Logger log = org.jboss.logging.Logger.getLogger(LogExample.class); 6  7 @Log 8     Creates private static final java.util.logging.Logger log = java.util.logging.Logger.getLogger(LogExample.class.getName()); 9 10 @Log4j11     Creates private static final org.apache.log4j.Logger log = org.apache.log4j.Logger.getLogger(LogExample.class);12 13 @Log4j214     Creates private static final org.apache.logging.log4j.Logger log = org.apache.logging.log4j.LogManager.getLogger(LogExample.class);15 16 @Slf4j17     Creates private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(LogExample.class);18 19 @XSlf4j20     Creates private static final org.slf4j.ext.XLogger log = org.slf4j.ext.XLoggerFactory.getXLogger(LogExample.class);

注:常用的日志处理器都在,一般我们使用log4j或slf4j。

没有logback,请使用slf4j代理logback。

Getter(lazy=true) 懒加载

如果Bean的一个字段的初始化是代价比较高的操作,比如加载大量的数据;同时这个字段并不是必定使用的。那么使用懒加载机制,可以保证节省资源。

懒加载机制,是对象初始化时,该字段并不会真正的初始化;而是第一次访问该字段时才进行初始化字段的操作。

一言不合贴代码:

1 package com.pollyduan; 2  3 import lombok.Data; 4 import lombok.Getter; 5  6 @Data 7 public class GetterLazyExample { 8     @Getter(lazy = true) 9     private final int[] cached = expensive();10     private Integer id;11 12     private int[] expensive() {13         int[] result = new int[100];14         for (int i = 0; i < result.length; i++) {15             result[i] = i;16             System.out.println(i);17         }18         System.out.println("cached 初始化完成。");19         return result;20     }21     public static void main(String[] args) {22         GetterLazyExample obj=new GetterLazyExample();23         obj.setId(1001);24         System.out.println("打印id:"+obj.getId());25         System.out.println("cached 还没有初始化哟。");26         // obj.getCached();27     }28 }

运行就会发现,cached这个字段并没有初始化,虽然看起来它是final的,并直接赋值使用expensive()进行初始化。

打印id:1001 cached

还没有初始化哟。

 
 

打开obj.getCached();的注释,获取这个字段的值,你就会发现它真的初始化了。

打印id:1001

cached 还没有初始化哟。

0 1 ... 97 98 99

cached 初始化完成。

 

Synchronized

同步方法注解。添加了该注解的方法,其方法体都会自动包含在一个synchronize块中。如:

1 package com.pollyduan; 2  3 import java.util.concurrent.BlockingQueue; 4  5 import lombok.AllArgsConstructor; 6 import lombok.Synchronized; 7  8 @AllArgsConstructor 9 public class SynchronizedExample {10     private BlockingQueue
queue;11 12 @Synchronized("queue")13 public void sync1() throws Exception {14 System.out.println("sync1.");15 }16 17 @Synchronized("queue")18 public void sync2() throws Exception {19 System.out.println("sync2.");20 }21 22 @Synchronized23 public void sync3() throws Exception {24 System.out.println("sync3.");25 }26 }

如果直接指定了value=queue,其中queue为类的一个成员,那么该方法使用该成员queue作为加锁对象,放在同步块中执行。那么本例中,sync1和sync2是互斥的,sync1没有执行完之前,sync2会被挂起,等待sync1执行完成之后才可以执行。

sync3,没有指定注解属性,这时lombok会自动创建一个对象作为锁,这样的结果是sync3自身互斥,多线程中两个线程不能同时执行sync3方法。

sync3等同于:

1 private final Object $lock = new Object[0];//lombok添加的2 public void sync3() throws Exception {3     synchronized($lock){4         System.out.println("sync3.");5     }6 }

注:因为sync3与sync1使用的不是同一个锁,那么他们没有互斥关系,sync2也一样。

一定要理清楚锁的关系,否则不要轻易使用该注解。

SneakyThrows 隐藏异常

自动捕获检查异常。

我们知道,java对于检查异常,需要在编码时进行捕获,或者throws抛出。

该注解的作用是将检查异常包装为运行时异常,那么编码时就无需处理异常了。

提示:不过这并不是友好的编码方式,因为你编写的api的使用者,不能显式的获知需要处理检查异常。

1 package com.pollyduan; 2  3 import java.io.FileInputStream; 4 import java.io.FileNotFoundException; 5 import java.io.UnsupportedEncodingException; 6  7 import lombok.SneakyThrows; 8  9 public class SneakyThrowsExample {10     @SneakyThrows({UnsupportedEncodingException.class})11     public void test(byte[] bytes) {12         String str = new String(bytes, "UTF8");13     }14     @SneakyThrows({UnsupportedEncodingException.class,FileNotFoundException.class})15     public void test2(byte[] bytes) {16         FileInputStream file=new FileInputStream("no_texists.txt");17         String str=new String(bytes, "UTF8");18     }19     @SneakyThrows20     public void test3(byte[] bytes) {21         FileInputStream file=new FileInputStream("no_texists.txt");22         String str=new String(bytes, "UTF8");23     }24 25 }

注解接受一个class数组的value属性,如果未指定value属性,默认捕获所有异常。

以上代码相当于:

1 package com.pollyduan; 2  3 import java.io.FileInputStream; 4 import java.io.FileNotFoundException; 5 import java.io.UnsupportedEncodingException; 6  7 import lombok.SneakyThrows; 8  9 public class SneakyThrowsExample {10     public void test(byte[] bytes) {11         try {12             String str = new String(bytes, "UTF8");13         } catch (UnsupportedEncodingException e) {14             e.printStackTrace();15         }16     }17     public void test2(byte[] bytes) {18         try {19             FileInputStream file=new FileInputStream("no_texists.txt");20         } catch (FileNotFoundException e) {21             e.printStackTrace();22         }23         try {24             String str=new String(bytes, "UTF8");25         } catch (UnsupportedEncodingException e) {26             e.printStackTrace();27         }28     }29     public void test3(byte[] bytes) {30         try {31             FileInputStream file=new FileInputStream("no_texists.txt");32             String str=new String(bytes, "UTF8");33         } catch (Throwable e) {34             e.printStackTrace();35         }36     }37 38 }

注:个人建议,了解即可,非必要不要使用。隐藏了异常细节,你的使用者会骂死你。

辅助注解

lombok.NonNull

前面已经使用过了,标记在字段上,表示非空字段。

也可以标注在方法参数上,会在第一次使用该参数是判断是否为空。

转载地址:http://fexcl.baihongyu.com/

你可能感兴趣的文章
unix 高级IO 文件锁
查看>>
我的友情链接
查看>>
Linux find 用法
查看>>
大型分布式网站架构技术总结
查看>>
十种排序算法的C++泛型实现
查看>>
momgodb 备份与恢复
查看>>
阿里腾讯云物理服务器镜像制作工具
查看>>
linux系统定时重启
查看>>
C++之格式化输出
查看>>
sublime text2 快速生成HTML头部信息Emmet(zen coding)
查看>>
symantec backup exec 备份exchange VSS错误
查看>>
ttlsa教程系列之MySQL---MySQL/Galera集群-多主高可用性负载均衡
查看>>
利用好快捷方式/组合键/鼠标动作,使用桌面工作效率更高
查看>>
DNS初体验之完美邂逅
查看>>
android使用startActivityForResult回传参数
查看>>
怎么在Win7下硬盘安装linux?
查看>>
我的友情链接
查看>>
【HTML+CSS+JavaScript】网页实战开发笔记之二—关于Web标准,你不能不知道的事
查看>>
我的友情链接
查看>>
Web系统Spring/SpringMVC启动完成监控
查看>>