简介
Lombok是一款Java代码功能增强库,它会自动集成到你的编辑器和构建工具中,从而使你的Java代码更加生动有趣。通过Lombok的注解,你可以不用再写getter、setter、equals等方法,Lombok将在编译时为你自动生成。
集成
首先我们需要在IDEA中安装好Lombok插件,如果你使用的是最新版IDEA 2020.3,则Lombok插件已经内置,无需安装。
maven依赖
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.16</version>
</dependency>
用例一:@val
使用val注解可以取代任意类型作为局部变量
@Test
public void valExample() {
// 1.使用@val注解可以取代任意类型作为局部变量
val val = new ArrayList<String>(16);
val.add("1");
val.add("2");
String s = val.get(1);
System.out.println(s);
System.out.println(val);
}
用例二: @NonNull
在方法上使用@NonNull注解可以做非空判断,如果传入空值的话会直接抛出NullPointerException。
@Test
public void nonNullExample() {
// 2.@NonNull的使用,直接会报空指针,原因是编译后的class会直接加上非空判断
String name = null;
notNullExample(name);
}
private static void notNullExample(@NonNull String name) {
System.out.println(name);
}
编译后的class
@Test
public void nonNullExample() {
String name = null;
notNullExample((String)name);
}
private static void notNullExample(@NonNull String name) {
if (name == null) {
throw new NullPointerException("name is marked non-null but is null");
} else {
System.out.println(name);
}
}
用例三:@Cleanup
当我们在Java中使用资源时,不可避免地需要在使用后关闭资源。使用@Cleanup注解可以自动关闭资源。
/**
* @author liumf
* 使用输入输出流自动关闭,无需编写try catch和调用close()方法
* class 文件编译后会自动生成finally释放资源
* @throws IOException
*/
@Test
public void CleanupExample() throws Exception {
String inStr = "Hello World!";
//使用输入输出流自动关闭,无需编写try catch和调用close()方法
@Cleanup ByteArrayInputStream in = new ByteArrayInputStream(inStr.getBytes("UTF-8"));
@Cleanup ByteArrayOutputStream out = new ByteArrayOutputStream();
byte[] b = new byte[1024];
while (true) {
int r = in.read(b);
if (r == -1) break;
out.write(b, 0, r);
}
String outStr = out.toString("UTF-8");
System.out.println(outStr);
}
编译后的class
@Test
public void CleanupExample() throws Exception {
String inStr = "Hello World!";
ByteArrayInputStream in = new ByteArrayInputStream(inStr.getBytes("UTF-8"));
try {
ByteArrayOutputStream out = new ByteArrayOutputStream();
try {
byte[] b = new byte[1024];
while(true) {
int r = in.read(b);
if (r == -1) {
String outStr = out.toString("UTF-8");
System.out.println(outStr);
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();
}
}
}
用例四:@Builder
使用@Builder注解可以通过建造者模式来创建对象,建造者模式加链式调用,创建对象太方便了!
/**
* 使用@Builder注解可以通过建造者模式来创建对象,建造者模式加链式调用,创建对象太方便了!
* 注意最后要加上.build()
*/
@Test
public void buildExample(){
User user = User.builder()
.name("liu")
.pwd("xy").build();
notNullProperty(user);
}
private static void notNullProperty(@NonNull User user) {
System.out.println(user);
}
用例五:@SneakyThrows
给手动抛出异常sayNo
/**
* 手动抛出异常??????试试@SneakyThrows
*/
@Test
public void neakyThrowsExample() {
String str = "Hello World!";
System.out.println(str2byte(str).length);
}
//自动抛出异常,无需处理
@SneakyThrows(UnsupportedEncodingException.class)
public byte[] str2byte(String str) {
return str.getBytes("UTF-8");
}
编译后的class
@Test
public void neakyThrowsExample() {
String str = "Hello World!";
System.out.println(this.str2byte(str).length);
}
public byte[] str2byte(String str) {
try {
return str.getBytes("UTF-8");
} catch (UnsupportedEncodingException var3) {
throw var3;
}
}
用例六:@Synchronized
当我们在多个线程中访问同一资源时,往往会出现线程安全问题,以前我们往往使用synchronized关键字修饰方法来实现同步访问。使用@Synchronized注解同样可以实现同步访问。
private static LombokExample lombokExample;
private LombokExample() {
}
@Synchronized
public static LombokExample getLombokExample(){
// if (lombokExample == null){
synchronized (LombokExample.class){
if (lombokExample ==null){
lombokExample = new LombokExample();
}
}
// }
return lombokExample;
}
编译后的class
private static LombokExample lombokExample;
private LombokExample() {
}
public static LombokExample getLombokExample() {
synchronized($LOCK) {
Class var1 = LombokExample.class;
synchronized(LombokExample.class) {
if (lombokExample == null) {
lombokExample = new LombokExample();
}
}
return lombokExample;
}
}
用例七:@With
使用@With注解可以实现对原对象进行克隆,并改变其一个属性,使用时需要指定全参构造方法。
/**
* @With注解
* 实现对象clone
* @Log4j 打印日志
* @param args
*/
public static void main(String[] args) {
Student student1 = new Student("liu", "15");
System.out.println(student1);
Student student2 = student1.withAge("19");
log.error("xxxxx");
System.out.println(student2);
}
用例八:@Getter(lazy=true)
当我们获取某一个属性比较消耗资源时,可以给@Getter添加lazy=true
属性实现懒加载,会生成Double Check Lock 样板代码对属性进行懒加载。
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;
}
public static void main(String[] args) {
//使用Double Check Lock 样板代码对属性进行懒加载
GetterLazyExample example = new GetterLazyExample();
System.out.println(example.getCached().length);
}
}
用例九:@Log、@Log4j、@Log4j2、@Slf4
@Slf4j
public class LogSlf4jExample {
public static void main(String[] args) {
log.info("level:{}","info");
log.warn("level:{}","warn");
log.error("level:{}", "error");
}
}
编译后的class
public class LogSlf4jExample {
private static final Logger log = LoggerFactory.getLogger(LogSlf4jExample.class);
public LogSlf4jExample() {
}
public static void main(String[] args) {
log.info("level:{}", "info");
log.warn("level:{}", "warn");
log.error("level:{}", "error");
}
}
用例十:@Value
使用@Value注解可以把类声明为不可变的,声明后此类相当于final类,无法被继承,其属性也会变成final属性。
package lombok.pojo;
import lombok.AllArgsConstructor;
import lombok.ToString;
import lombok.Value;
import lombok.With;
import lombok.extern.java.Log;
import lombok.extern.log4j.Log4j;
import org.junit.Test;
/**
* @author liumf
* @date 22:41 2020/12/23
* @className Student
* @description
*/
@AllArgsConstructor
@With
@ToString
@Log4j
@Value
public class Student {
private String name;
private String age;
/**
* @With注解
* 实现对象clone
* @Log4j 打印日志
* @param args
*/
public static void main(String[] args) {
Student student1 = new Student("liu", "15");
System.out.println(student1);
Student student2 = student1.withAge("19");
log.error("xxxxx");
System.out.println(student2);
}
}
编译后的class
public final class Student {
private static final Logger log = Logger.getLogger(Student.class);
private final String name;
private final String age;
public static void main(String[] args) {
Student student1 = new Student("liu", "15");
System.out.println(student1);
Student student2 = student1.withAge("19");
log.error("xxxxx");
System.out.println(student2);
}
用例十一:@Getter/@Setter @ToString @EqualsAndHashCode
- @Getter/@Setter注解,我们再也不用编写getter/setter方法了
- 使用@ToString注解可以自动生成toString方法,默认会包含所有类属性,使用@ToString.Exclude注解可以排除属性的生成。
- 使用@EqualsAndHashCode注解可以自动生成hashCode和equals方法,默认包含所有类属性,使用@EqualsAndHashCode.Exclude可以排除属性的生成。
/**
* @ToString
*
*/
public class ToStringExample {
private Long id;
private String name;
private Integer age;
public ToStringExample(Long id, String name, Integer age) {
this.id = id;
this.name = name;
this.age = age;
}
public String toString() {
return "ToStringExample(name=" + this.name + ", age=" + this.age + ")";
}
}
/**
* @EqualsAndHashCode
*
*/
@Getter
@Setter
@EqualsAndHashCode
public class EqualsAndHashCodeExample {
private Long id;
@EqualsAndHashCode.Exclude
private String name;
@EqualsAndHashCode.Exclude
private Integer age;
public static void main(String[] args) {
EqualsAndHashCodeExample example1 = new EqualsAndHashCodeExample();
example1.setId(1L);
example1.setName("test");
example1.setAge(20);
EqualsAndHashCodeExample example2 = new EqualsAndHashCodeExample();
example2.setId(1L);
//equals方法只对比id,返回true
System.out.println(example1.equals(example2));
}
}
编译后的class
public class User {
private String name;
private String pwd;
public static void main(String[] args) {
LombokExample lombokExample = LombokExample.getLombokExample();
System.out.println(lombokExample);
}
public static User.UserBuilder builder() {
return new User.UserBuilder();
}
public User withName(String name) {
return this.name == name ? this : new User(name, this.pwd);
}
public User withPwd(String pwd) {
return this.pwd == pwd ? this : new User(this.name, pwd);
}
public String getName() {
return this.name;
}
public String getPwd() {
return this.pwd;
}
public void setName(String name) {
this.name = name;
}
public void setPwd(String pwd) {
this.pwd = pwd;
}
public boolean equals(Object o) {
if (o == this) {
return true;
} else if (!(o instanceof User)) {
return false;
} else {
User other = (User)o;
if (!other.canEqual(this)) {
return false;
} else {
Object this$name = this.getName();
Object other$name = other.getName();
if (this$name == null) {
if (other$name != null) {
return false;
}
} else if (!this$name.equals(other$name)) {
return false;
}
Object this$pwd = this.getPwd();
Object other$pwd = other.getPwd();
if (this$pwd == null) {
if (other$pwd != null) {
return false;
}
} else if (!this$pwd.equals(other$pwd)) {
return false;
}
return true;
}
}
}
protected boolean canEqual(Object other) {
return other instanceof User;
}
public int hashCode() {
int PRIME = true;
int result = 1;
Object $name = this.getName();
int result = result * 59 + ($name == null ? 43 : $name.hashCode());
Object $pwd = this.getPwd();
result = result * 59 + ($pwd == null ? 43 : $pwd.hashCode());
return result;
}
public String toString() {
return "User(name=" + this.getName() + ", pwd=" + this.getPwd() + ")";
}
public User(String name, String pwd) {
this.name = name;
this.pwd = pwd;
}
public static class UserBuilder {
private String name;
private String pwd;
UserBuilder() {
}
public User.UserBuilder name(String name) {
this.name = name;
return this;
}
public User.UserBuilder pwd(String pwd) {
this.pwd = pwd;
return this;
}
public User build() {
return new User(this.name, this.pwd);
}
public String toString() {
return "User.UserBuilder(name=" + this.name + ", pwd=" + this.pwd + ")";
}
}
}
用例十一:@XxConstructor
使用@XxConstructor注解可以自动生成构造方法,有@NoArgsConstructor、@RequiredArgsConstructor和@AllArgsConstructor三个注解可以使用。
- @NoArgsConstructor:生成无参构造函数。
- @RequiredArgsConstructor:生成包含必须参数的构造函数,使用@NonNull注解的类属性为必须参数。
- @AllArgsConstructor:生成包含所有参数的构造函数
@NoArgsConstructor
@RequiredArgsConstructor(staticName = "of")
@AllArgsConstructor
public class ConstructorExample {
@NonNull
private Long id;
private String name;
private Integer age;
public static void main(String[] args) {
//无参构造器
ConstructorExample example1 = new ConstructorExample();
//全部参数构造器
ConstructorExample example2 = new ConstructorExample(1L,"test",20);
//@NonNull注解的必须参数构造器
ConstructorExample example3 = ConstructorExample.of(1L);
}
}
编译后的class
public class ConstructorExample {
@NonNull
private Long id;
private String name;
private Integer age;
public ConstructorExample() {
}
private ConstructorExample(@NonNull final Long id) {
if (id == null) {
throw new NullPointerException("id is marked non-null but is null");
} else {
this.id = id;
}
}
public static ConstructorExample of(@NonNull final Long id) {
return new ConstructorExample(id);
}
public ConstructorExample(@NonNull final Long id, final String name, final Integer age) {
if (id == null) {
throw new NullPointerException("id is marked non-null but is null");
} else {
this.id = id;
this.name = name;
this.age = age;
}
}
}
用例十一:@Data
@Data是一个方便使用的组合注解,是@ToString、@EqualsAndHashCode、@Getter、@Setter和@RequiredArgsConstructor的组合体。
编译后
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//
package lombok.pojo;
import org.apache.log4j.Logger;
public final class Student {
private static final Logger log = Logger.getLogger(Student.class);
private final String name;
private final String age;
public static void main(String[] args) {
Student student1 = new Student("liu", "15");
System.out.println(student1);
Student student2 = student1.withAge("19");
log.error("xxxxx");
System.out.println(student2);
}
public String getName() {
return this.name;
}
public String getAge() {
return this.age;
}
public boolean equals(Object o) {
if (o == this) {
return true;
} else if (!(o instanceof Student)) {
return false;
} else {
Student other = (Student)o;
Object this$name = this.getName();
Object other$name = other.getName();
if (this$name == null) {
if (other$name != null) {
return false;
}
} else if (!this$name.equals(other$name)) {
return false;
}
Object this$age = this.getAge();
Object other$age = other.getAge();
if (this$age == null) {
if (other$age != null) {
return false;
}
} else if (!this$age.equals(other$age)) {
return false;
}
return true;
}
}
public int hashCode() {
int PRIME = true;
int result = 1;
Object $name = this.getName();
int result = result * 59 + ($name == null ? 43 : $name.hashCode());
Object $age = this.getAge();
result = result * 59 + ($age == null ? 43 : $age.hashCode());
return result;
}
public Student(String name, String age) {
this.name = name;
this.age = age;
}
public Student withName(String name) {
return this.name == name ? this : new Student(name, this.age);
}
public Student withAge(String age) {
return this.age == age ? this : new Student(this.name, age);
}
public String toString() {
return "Student(name=" + this.getName() + ", age=" + this.getAge() + ")";
}
}