Project Lombok是一个java库,可以自动插入到编辑器和构建工具中,为java增添情趣。不要再编写另一个getter或equals方法,只需一个注释,您的类就有一个功能齐全的构建器、自动化您的日志记录变量等等。(避免重复造轮子)
现有版本采用JSR 269规范(可插拔批注处里API)可以让我们修改编译过程,在编译期融入我们自己的东西,相比通过反射来获取注解,运行时代码效率降低等问题。所以在javac 解析成抽象语法树之后(AST),Lombok根据自己的注解处理器,动态修改AST,增加新的节点,最终通过生成字节码得以体现
优点:通过注解的形式生成构造器,getter/setter, equals, hascode, toString等方法,提高开发效率让代码变得简洁。
缺点:
根据 官网分为稳定版和实验版进行说明
通过maven导入Lombok (截至2022/12/1 最新)
org.projectlombok lombok 1.18.24 provided
// 使用 Lombok
val example = new ArrayList();
val foo = example.get(0);
// 生成class文件final ArrayList example = new ArrayList();final String foo = example.get(0);
// 使用Lombok
var example = new ArrayList();
var foo = example.get(0);
// 生成class文件ArrayList example = new ArrayList();String foo = example.get(0);
var 和 val 支持配置项
lombok.val.flagUsage = [warning | error] (默认: 未设置)
如果配置,Lombok会将val的任何使用标记为warning或error。
lombok.var.flagUsage = [warning | error] (默认: 未设置)
如果配置,Lombok会将var的任何使用标记为warning或error。
在不明确的情况下 初始化为null时会判断成java.lang.Object
对于复合类型,谨慎使用,避免与我们想象中的类型不一致 导致程序异常
// 使用Lombok
@NonNull Person person
// 生成class文件if (person == null) {throw new NullPointerException("person is marked non-null but is null");}
// 使用Lombok
@Cleanup InputStream in = new FileInputStream(args[0]);
@Cleanup OutputStream out = new FileOutputStream(args[1]);
// 生成class文件
InputStream in = new FileInputStream(args[0]);
try {OutputStream out = new FileOutputStream(args[1]);try {}} finally {if (out != null) {out.close();}}} finally {if (in != null) {in.close();}}
}
// 使用Lombok
@Getter @Setter private int age;
@Setter(AccessLevel.PROTECTED) private String name;
// 生成class文件/*** Age of the person. Water is wet.** @return The current value of this person's age. Circles are round.*/public int getAge() {return age;}/*** Age of the person. Water is wet.** @param age New value for this person's age. Sky is blue.*/public void setAge(int age) {this.age = age;}/*** Changes the name of this person.** @param name The new value.*/protected void setName(String name) {this.name = name;}
// 使用Lombok
import lombok.ToString;@ToString( includeFieldNames=false) // 给ToStringExample 生成toString方法
public class ToStringExample {private static final int STATIC_VAR = 10;private String name;private Shape shape = new Square(5, 10);private String[] tags;@ToString.Exclude private int id; // 给ToStringExample 生成toString方法中去除id属性public String getName() {return this.name;}@ToString(callSuper=true, includeFieldNames=true) // 实现toString方法输出父类中继承的属性 和 形式为fieldName = fieldValuepublic static class Square extends Shape {private final int width, height;public Square(int width, int height) {this.width = width;this.height = height;}}
}// 生成class文件import java.util.Arrays;public class ToStringExample {private static final int STATIC_VAR = 10;private String name;private Shape shape = new Square(5, 10);private String[] tags;private int id;public String getName() {return this.name;}public static class Square extends Shape {private final int width, height;public Square(int width, int height) {this.width = width;this.height = height;}@Override public String toString() {return "Square(super=" + super.toString() + ", width=" + this.width + ", height=" + this.height + ")";}}@Override public String toString() {return "ToStringExample(" + this.getName() + ", " + this.shape + ", " + Arrays.deepToString(this.tags) + ")";}
}
支持的配置项
lombok.toString.includeFieldNames = [true | false] (default: true)
lombok为每个字段生成一个toString响应的片段,形式为fieldName = fieldValue。如果这个设置为false,lombok将省略字段的名称,并简单地部署所有字段值的逗号分隔的列表。
lombok.toString.doNotUseGetters = [true | false] (default: false)
如果设置为true,lombok在生成toString方法时将直接访问字段而不是使用getters(如果有的话)。
lombok.toString.callSuper = [call | skip | warn] (default: skip)
如果设置为call,则如果您的类扩展了某些内容,lombok将生成对toString的父类实现的调用。如果设置为skip,则不会生成此父类调用。如果设置为warn,则也不会生成此父类调用,但lombok会生成警告来告诉您。
lombok.toString.onlyExplicitlyIncluded = [true | false] (default: false)
如果设置为false(默认),那么所有字段(除非static、name以$开头,或者由于明显的原因被排除在外)都将作为toString中包含的默认内容集.。
@ToString.Exclude 将该属性排除在外
@ToString.Include 将该属性包含在内
lombok.toString.flagUsage = [warning | error] (default: not set)
Lombok将@ToString的任何使用标记为警告或错误(如果已配置)。
//使用Lombokimport 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;}}
}
// 生成class文件
import java.util.Arrays;public class EqualsAndHashCodeExample {private transient int transientVar = 10;private String name;private double score;private Shape shape = new Square(5, 10);private String[] tags;private int id;public String getName() {return this.name;}@Override public boolean equals(Object o) {if (o == this) return true;if (!(o instanceof EqualsAndHashCodeExample)) return false;EqualsAndHashCodeExample other = (EqualsAndHashCodeExample) o;if (!other.canEqual((Object)this)) return false;if (this.getName() == null ? other.getName() != null : !this.getName().equals(other.getName())) return false;if (Double.compare(this.score, other.score) != 0) return false;if (!Arrays.deepEquals(this.tags, other.tags)) return false;return true;}@Override public int hashCode() {final int PRIME = 59;int result = 1;final long temp1 = Double.doubleToLongBits(this.score);result = (result*PRIME) + (this.name == null ? 43 : this.name.hashCode());result = (result*PRIME) + (int)(temp1 ^ (temp1 >>> 32));result = (result*PRIME) + Arrays.deepHashCode(this.tags);return result;}protected boolean canEqual(Object other) {return other instanceof EqualsAndHashCodeExample;}public static class Square extends Shape {private final int width, height;public Square(int width, int height) {this.width = width;this.height = height;}@Override public boolean equals(Object o) {if (o == this) return true;if (!(o instanceof Square)) return false;Square other = (Square) o;if (!other.canEqual((Object)this)) return false;if (!super.equals(o)) return false;if (this.width != other.width) return false;if (this.height != other.height) return false;return true;}@Override public int hashCode() {final int PRIME = 59;int result = 1;result = (result*PRIME) + super.hashCode();result = (result*PRIME) + this.width;result = (result*PRIME) + this.height;return result;}protected boolean canEqual(Object other) {return other instanceof Square;}}
}
// 使用Lombok
import lombok.AccessLevel;
import lombok.RequiredArgsConstructor;
import lombok.AllArgsConstructor;
import lombok.NonNull;@RequiredArgsConstructor(staticName = "of") // 生成该类下被final修饰或者non-null字段生成一个构造方法。
@AllArgsConstructor(access = AccessLevel.PROTECTED) // 构造方法的访问修饰符为PROTECTED 生成该类下全部属性的构造方法。
public class ConstructorExample {private int x, y;@NonNull private T description;@NoArgsConstructor //生成无参的构造方法。public static class NoArgsExample {@NonNull private String field;}
}// 生成class文件
public class ConstructorExample {private int x, y;@NonNull private T description;private ConstructorExample(T description) {if (description == null) throw new NullPointerException("description");this.description = description;}public static ConstructorExample of(T description) {return new ConstructorExample(description);}@java.beans.ConstructorProperties({"x", "y", "description"})protected ConstructorExample(int x, int y, T description) {if (description == null) throw new NullPointerException("description");this.x = x;this.y = y;this.description = description;}public static class NoArgsExample {@NonNull private String field;public NoArgsExample() {}}
}
重要场景:当一个bean类,注入其他bean的时候我们通常用@Autowired ,可以用@AllArgsConstructor或者@RequiredArgsConstructor来代替(实用)
当bean属性注入需要找类型为String名字是name的bean对象 需要使用@RequiredArgsConstructor 当使用@RequiredArgsConstructor 必须加上 final 或者 @NonNull修饰
特殊说明: 通常注解会有几个属性
生成的构造方法是私有的并且生成一个参数为final变量和@NonNull注解变量,返回类型为当前对象的静态方法 方法名为staticName 值
设置构造方法的访问修饰符,PUBLIC、MODULE、PROTECTED、PACKAGE、PRIVATE、NONE ,MODULE 是 Java 9 的新特性,NONE 表示不生成构造方法也不生成静态方法,即停用注解功能
列出的所有注解都放在生成的构造方法上
JDK 7 之前的写法是 onConstructor = @__({@Deprecated}),而 JDK 8 之后的写法是 onConstructor_ = {@Deprecated}
注在类上,提供类的get、set、equals、hashCode、canEqual、toString方法 合理使用,不要因为只用setter getter方法直接用 按需使用
// 使用 Lombok
import lombok.AccessLevel;
import lombok.Setter;
import lombok.Data;
import lombok.ToString;@Data public class DataExample {private final String name;@Setter(AccessLevel.PACKAGE) private int age; // Set方法 访问修饰方法为 providedprivate double score;private String[] tags;@ToString(includeFieldNames=true) // toString方法 以FieldName=FieldValue对应@Data(staticConstructor="of") // 构造方法为私有 并生成静态方法返回当前对象 方法名为staticConstructor值public static class Exercise {private final String name;private final T value;}
}
// 生成class文件import java.util.Arrays;public class DataExample {private final String name;private int age;private double score;private String[] tags;public DataExample(String name) {this.name = name;}public String getName() {return this.name;}void setAge(int age) {this.age = age;}public int getAge() {return this.age;}public void setScore(double score) {this.score = score;}public double getScore() {return this.score;}public String[] getTags() {return this.tags;}public void setTags(String[] tags) {this.tags = tags;}@Override public String toString() {return "DataExample(" + this.getName() + ", " + this.getAge() + ", " + this.getScore() + ", " + Arrays.deepToString(this.getTags()) + ")";}protected boolean canEqual(Object other) {return other instanceof DataExample;}@Override public boolean equals(Object o) {if (o == this) return true;if (!(o instanceof DataExample)) return false;DataExample other = (DataExample) o;if (!other.canEqual((Object)this)) return false;if (this.getName() == null ? other.getName() != null : !this.getName().equals(other.getName())) return false;if (this.getAge() != other.getAge()) return false;if (Double.compare(this.getScore(), other.getScore()) != 0) return false;if (!Arrays.deepEquals(this.getTags(), other.getTags())) return false;return true;}@Override public int hashCode() {final int PRIME = 59;int result = 1;final long temp1 = Double.doubleToLongBits(this.getScore());result = (result*PRIME) + (this.getName() == null ? 43 : this.getName().hashCode());result = (result*PRIME) + this.getAge();result = (result*PRIME) + (int)(temp1 ^ (temp1 >>> 32));result = (result*PRIME) + Arrays.deepHashCode(this.getTags());return result;}public static class Exercise {private final String name;private final T value;private Exercise(String name, T value) {this.name = name;this.value = value;}public static Exercise of(String name, T value) {return new Exercise(name, value);}public String getName() {return this.name;}public T getValue() {return this.value;}@Override public String toString() {return "Exercise(name=" + this.getName() + ", value=" + this.getValue() + ")";}protected boolean canEqual(Object other) {return other instanceof Exercise;}@Override public boolean equals(Object o) {if (o == this) return true;if (!(o instanceof Exercise)) return false;Exercise> other = (Exercise>) o;if (!other.canEqual((Object)this)) return false;if (this.getName() == null ? other.getValue() != null : !this.getName().equals(other.getName())) return false;if (this.getValue() == null ? other.getValue() != null : !this.getValue().equals(other.getValue())) return false;return true;}@Override public int hashCode() {final int PRIME = 59;int result = 1;result = (result*PRIME) + (this.getName() == null ? 43 : this.getName().hashCode());result = (result*PRIME) + (this.getValue() == null ? 43 : this.getValue().hashCode());return result;}}
}
作用于类 使所有的成员变量都是final 是 @ToString @EqualsAndHashCode @AllArgsConstructor @FieldDefaults(makeFinal = true, level = AccessLevel.PRIVATE) @Getter
在注解源码中只有一个属性
使生成的构造方法私有化 并生成一个返回类型为当前对象的无参静态方法,方法名为staticConstructor值
// 使用Lombokimport lombok.AccessLevel;
import lombok.experimental.NonFinal;
import lombok.experimental.Value;
import lombok.experimental.With;
import lombok.ToString;@Value public class ValueExample {String name;@With(AccessLevel.PACKAGE) @NonFinal int age; // With:生成方法名为with+属性名 返回全参构造方法的对象 修改当前属性的值 NonFinal:保持非final的字段double score;protected String[] tags;@ToString(includeFieldNames=true) // 生成ToString方法 以fieldname = fieldValue对应@Value(staticConstructor="of") // staticConstructor:构造方法为私有生成静态方法返回对象 方法名为staticConstructor值public static class Exercise {String name;T value;}
}
// 生成class类
import java.util.Arrays;public final class ValueExample {private final String name;private int age;private final double score;protected final String[] tags;@java.beans.ConstructorProperties({"name", "age", "score", "tags"})public ValueExample(String name, int age, double score, String[] tags) {this.name = name;this.age = age;this.score = score;this.tags = tags;}public String getName() {return this.name;}public int getAge() {return this.age;}public double getScore() {return this.score;}public String[] getTags() {return this.tags;}@java.lang.Overridepublic boolean equals(Object o) {if (o == this) return true;if (!(o instanceof ValueExample)) return false;final ValueExample other = (ValueExample)o;final Object this$name = this.getName();final Object other$name = other.getName();if (this$name == null ? other$name != null : !this$name.equals(other$name)) return false;if (this.getAge() != other.getAge()) return false;if (Double.compare(this.getScore(), other.getScore()) != 0) return false;if (!Arrays.deepEquals(this.getTags(), other.getTags())) return false;return true;}@java.lang.Overridepublic int hashCode() {final int PRIME = 59;int result = 1;final Object $name = this.getName();result = result * PRIME + ($name == null ? 43 : $name.hashCode());result = result * PRIME + this.getAge();final long $score = Double.doubleToLongBits(this.getScore());result = result * PRIME + (int)($score >>> 32 ^ $score);result = result * PRIME + Arrays.deepHashCode(this.getTags());return result;}@java.lang.Overridepublic String toString() {return "ValueExample(name=" + getName() + ", age=" + getAge() + ", score=" + getScore() + ", tags=" + Arrays.deepToString(getTags()) + ")";}ValueExample withAge(int age) {return this.age == age ? this : new ValueExample(name, age, score, tags);}public static final class Exercise {private final String name;private final T value;private Exercise(String name, T value) {this.name = name;this.value = value;}public static Exercise of(String name, T value) {return new Exercise(name, value);}public String getName() {return this.name;}public T getValue() {return this.value;}@java.lang.Overridepublic boolean equals(Object o) {if (o == this) return true;if (!(o instanceof ValueExample.Exercise)) return false;final Exercise> other = (Exercise>)o;final Object this$name = this.getName();final Object other$name = other.getName();if (this$name == null ? other$name != null : !this$name.equals(other$name)) return false;final Object this$value = this.getValue();final Object other$value = other.getValue();if (this$value == null ? other$value != null : !this$value.equals(other$value)) return false;return true;}@java.lang.Overridepublic int hashCode() {final int PRIME = 59;int result = 1;final Object $name = this.getName();result = result * PRIME + ($name == null ? 43 : $name.hashCode());final Object $value = this.getValue();result = result * PRIME + ($value == null ? 43 : $value.hashCode());return result;}@java.lang.Overridepublic String toString() {return "ValueExample.Exercise(name=" + getName() + ", value=" + getValue() + ")";}}
}
对初学者有些难度 理解上费劲些 熟能生巧
使用建造者模式: 用来生成对象 通过对象链式赋值
内部生成步骤:
作用于属性 想要这样来操作集合 需要使用
支持类型:java.util.Iterable,Collection, List
Set,SortedSet,NavigableSet
Map,SortedMap,NavigableMap
Guava’s com.google.common.collect:ImmutableCollection,ImmutableList,ImmutableSet,ImmutableSortedSet
ImmutableMap,ImmutableBiMap,ImmutableSortedMap,ImmutableTable
作用于属性,不需要初始化
// 使用Lombok
@Builder
public class User {private final Integer id;private final String zipCode = "123456";private String username;private String password;@Singularprivate List hobbies;
}
// 生成class
public class User {private final Integer id;private final String zipCode = "123456";private String username;private String password;private List hobbies;User(Integer id, String username, String password, List hobbies) {this.id = id; this.username = username;this.password = password; this.hobbies = hobbies;}public static User.UserBuilder builder() {return new User.UserBuilder();}public static class UserBuilder {private Integer id;private String username;private String password;private ArrayList hobbies;UserBuilder() {}public User.UserBuilder id(Integer id) { this.id = id; return this; }public User.UserBuilder username(String username) { this.username = username; return this; }public User.UserBuilder password(String password) { this.password = password; return this; }public User.UserBuilder hobby(String hobby) {if (this.hobbies == null) {this.hobbies = new ArrayList();}this.hobbies.add(hobby);return this;}public User.UserBuilder hobbies(Collection extends String> hobbies) {if (this.hobbies == null) {this.hobbies = new ArrayList();}this.hobbies.addAll(hobbies);return this;}public User.UserBuilder clearHobbies() {if (this.hobbies != null) {this.hobbies.clear();}return this;}public User build() {List hobbies;switch(this.hobbies == null ? 0 : this.hobbies.size()) {case 0:hobbies = Collections.emptyList();break;case 1:hobbies = Collections.singletonList(this.hobbies.get(0));break;default:hobbies = Collections.unmodifiableList(new ArrayList(this.hobbies));}return new User(this.id, this.username, this.password, hobbies);}public String toString() {return "User.UserBuilder(id=" + this.id + ", username=" + this.username + ", password=" + this.password + ", hobbies=" + this.hobbies + ")";}}
}
作用于方法 将当前方法抛出的异常,包装成RuntimeException,骗过编译器 使得调用点可以不用显示处理异常信息
// 使用Lombok
import lombok.SneakyThrows;public class SneakyThrowsExample implements Runnable {@SneakyThrows(UnsupportedEncodingException.class)public String utf8ToString(byte[] bytes) {return new String(bytes, "UTF-8");}@SneakyThrowspublic void run() {throw new Throwable();}
}
// 生成classimport lombok.Lombok;public class SneakyThrowsExample implements Runnable {public String utf8ToString(byte[] bytes) {try {return new String(bytes, "UTF-8");} catch (UnsupportedEncodingException e) {throw Lombok.sneakyThrow(e);}}public void run() {try {throw new Throwable();} catch (Throwable t) {throw Lombok.sneakyThrow(t);}}
}
作用于方法 锁住方法代码块 实现同步
// 使用Lombok
import lombok.Synchronized;public class SynchronizedExample {private final Object readLock = new Object();@Synchronizedpublic static void hello() {System.out.println("world");}@Synchronizedpublic int answerToLife() {return 42;}@Synchronized("readLock")public void foo() {System.out.println("bar");}
}
// 生成class
public class SynchronizedExample {private static final Object $LOCK = new Object[0];private final Object $lock = new Object[0];private final Object readLock = new Object();public static void hello() {synchronized($LOCK) {System.out.println("world");}}public int answerToLife() {synchronized($lock) {return 42;}}public void foo() {synchronized(readLock) {System.out.println("bar");}}
}
作用于类,生成多个with+变量名的方法(个数为所有成员变量 不包含@NonNull)
作用于变量 生成with+变量名的方法 返回当前对象 需要提供全参(不包含 静态变量)构造方法
// 使用Lombok
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(@NonNull String name, int age) {this.name = name;this.age = age;}
}
// 生成class
import lombok.NonNull;public class WithExample {private @NonNull final String name;private final int age;public WithExample(String name, int age) {if (name == null) throw new NullPointerException();this.name = name;this.age = age;}protected WithExample withName(@NonNull String name) {if (name == null) throw new java.lang.NullPointerException("name");return this.name == name ? this : new WithExample(name, age);}public WithExample withAge(int age) {return this.age == age ? this : new WithExample(name, age);}
}
Lombok 生成一个getter,第一次调用这个getter时计算一个值并从那时起缓存它。自动去管理线程安全的问题,不会存在重复赋值的问题,使用此功能,需要创建一个private final变量,并且使用运行成本高的表达式对其进行初始化
// 使用 Lombok
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;}
}
// 生成class
public class GetterLazyExample {private final java.util.concurrent.AtomicReference cached = new java.util.concurrent.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;}
}
生成一个logger字段
// 使用Lombokimport lombok.extern.java.Log;
import lombok.extern.slf4j.Slf4j;@Log
public class LogExample {public static void main(String... args) {log.severe("Something's wrong here");}
}@Slf4j
public class LogExampleOther {public static void main(String... args) {log.error("Something else is wrong here");}
}@CommonsLog(topic="CounterLog")
public class LogExampleCategory {public static void main(String... args) {log.error("Calling the 'CounterLog' with a message");}
}
// 生成classpublic class LogExample {private static final java.util.logging.Logger log = java.util.logging.Logger.getLogger(LogExample.class.getName());public static void main(String... args) {log.severe("Something's wrong here");}
}public class LogExampleOther {private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(LogExampleOther.class);public static void main(String... args) {log.error("Something else is wrong here");}
}public class LogExampleCategory {private static final org.apache.commons.logging.Log log = org.apache.commons.logging.LogFactory.getLog("CounterLog");public static void main(String... args) {log.error("Calling the 'CounterLog' with a message");}
}
可用于类及属性字段 用于生成getter和setter方法时的一些设置
属性
为true: 生成的getter方法忽略get,并且setter方法返回对象本身,getter方法返回属性类型。
为false: @Data默认的属性.即(默认为false 生成的为getUserName(),为true时为userName() )
为true: getter和setter方法和默认时一样,并且遵循驼峰命名,且setter方法返回的是对象本身,和Fient=true时返回类型一样
为false: @Data默认形式
属性值为String类型数组,意思就是比如prefix='user’且一个属性字段为String userName,则生成就为get方法:String getName();set方法:setName(String userName).
// 使用Lombokimport lombok.experimental.Accessors;
import lombok.Getter;
import lombok.Setter;@Accessors(fluent = true)
public class AccessorsExample {@Getter @Setterprivate int age = 10;
}class PrefixExample {@Accessors(prefix = "f") @Getterprivate String fName = "Hello, World!";
}
// 生成classpublic class AccessorsExample {private int age = 10;public int age() {return this.age;}public AccessorsExample age(final int age) {this.age = age;return this;}
}class PrefixExample {private String fName = "Hello, World!";public String getName() {return this.fName;}
}
作用于类 向类中添加方法 无需创建新的子类, 变量与方法参数,返回值类型必须一样
属性介绍
指定添加类
如果为 false,基础类型不能调用方法,默认为 true
如果 suppressBaseMethods = false
1、变量与方法参数、返回值的类型不能为基础类型
2、自定义方法不可与引用对象的方法重名(无法使用 变量.方法名)
// 使用Lombok@ExtensionMethod(value = LongYiYi.class, suppressBaseMethods = true)
public class QiaoXin {public static void main(String[] args) {int num = 0;num = num.aaa();System.out.println(num); // 输出结果为 1;"乔欣".print();List list = new ArrayList();list.add();}
}
class LongYiYi {public static int aaa(int num) {return ++num;}public static void print(String name) {System.out.println(name);}public static void add(List list) {list.add("龙一一");}
}// 生成class文件public class QiaoXin {public static void main(String[] args) {int num = 0;num = LongYiYi.aaa(num);System.out.println(num);LongYiYi.print("乔欣");List list = new ArrayList();LongYiYi.add(list);}
}
作用于类或枚举中的每个字段添加访问修饰符,为注释的类或枚举中的每个字段添加final
如果保持非final字段 可以用 @NonFinal
作用于实例字段中不添加final 需要使用@FieldDefaults(makeFinal=true)
@FieldDefaults(level=AccessLevel.PRIVATE)
任何还没有访问修饰符的字段(即任何看起来像包私有访问的字段)都被改变为具有适当的访问修饰符
任何必须保持包私有的字段都可以用@PackagePrivate
// 使用Lombok
import lombok.AccessLevel;
import lombok.experimental.FieldDefaults;
import lombok.experimental.NonFinal;
import lombok.experimental.PackagePrivate;@FieldDefaults(makeFinal=true, level=AccessLevel.PRIVATE)
public class FieldDefaultsExample {public final int a;int b;@NonFinal int c;@PackagePrivate int d;FieldDefaultsExample() {a = 0;b = 0;d = 0;}
}
// 生成class
public class FieldDefaultsExample {public final int a;private final int b;private int c;final int d;FieldDefaultsExample() {a = 0;b = 0;d = 0;}
}
任何字段或无参数方法都可以用@Delegate来注解,让lombok生成转发对这个字段的调用(或调用这个方法的结果)的委托方法。
// 使用Lombok
import java.util.ArrayList;
import java.util.Collection;import lombok.experimental.Delegate;public class DelegationExample {private interface SimpleCollection {boolean add(String item);boolean remove(Object item);}@Delegate(types=SimpleCollection.class)private final Collection collection = new ArrayList();
}class ExcludesDelegateExample {long counter = 0L;private interface Add {boolean add(String x);boolean addAll(Collection extends String> x);}@Delegate(excludes=Add.class)private final Collection collection = new ArrayList();public boolean add(String item) {counter++;return collection.add(item);}public boolean addAll(Collection extends String> col) {counter += col.size();return collection.addAll(col);}
}
// 生成class
import java.util.ArrayList;
import java.util.Collection;public class DelegationExample {private interface SimpleCollection {boolean add(String item);boolean remove(Object item);}private final Collection collection = new ArrayList();@java.lang.SuppressWarnings("all")public boolean add(final java.lang.String item) {return this.collection.add(item);}@java.lang.SuppressWarnings("all")public boolean remove(final java.lang.Object item) {return this.collection.remove(item);}
}class ExcludesDelegateExample {long counter = 0L;private interface Add {boolean add(String x);boolean addAll(Collection extends String> x);}private final Collection collection = new ArrayList();public boolean add(String item) {counter++;return collection.add(item);}public boolean addAll(Collection extends String> col) {counter += col.size();return collection.addAll(col);}@java.lang.SuppressWarnings("all")public int size() {return this.collection.size();}@java.lang.SuppressWarnings("all")public boolean isEmpty() {return this.collection.isEmpty();}@java.lang.SuppressWarnings("all")public boolean contains(final java.lang.Object arg0) {return this.collection.contains(arg0);}@java.lang.SuppressWarnings("all")public java.util.Iterator iterator() {return this.collection.iterator();}@java.lang.SuppressWarnings("all")public java.lang.Object[] toArray() {return this.collection.toArray();}@java.lang.SuppressWarnings("all")public T[] toArray(final T[] arg0) {return this.collection.toArray(arg0);}@java.lang.SuppressWarnings("all")public boolean remove(final java.lang.Object arg0) {return this.collection.remove(arg0);}@java.lang.SuppressWarnings("all")public boolean containsAll(final java.util.Collection> arg0) {return this.collection.containsAll(arg0);}@java.lang.SuppressWarnings("all")public boolean removeAll(final java.util.Collection> arg0) {return this.collection.removeAll(arg0);}@java.lang.SuppressWarnings("all")public boolean retainAll(final java.util.Collection> arg0) {return this.collection.retainAll(arg0);}@java.lang.SuppressWarnings("all")public void clear() {this.collection.clear();}
}
暂不介绍
作用于类 将类标记为final 并且类,内部类中的方法 字段 都标记为static
// 使用Lombok
import lombok.experimental.UtilityClass;@UtilityClass
public class UtilityClassExample {private final int CONSTANT = 5;public int addSomething(int in) {return in + CONSTANT;}
}
// 生成class
public final class UtilityClassExample {private static final int CONSTANT = 5;private UtilityClassExample() {throw new java.lang.UnsupportedOperationException("This is a utility class and cannot be instantiated");}public static int addSomething(int in) {return in + CONSTANT;}
}
作用于方法内部类,使内部类中的方法暴露在外面可以被直接调用
// 使用Lombok
import lombok.experimental.Helper;public class HelperExample {int someMethod(int arg1) {int localVar = 5;@Helper class Helpers {int helperMethod(int arg) {return arg + localVar;}}return helperMethod(10);}
}
// 生成class
public class HelperExample {int someMethod(int arg1) {int localVar = 5;class Helpers {int helperMethod(int arg) {return arg + localVar;}}Helpers $Helpers = new Helpers();return $Helpers.helperMethod(10);}
}
生成了一个内部类 Fields
// 使用Lombok
import lombok.experimental.FieldNameConstants;
import lombok.AccessLevel;@FieldNameConstants
public class FieldNameConstantsExample {private final String iAmAField;private final int andSoAmI;@FieldNameConstants.Exclude private final int asAmI;
}
// 生成class
public class FieldNameConstantsExample {private final String iAmAField;private final int andSoAmI;private final int asAmI;public static final class Fields {public static final String iAmAField = "iAmAField";public static final String andSoAmI = "andSoAmI";}
}
(慎用)
@Builder 的升级版,不支持对基类成员属性的构造
属性
builderMethodName:创建内部静态类的方法名,默认值为 builder
buildMethodName:创建实体类的方法名,默认值为 build
toBuilder:设置为 true 可以对这个对象进行拷贝生成新的对象,可以再修改,默认为 false
setterPrefix:setter 方法的前缀
注意事项
// 使用Lombok
@SuperBuilder
public class ParentClass {private final String a;private final String b;
}@SuperBuilder
public class ChildClass extends ParentClass{private final String c;
}
// 生成class
ChildClass.builder().a("testA").b("testB").c("testC").build();
任何方法或构造函数都可以用注释,@Tolerate并且lombok会像它不存在一样起作用。
缺点
难以支持递归委派
// 使用Lombok
import lombok.experimental.Tolerate;public class TolerateExample {@Setterprivate Date date;@Toleratepublic void setDate(String date) {this.date = Date.valueOf(date);}
}
// 生成class
public class TolerateExample {@Setterprivate Date date;public void setDateFromString(String date) {this.date = Date.valueOf(date);}
}
该@Jacksonized注释是一个附加注释的@Builder和@SuperBuilder。它会自动配置生成的生成器类,以供Jackson的反序列化使用。它只有在还存在a@Builder或a的上下文中出现时才起作用@SuperBuilder。否则会发出警告。
放置任何扩展了某些{@code java.lang.Throwable}类型的类,以添加4个常见异常构造函数
// 使用Lombok
import lombok.experimental.StandardException;@StandardException
public class ExampleException extends Exception {
}
// 生成classpublic class ExampleException extends Exception {public ExampleException() {this(null, null);}public ExampleException(String message) {this(message, null);}public ExampleException(Throwable cause) {this(cause != null ? cause.getMessage() : null, cause);}public ExampleException(String message, Throwable cause) {super(message);if (cause != null) super.initCause(cause);}
}