Lombok是一款好用顺手的工具,就像Google Guava同样,在此予以强烈推荐,每个Java工程师都应该使用它。Lombok是一种Java™实用工具,可用来帮助开发人员消除Java的冗长代码,尤为是对于简单的Java对象(POJO)。它经过注释实现这一目的。经过在开发环境中实现Lombok,开发人员能够节省构建诸如hashCode()和equals()这样的方法以及以往用来分类各类accessor和mutator的大量时间。html
经过IntelliJ的插件中心安装java
Install Pluginweb
最后须要注意的是,在使用lombok注解的时候记得要导入lombok.jar包到工程,若是使用的是Maven Project,要在pom.xml中添加依赖。apache
<dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.16.8</version> </dependency>
val
:用在局部变量前面,至关于将变量声明为final@NonNull
:给方法参数增长这个注解会自动在方法内对该参数进行是否为空的校验,若是为空,则抛出NPE(NullPointerException)@Cleanup
:自动管理资源,用在局部变量以前,在当前变量范围内即将执行完毕退出以前会自动清理资源,自动生成try-finally这样的代码来关闭流@Getter/@Setter
:用在属性上,不再用本身手写setter和getter方法了,还能够指定访问范围@ToString
:用在类上,能够自动覆写toString方法,固然还能够加其余参数,例如@ToString(exclude=”id”)排除id属性,或者@ToString(callSuper=true, includeFieldNames=true)调用父类的toString方法,包含全部属性@EqualsAndHashCode
:用在类上,自动生成equals方法和hashCode方法@NoArgsConstructor, @RequiredArgsConstructor and @AllArgsConstructor
:用在类上,自动生成无参构造和使用全部参数的构造函数以及把全部@NonNull属性做为参数的构造函数,若是指定staticName = “of”参数,同时还会生成一个返回类对象的静态工厂方法,比使用构造函数方便不少@Data
:注解在类上,至关于同时使用了@ToString
、@EqualsAndHashCode
、@Getter
、@Setter
和@RequiredArgsConstrutor
这些注解,对于POJO类
十分有用@Value
:用在类上,是@Data的不可变形式,至关于为属性添加final声明,只提供getter方法,而不提供setter方法@Builder
:用在类、构造器、方法上,为你提供复杂的builder APIs,让你能够像以下方式同样调用Person.builder().name("Adam Savage").city("San Francisco").job("Mythbusters").job("Unchained Reaction").build();
更多说明参考Builder@SneakyThrows
:自动抛受检异常,而无需显式在方法上使用throws语句@Synchronized
:用在方法上,将方法声明为同步的,并自动加锁,而锁对象是一个私有的属性$lock
或$LOCK
,而java中的synchronized关键字锁对象是this,锁在this或者本身的类对象上存在反作用,就是你不能阻止非受控代码去锁this或者类对象,这可能会致使竞争条件或者其它线程错误@Getter(lazy=true)
:能够替代经典的Double Check Lock样板代码@Log
:根据不一样的注解生成不一样类型的log对象,可是实例名称都是log,有六种可选实现类
@CommonsLog
Creates log = org.apache.commons.logging.LogFactory.getLog(LogExample.class);@Log
Creates log = java.util.logging.Logger.getLogger(LogExample.class.getName());@Log4j
Creates log = org.apache.log4j.Logger.getLogger(LogExample.class);@Log4j2
Creates log = org.apache.logging.log4j.LogManager.getLogger(LogExample.class);@Slf4j
Creates log = org.slf4j.LoggerFactory.getLogger(LogExample.class);@XSlf4j
Creates log = org.slf4j.ext.XLoggerFactory.getXLogger(LogExample.class);public static void main(String[] args) { val sets = new HashSet<String>(); val lists = new ArrayList<String>(); val maps = new HashMap<String, String>(); //=>至关于以下 final Set<String> sets2 = new HashSet<>(); final List<String> lists2 = new ArrayList<>(); final Map<String, String> maps2 = new HashMap<>(); }
public void notNullExample(@NonNull String string) { string.length(); } //=>至关于 public void notNullExample(String string) { if (string != null) { string.length(); } else { throw new NullPointerException("null"); } }
public static void main(String[] args) { try { @Cleanup InputStream inputStream = new FileInputStream(args[0]); } catch (FileNotFoundException e) { e.printStackTrace(); } //=>至关于 InputStream inputStream = null; try { inputStream = new FileInputStream(args[0]); } catch (FileNotFoundException e) { e.printStackTrace(); } finally { if (inputStream != null) { try { inputStream.close(); } catch (IOException e) { e.printStackTrace(); } } } }
@Setter(AccessLevel.PUBLIC) @Getter(AccessLevel.PROTECTED) private int id; private String shap;
@ToString(exclude = "id", callSuper = true, includeFieldNames = true) public class LombokDemo { private int id; private String name; private int age; public static void main(String[] args) { //输出LombokDemo(super=LombokDemo@48524010, name=null, age=0) System.out.println(new LombokDemo()); } }
@EqualsAndHashCode(exclude = {"id", "shape"}, callSuper = false) public class LombokDemo { private int id; private String shap; }
@NoArgsConstructor @RequiredArgsConstructor(staticName = "of") @AllArgsConstructor public class LombokDemo { @NonNull private int id; @NonNull private String shap; private int age; public static void main(String[] args) { new LombokDemo(1, "circle"); //使用静态工厂方法 LombokDemo.of(2, "circle"); //无参构造 new LombokDemo(); //包含全部参数 new LombokDemo(1, "circle", 2); } }
import lombok.Data; @Data public class Menu { private String shopId; private String skuMenuId; private String skuName; private String normalizeSkuName; private String dishMenuId; private String dishName; private String dishNum; //默认阈值 private float thresHold = 0; //新阈值 private float newThresHold = 0; //总得分 private float totalScore = 0; }
@Value public class LombokDemo { @NonNull private int id; @NonNull private String shap; private int age; //至关于 private final int id; public int getId() { return this.id; } ... }
@Builder public class BuilderExample { private String name; private int age; @Singular private Set<String> occupations; public static void main(String[] args) { BuilderExample test = BuilderExample.builder().age(11).name("test").build(); } }
import lombok.SneakyThrows; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.InputStream; import java.io.UnsupportedEncodingException; public class Test { @SneakyThrows() public void read() { InputStream inputStream = new FileInputStream(""); } @SneakyThrows public void write() { throw new UnsupportedEncodingException(); } //至关于 public void read() throws FileNotFoundException { InputStream inputStream = new FileInputStream(""); } public void write() throws UnsupportedEncodingException { throw new UnsupportedEncodingException(); } }
public class SynchronizedDemo { @Synchronized public static void hello() { System.out.println("world"); } //至关于 private static final Object $LOCK = new Object[0]; public static void hello() { synchronized ($LOCK) { System.out.println("world"); } } }
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; } } // 至关于以下所示: import java.util.concurrent.atomic.AtomicReference; public class GetterLazyExample { private final AtomicReference<java.lang.Object> cached = new AtomicReference<>(); public double[] getCached() { java.lang.Object value = this.cached.get(); if (value == null) { synchronized (this.cached) { value = this.cached.get(); if (value == null) { final double[] actualValue = expensive(); value = actualValue == null ? this.cached : actualValue; this.cached.set(value); } } } return (double[]) (value == this.cached ? null : value); } private double[] expensive() { double[] result = new double[1000000]; for (int i = 0; i < result.length; i++) { result[i] = Math.asin(i); } return result; } }
说道 Lombok,咱们就得去提到 JSR 269: Pluggable Annotation Processing API (www.jcp.org/en/jsr/deta…) 。JSR 269 以前咱们也有注解这样的神器,但是咱们好比想要作什么必须使用反射,反射的方法局限性较大。首先,它必须定义@Retention为RetentionPolicy.RUNTIME,只能在运行时经过反射来获取注解值,使得运行时代码效率下降。其次,若是想在编译阶段利用注解来进行一些检查,对用户的某些不合理代码给出错误报告,反射的使用方法就无能为力了。而 JSR 269 以后咱们能够在 Javac的编译期利用注解作这些事情。因此咱们发现核心的区分是在 运行期 仍是 编译期。ide
从上图可知,Annotation Processing 是在解析和生成之间的一个步骤。具体详细步骤以下:函数
上图是 Lombok 处理流程,在Javac 解析成抽象语法树以后(AST), Lombok 根据本身的注解处理器,动态的修改 AST,增长新的节点(所谓代码),最终经过分析和生成字节码。工具
自从Java 6起,javac就支持“JSR 269 Pluggable Annotation Processing API”规范,只要程序实现了该API,就能在javac运行的时候获得调用。post
- 经常使用的项目管理工具Maven所使用的java编译工具来源于配置的第三方工具,若是咱们配置这个第三方工具为Oracle javac的话,那么Maven也就直接支持lombok了;
- Intellij Idea配置的编译工具为Oracle javac的话,也就直接支持lombok了;
IDE工具问题解决:优化
如今有一个A类,其中有一些字段,没有建立它们的setter和getter方法,使用了lombok的@Data注解,另外有一个B类,它调用了A类实例的相应字段的setter和getter方法ui
编译A类和B类所在的项目,并不会报错,由于最终生成的A类字节码文件中存在相应字段的setter和getter方法
可是,IDE发现B类源代码中所使用的A类实例的setter和getter方法在A类源代码中找不到定义,IDE会认为这是错误
要解决以上这个不是真正错误的错误,能够下载安装Intellij Idea中的"Lombok plugin"。
通常javac的编译过程,java文件首先经过进行解析构建出一个AST,而后执行注解处理,最后通过分析优化生成二进制的.class文件。咱们能作到的是,在注解处理阶段进行一些相应处理。首先咱们在META-INF.services下建立以下文件:
文件中指定咱们的注解处理器:com.alipay.kris.other.lombok.MyAnnotaionProcessor
,而后咱们接能够编写本身的注解处理器,一个简单的实例代码以下:
@SupportedSourceVersion(SourceVersion.RELEASE_8) @SupportedAnnotationTypes("com.alipay.kris.other.lombok.*") public class MyAnnotaionProcessor extends AbstractProcessor { public MyAnnotaionProcessor() { super(); } @Override public boolean process(Set<? extends TypeElement> annotations,RoundEnvironment roundEnv) { for (Element elem : roundEnv.getElementsAnnotatedWith(MyAnnotation.class)) { MyAnnotation annotation = elem.getAnnotation(MyAnnotation.class); String message = "annotation found in " + elem.getSimpleName() + " with " + annotation.value(); addToString(elem); processingEnv.getMessager().printMessage(Diagnostic.Kind.NOTE, message); } return true; // no further processing of this annotation type } }
做者:猿码道连接:https://juejin.im/post/5a6eceb8f265da3e467555fe来源:掘金著做权归做者全部。商业转载请联系做者得到受权,非商业转载请注明出处。