正文
引言 Lombok这个插件Java开发一般都不陌生,正常情况下可以用来简化我们的JavaBean代码量,网上找了很多lombok相关的文章,注解介绍都不怎么全,索性自己摸索一篇出来,供大家参考
Lombok概述
Project Lombok is a java library that automatically plugs into your editor and build tools, spicing up your java.Never write another getter or equals method again, with one annotation your class has a fully featured builder, Automate your logging variables, and much more. ######################################################## 大概的意思:Lombok是一个Java库,能自动插入编辑器并构建工具,简化Java开发。通过添加注解的方式,不需要为类编写getter或eques方法,同时可以自动化日志变量。
该不该用Lombok
这个问题可以说一直有很大争议,比如最近爆文:为什么要放弃Lombok,等等许多相似抨击Lombok插件的文章,我个人是比较赞成使用Lombok的,至少目前为止使用非常的得心应手,下面是常见的两方观点;
正方观点 | 反方观点 |
---|---|
代码干净整洁,工作量大大降低 | 强侵入性,一人用都得用,否则编译通不过 |
代码可读性增强,保持代码风格一致 | 失去了封装意义,因为有些属性不一定想提供公共的getter/setter方法 |
Bean修改后,不需要修改模板化代码 | IDE和JDK升级存在破裂的风险 |
安装
使用Lombok必须要安装Lombok插件,在IDEA应用市场搜索lombok,定位到
file/setings/plugins/markeptlace
搜索Lombok
<dependencies> <!--Lombok依赖--> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.12</version> </dependency> </dependencies>
常用注解介绍
可以使用@Getter 或 @Setter标注任何字段,lombok 会帮助你自动生成默认的get、set方法。默认的get、set方法是public的,除非你额外设置AccessLevel
@Getter @Setter public class Person { private String name; private Integer age; } /** * @Getter @Setter private int age = 10; //其他写法 * @Setter(AccessLevel.PROTECTED) private String name; */
@ToString
任何类的定义上都可以被
@ToString
标注,lombok
可以生成一个toString()
的实现方法。默认会打印类名以及每个字段并且用逗号分隔。
@Getter @Setter @ToString public class Person { private String name; private Integer age; }
@Data
@Data 注解在类上面,自动生成
setter/getter、equals、canEqual、hashCode、toString
方法,如某个属性为final,则不会为该属性生成setter方法。
@Data public class Person { private String name; private Integer age; }
@NonNull
可以在方法或构造器的参数上使用
@NonNull,lombok
会为你生成一个空值检查的声明。相当于以下代码
if (param == null) { throw new NullPointerException("null"); }
@Data public class Person { private String name; private Integer age; public Person(@NonNull String person) { this.name = person; } }
@Cleanup
可以使用@Cleanup来确保在代码执行路径退出当前作用域之前自动清除给定的资源。其实就是关闭注解标注的当前资源。【简单了解一下就行,一般也用不上】
public static void main(String[] args) throws Exception { @Cleanup InputStream in = new FileInputStream(args[0]); @Cleanup OutputStream out = new FileOutputStream(args[1]); byte[] b = new byte[1024]; while (true) { int r = in.read(); if (r == -1) break; out.write(b, 0, r); } }
@EqualsAndHashCode
任何类的定义上都可以被
@EqualsAndHashCode
标注,lombok可以生成一个equals(Object other)
和hashCode()的实现方法。它将使用所有非静态,但是可以通过使用@ EqualsAndHashCode.Include
或@EqualsAndHashCode
标记类型成员来修改使用的字段。
import lombok.EqualsAndHashCode; @EqualsAndHashCode public class EqualsAndHashCodeExample { private transient int transientVar = 10; private String name; private double score; @EqualsAndHashCode.Exclude private Shape shape = new Square(5, 10); private String[] tags; @EqualsAndHashCode.Exclude private int id; public String getName() { return this.name; } @EqualsAndHashCode(callSuper=true) public static class Square extends Shape { private final int width, height; public Square(int width, int height) { this.width = width; this.height = height; } } }
@NoArgsConstructor
这组3个注释会生成一个构造函数,该构造函数将为某些字段接受1个参数,并将该参数简单地分配给该字段。
import lombok.AccessLevel; import lombok.RequiredArgsConstructor; import lombok.AllArgsConstructor; import lombok.NonNull; @RequiredArgsConstructor(staticName = "of") @AllArgsConstructor(access = AccessLevel.PROTECTED) public class ConstructorExample<T> { private int x, y; @NonNull private T description; @NoArgsConstructor public static class NoArgsExample { @NonNull private String field; } }
@Value使用
@Value是@Data的不可变形式; 默认情况下,所有字段都设为私有和final的字段,并且不会生成setter。
import lombok.AccessLevel; import lombok.experimental.NonFinal; import lombok.experimental.Value; import lombok.experimental.Wither; import lombok.ToString; @Value public class ValueExample { String name; @Wither(AccessLevel.PACKAGE) @NonFinal int age; double score; protected String[] tags; @ToString(includeFieldNames=true) @Value(staticConstructor="of") public static class Exercise<T> { String name; T value; } }
@Builder
import lombok.Builder; import lombok.Singular; import java.util.Set; @Builder public class BuilderExample { @Builder.Default private long created = System.currentTimeMillis(); private String name; private int age; @Singular private Set<String> occupations; }
Book book = Book.builder() .id(rs.getInt("id")) .bookName(rs.getString("bookname")) .bookDesc(rs.getString("bookdesc")) .pic(rs.getString("pic")) .price(rs.getFloat("price")) .build();
@SneakyThrows
@SneakyThrows可用于偷偷地抛出已检查的异常,而无需在方法的throws子句中实际声明。[这个我经常使用,非常方便]
import lombok.SneakyThrows; public class SneakyThrowsExample implements Runnable { @SneakyThrows(UnsupportedEncodingException.class) public String utf8ToString(byte[] bytes) { return new String(bytes, "UTF-8"); } @SneakyThrows public void run() { throw new Throwable(); } }
@Synchronized
@Synchronized是同步方法修饰符的更安全的变体。 与同步一样,注释只能在静态和实例方法上使用。 它的操作类似于synchronized关键字,但是它锁定在不同的对象上
import lombok.Synchronized; public class SynchronizedExample { 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"); } }
@With
The next best alternative to a setter for an immutable property is to construct a clone of the object, but with a new value for this one field. A method to generate this clone is precisely what @With generates: a withFieldName(newValue) method which produces a clone except for the new value for the associated field. 说实话没看明白这段话是什么意思,个人理解为:在类的字段上标注 @With 注解之后,将会自动生成一个 withFieldName(newValue) 的方法,该方法会基于 newValue 调用相应构造函数,创建一个当前类对应的实例。
import lombok.AccessLevel; import lombok.NonNull; import lombok.With; public class WithExample { @With(AccessLevel.PROTECTED) @NonNull private final String name; @With private final int age; public WithExample(String name, int age) { if (name == null) throw new NullPointerException(); this.name = name; this.age = age; } }
@Getter
@Getter 注解支持一个 lazy 属性,该属性默认为 false。当设置为 true 时,会启用延迟初始化,即当首次调用 getter 方法时才进行初始化。
import lombok.Getter; public class GetterLazyExample { @Getter(lazy=true) private final double[] cached = expensive(); private double[] expensive() { double[] result = new double[1000000]; for (int i = 0; i < result.length; i++) { result[i] = Math.asin(i); } return result; } }
@Accessors
@Accessors注释用于配置lombok如何生成和查找getter和setter。 默认情况下,lombok遵循针对getter和setter的bean规范:例如,名为Pepper的字段的getter是getPepper。 但是,有些人可能希望打破bean规范,以得到更好看的API。 @Accessors提供3种方式: fluent--》 一个布尔值。如果为真,pepper的getter就是 pepper(),setter方法就是pepper(T newValue)。并且,除非特别说明,chain默认为真。 chain--》 一个布尔值。如果为真,产生的setter返回的this而不是void。默认是假。如果fluent=true,那么chain默认为真。 prefix--》 一系列string类型。如果显示,属性必须加上某些定义的前缀。
import lombok.experimental.Accessors; import lombok.Getter; import lombok.Setter; @Accessors(fluent = true) public class AccessorsExample { @Getter @Setter private int age = 10; } class PrefixExample { @Accessors(prefix = "f") @Getter private String fName = "Hello, World!"; }
今天的内容就到这里了,祝我好运,也祝你们好运,加油! 如果觉得这篇文章还不错的话,求在看、求转发,明人不说暗话,我喜欢这种被大家伙宠爱的感觉。 one more thing!如果大家想要第一时间看到墨白更新的文章,可以扫描下方的二维码,关注我的公众号。我们下篇文章见!
本文分享自微信公众号 - 框架师(mohu121),作者:MoBai白
原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。
原始发表时间:2020-07-06
本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。
我来说两句