前言
Lombok是一款Java开发插件,使得Java开发者可以通过其定义的一些注解来消除业务工程中冗长和繁琐的代码,尤其对于简单的Java模型对象(POJO)。在开发环境中使用Lombok插件后,Java开发人员可以节省出重复构建,诸如hashCode和equals这样的方法以及各种业务对象模型的accessor和ToString等方法的大量时间。对于这些方法,它能够在编译源代码期间自动帮我们生成这些方法,并没有如反射那样降低程序的性能。
它所有的增强都是通过注解实现,所以了解其使用主要了解一下注解即可
注解列表
当前使用版本为2018年最新版本:
/
<dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <scope>provided</scope> <version>1.18.2-RELEASE</version> </dependency>
先介绍这一波最常用的注解:
@NoArgsConstructor/@RequiredArgsConstructor /@AllArgsConstructor
这三个注解都是用在类上的,第一个和第三个都很好理解,就是为该类产生无参的构造方法和包含所有参数的构造方法,第二个注解则使用类中所有带有@NonNull注解的或者带有final修饰的成员变量生成对应的构造方法,当然,和前面几个注解一样,成员变量都是非静态的。另外,如果类中含有final修饰的成员变量,是无法使用@NoArgsConstructor注解的。
三个注解都可以指定生成的构造方法的访问权限,还可指定生成一个静态方法
使用案例:
@AllArgsConstructor public class Demo { private String name; private int age; } @AllArgsConstructor class Parent { private Integer id; }
编译后的两个class文件如下:
public class Demo { private String name; private int age; public Demo(String name, int age) { this.name = name; this.age = age; } } //第二个类 class Parent { private Integer id; public Parent(Integer id) { this.id = id; } }
由此课件,此注解并不会把父类的属性id拿到Demo的构造器里面去,这是需要注意的地方。并且它也没有默认的构造器了
@AllArgsConstructor(access = AccessLevel.PROTECTED, staticName = "test") public class Demo { private final int finalVal = 10; private String name; private int age; }
生成如下:
public class Demo { private final int finalVal = 10; private String name; private int age; private Demo(String name, int age) { this.name = name; this.age = age; } protected static Demo test(String name, int age) { return new Demo(name, age); } }
看出来的效果为:可以指定生成的构造器的访问权限。但是,但是如果指定了一个静态方法,那么构造器会自动会被private,只通过静态方法对外提供反问,并且我们发现final的属性值,是不会放进构造函数里面的。
NoArgsConstructor的使用方式同上,RequiredArgsConstructor看看效果:
@RequiredArgsConstructor public class Demo { private final int finalVal = 10; @NonNull private String name; @NonNull private int age; }
编译后:
public class Demo { private final int finalVal = 10; @NonNull private String name; @NonNull private int age; public Demo(@NonNull String name, @NonNull int age) { if (name == null) { throw new NullPointerException("name is marked @NonNull but is null"); } else { this.name = name; this.age = age; } } }
解释:该注解会识别@nonNull字段,然后以该字段为元素产生一个构造函数。备注:如果所有字段都没有@nonNull注解,那效果同NoArgsConstructor
@Builder 提供了一种比较推崇的构建值对象的方式
非常推荐的一种构建值对象的方式。缺点就是父类的属性不能产于builder
@Builder public class Demo { private final int finalVal = 10; private String name; private int age; }
编译后
public class Demo { private final int finalVal = 10; private String name; private int age; Demo(String name, int age) { this.name = name; this.age = age; } public static Demo.DemoBuilder builder() { return new Demo.DemoBuilder(); } public static class DemoBuilder { private String name; private int age; DemoBuilder() { } public Demo.DemoBuilder name(String name) { this.name = name; return this; } public Demo.DemoBuilder age(int age) { this.age = age; return this; } public Demo build() { return new Demo(this.name, this.age); } public String toString() { String var10000 = this.name; return this.age; } } }
因此我们构造一个对象就可以优雅的这么来
public static void main(String[] args) { Demo demo = Demo.builder().name("aa").age(10).build(); System.out.println(demo); }
里面有一些自定义参数,我表示,完全没有必要去自定义。
@Cleanup 能够自动释放资源
这个注解用在变量前面,可以保证此变量代表的资源会被自动关闭,默认是调用资源的close()方法。如果该资源有其它关闭方法,可使用@Cleanup(“methodName”)来指定要调用的方法,就用输入输出流来举个例子吧:
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(b); if (r == -1) break; out.write(b, 0, r); } }
编译后:
public static void main(String[] args) throws Exception { FileInputStream in = new FileInputStream(args[0]); try { FileOutputStream out = new FileOutputStream(args[1]); try { byte[] b = new byte[1024]; while(true) { int r = in.read(b); if (r == -1) { return; } out.write(b, 0, r); } } finally { if (Collections.singletonList(out).get(0) != null) { out.close(); } } } finally { if (Collections.singletonList(in).get(0) != null) { in.close(); } } }
就这么简单的一个注解,就实现了优雅的关流操作哟。
@Data 强悍的组合功能包
相当于注解集合。效果等同于**@Getter + @Setter + @ToString + @EqualsAndHashCode + @RequiredArgsConstructor** 由于生成的代码篇幅太长,这里就不给demo了,反正效果同上5个注解的效果,强悍
需要注意的是,这里不包括@NoArgsConstructor和@AllArgsConstructor
@Value注解和@Data类似,区别在于它会把所有成员变量默认定义为private final修饰,并且不会生成set方法。
所以@Value更适合只读性更强的类,所以特殊情况下,还是可以使用的。