- pom.xml依赖及IDEA插件安装
- 注解概要说明
- 注解详细说明
引言:Lombok需要安装专门的插件及maven依赖,实现原理也很简单,将.java按照lombok方式进行编译,自动解析对应的注解做出不同的动作,这里不再讨论实现细节,只是简单说明各个稳定版本的注解的使用
1. pom.xml依赖及IDEA插件安装
- pom.xml依赖配置:
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.10</version>
</dependency>
-
idea 插件安装:
lombok插件
2.稳定版本注解概要说明
注解名称 | 注解作用域 | 注解说明 |
---|---|---|
val | 代替变量类型 | 自适应对应的变量类型,并将变量声明成final类型 |
var | 代替变量类型 | 自适应对应变量类型,与val不同不会将变量声明成final类型 |
@NonNull | 变量 | 判断该参数是否为null,如果是将抛出lombok异常 |
@Cleanup | 变量 | 将自动资源管理,安全调用你的close()方法 |
@Getter/@Setter | 变量、类 | 为类的全部字段或者变量生成getter/setter方法 |
@ToString | 类 | 生成toString方法(toString的子注解有些是作用于字段,比如@ToString.Exclude) |
@EqualsAndHashCode | 类 | 生成equals()和hashcode()的方法 |
@NoArgsConstructor/@RequiredArgsConstructor/@AllArgsConstructor | 类 | 生成无参构造方法,必填参数构造方法,及全参数构造方法 |
@Data | 类 | @ToString、@EqualsAndHashCode、@Getter/@Setter和@RequiredArgsConstructor集合 |
@Value | 类 | 不可变类的@Data注解 |
@Builder | 类 | 生成建造者模式方法 |
@SneakyThrows | 类 | 可用于不实际在方法的throws子句中声明而偷偷抛出已检查异常 |
@Getter(lazy=true) | 字段 | 对字段内容赋予一次初值 |
@Log | 类 | 代替繁杂的private static final Logger log = ..... |
3.注解详细说明
3.1 val
3.1.1 示例
通过val编写的java代码:
import java.util.ArrayList;
import java.util.HashMap;
import lombok.val;
public class ValExample {
public String example() {
val example = new ArrayList<String>();
example.add("Hello, World!");
val foo = example.get(0);
return foo.toLowerCase();
}
public void example2() {
val map = new HashMap<Integer, String>();
map.put(0, "zero");
map.put(5, "five");
for (val entry : map.entrySet()) {
System.out.printf("%d: %s\n", entry.getKey(), entry.getValue());
}
}
}
编译结果:
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
public class ValExample {
public String example() {
final ArrayList<String> example = new ArrayList<String>();
example.add("Hello, World!");
final String foo = example.get(0);
return foo.toLowerCase();
}
public void example2() {
final HashMap<Integer, String> map = new HashMap<Integer, String>();
map.put(0, "zero");
map.put(5, "five");
for (final Map.Entry<Integer, String> entry : map.entrySet()) {
System.out.printf("%d: %s\n", entry.getKey(), entry.getValue());
}
}
}
需要注意的是:这个特性在NetbBeans中不支持。
其实我自己编译的时候,并没有final关键字和var效果一致。。。
3.1.2 支持配置
lombok.val.flagUsage = [warning|error](默认为不设置)
如果配置上了val会被标记为(warning|error)
3.1.3 附属详细说明
- 对于混合的类型,最常见的是继承类,而非接口类。举个例子:bool?new HashSet() : new ArrayList()是一个混合类型的表达式,它们的结果既可以是AbstractCollection也可以是Serializable,然而类型的推测它是AbstractCollection,因为它是一个类,而Serializable是一个接口类
- 在模糊不清的例子中,如果初始化表达式是null,推导出来的结果就是java.lang.Object。
3.2 var
3.2.1 示例
和3.1.1一样,不再复述。
3.2.2 支持配置
lombok.var.flagUsage = [warning|error](默认为不设置)
如果配置上了var会被标记为(warning|error)
3.2.3 附属详细说明
- var的工作和val很相似,除了var是本地变量,不会被标记为final外。
- 类型仍然完全是从强制初始化器表达式派生的,任何进一步的赋值(虽然现在是合法的(因为变量不再是final)都不会查看以确定适当的类型。
- 例如,var x = "Hello";x = Color.RED;是不工作;x的类型将被推断为java.lang.String,因此,x =Color.RED分配将失败。如果x的类型被推断为java.lang.Object这个代码会被编译,但var不会很好的工作。
3.3 @NonNull
3.3.1 示例
- 代码片段1:直接作用于函数的变量上判断非空
- 代码片段2:结合@Data注解,如果被标记为@NonNull注解的字段将会成为必填字段,在构造函数中如果该字段为null抛出lombok异常。
代码片段1:
package study.lombok;
import lombok.Getter;
import lombok.NonNull;
import lombok.Setter;
/**
* @Author LynHB
* @Description : Lombok @NonNull注解测试
* @Date 20:23 2020/6/24
**/
public class NonNullAnnotation {
@Getter
@Setter
public class Person{
private String name;
private int age;
}
public void testPersonIsNull(@NonNull Person person){
System.out.println(person.getName());
}
public static void main(String[] args){
NonNullAnnotation nonNullAnnotation = new NonNullAnnotation();
nonNullAnnotation.testPersonIsNull(null);
}
}
编译结果1:
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//
package study.lombok;
import lombok.NonNull;
public class NonNullAnnotation {
public NonNullAnnotation() {
}
public void testPersonIsNull(@NonNull NonNullAnnotation.Person person) {
if (person == null) {
throw new NullPointerException("person is marked non-null but is null");
} else {
System.out.println(person.getName());
}
}
public static void main(String[] args) {
NonNullAnnotation nonNullAnnotation = new NonNullAnnotation();
nonNullAnnotation.testPersonIsNull((NonNullAnnotation.Person)null);
}
public class Person {
private String name;
private int age;
public Person() {
}
public String getName() {
return this.name;
}
public int getAge() {
return this.age;
}
public void setName(String name) {
this.name = name;
}
public void setAge(int age) {
this.age = age;
}
}
}
代码片段2:
package study.lombok;
import lombok.Data;
import lombok.Getter;
import lombok.NonNull;
import lombok.Setter;
/**
* @Author LynHB
* @Description : Lombok @NonNull注解测试
* @Date 20:23 2020/6/24
**/
public class NonNullAnnotation {
@Getter
@Setter
@Data
public static class Person{
@NonNull private String name;
private int age;
}
public void testPersonIsNull(Person person){
System.out.println(person.getName());
}
public static void main(String[] args){
NonNullAnnotation nonNullAnnotation = new NonNullAnnotation();
Person person = new Person(null);
nonNullAnnotation.testPersonIsNull(person);
}
}
编译结果2:
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//
package study.lombok;
import lombok.NonNull;
public class NonNullAnnotation {
public NonNullAnnotation() {
}
public void testPersonIsNull(NonNullAnnotation.Person person) {
System.out.println(person.getName());
}
public static void main(String[] args) {
NonNullAnnotation nonNullAnnotation = new NonNullAnnotation();
NonNullAnnotation.Person person = new NonNullAnnotation.Person((String)null);
nonNullAnnotation.testPersonIsNull(person);
}
public static class Person {
@NonNull
private String name;
private int age;
@NonNull
public String getName() {
return this.name;
}
public int getAge() {
return this.age;
}
public void setName(@NonNull String name) {
if (name == null) {
throw new NullPointerException("name is marked non-null but is null");
} else {
this.name = name;
}
}
public void setAge(int age) {
this.age = age;
}
public Person(@NonNull String name) {
if (name == null) {
throw new NullPointerException("name is marked non-null but is null");
} else {
this.name = name;
}
}
public boolean equals(Object o) {
if (o == this) {
return true;
} else if (!(o instanceof NonNullAnnotation.Person)) {
return false;
} else {
NonNullAnnotation.Person other = (NonNullAnnotation.Person)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 this.getAge() == other.getAge();
}
} else if (this$name.equals(other$name)) {
return this.getAge() == other.getAge();
}
return false;
}
}
}
protected boolean canEqual(Object other) {
return other instanceof NonNullAnnotation.Person;
}
public int hashCode() {
int PRIME = true;
int result = 1;
Object $name = this.getName();
int result = result * 59 + ($name == null ? 43 : $name.hashCode());
result = result * 59 + this.getAge();
return result;
}
public String toString() {
return "NonNullAnnotation.Person(name=" + this.getName() + ", age=" + this.getAge() + ")";
}
}
}
3.3.2 支持配置
- lombok.nonNull.exceptionType =NullPointerException | IllegalArrumentException|JDK|Guava|Assertion(默认为:NullPointerException)
- lombok.nonNull.flagUsage 同上
3.4 @Cleanup
3.4.1 示例
代码片段:
package study.lombok;
import lombok.Cleanup;
import java.io.*;
/**
* @Author LynHB
* @Description :
* @Date 21:03 2020/6/24
**/
public class CleanupExample {
public static void main(String[] args) throws IOException {
@Cleanup InputStream in = new FileInputStream(args[0]);
@Cleanup OutputStream out = new FileOutputStream(args[1]);
byte[] b = new byte[10000];
while (true) {
int r = in.read(b);
if (r == -1) break;
out.write(b, 0, r);
}
}
}
编译结果:
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//
package study.lombok;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Collections;
public class CleanupExample {
public CleanupExample() {
}
public static void main(String[] args) throws IOException {
FileInputStream in = new FileInputStream(args[0]);
try {
FileOutputStream out = new FileOutputStream(args[1]);
try {
byte[] b = new byte[10000];
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();
}
}
}
}
3.4.2 支持配置
- lombok.cleanup.flagUsage 同上
3.5 @Getter/@Setter
3.5.1 示例
- 通过Getter Setter注解进行生成getter和setter方法
- 在注解里可以设置对应方法的访问级别(public、protected、package、private)
代码片段:
package study.lombok;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.Setter;
/**
* @Author LynHB
* @Description : Getting Setting方法demo
* @Date 22:48 2020/6/24
**/
public class GetterSetterExample {
@Getter
@Setter
private int age = 10;
@Setter(AccessLevel.PROTECTED) private String name;
@Override public String toString() {
return String.format("%s (age: %d)", name, age);
}
}
编译结果:
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//
package study.lombok;
public class GetterSetterExample {
private int age = 10;
private String name;
public GetterSetterExample() {
}
public String toString() {
return String.format("%s (age: %d)", this.name, this.age);
}
public int getAge() {
return this.age;
}
public void setAge(int age) {
this.age = age;
}
protected void setName(String name) {
this.name = name;
}
}
3.5.2 支持配置
配置项 | 可选值 | 默认值 | 配置说明 |
---|---|---|---|
lombok.accessors.chain | true false | false | 如果设置为true,会返回this(代替viod)。显式的配置@Accessors注解chain会优先于此设置。 |
lombok.accessors.fluent | true false | false | 如果设置为true,不会生成'get' 'is' 'set'前缀,相反的是方法会用自身的字段名称作为函数名。显式的配置@Accessors注解fluent会优先于此设置。 |
lombok.accessors.prefix | +=自定义前缀字符串 | 空列表 | 这是一个列表属性;可以通过+=进行添加。继承父配置文件中的删除-=操作。Lombok将从字段名称中删除任何匹配的字段前缀,以便确定要生成的getter/setter的名称。例如,如果m是这个设置中列出的前缀之一,那么一个名为mFoobar的字段将导致一个名为getFoobar()的getter,而不是getMFoobar()。显式的配置@Accessors注解prefix会优先于此设置。 |
lombok.getter.noIsPrefix | true false | false | 如果设置为true,为boolean类型设置get前缀而非is前缀,所有生成的代码有调用到getters的地方,比如@ToString也会用get而不是is。 |
lombok.setter.flagUsage | warning error | 不设置 | 同其他注解 |
lombok.getter.flagUsage | warning eroor | 不设置 | 同其他注解 |
lombok.copyableAnnotations | 完全限定类型列表 | 空集合 | lombok将会拷贝这些注解从字段复制到setter参数和getter方法。注意lombok附带了一些开箱的注解,这些注解都可以复制,所有流行的可空/非空注解。 |
3.6 @ToString
3.6.1 示例
代码片段:
package study.lombok;
import lombok.ToString;
import java.awt.*;
/**
* @Author LynHB
* @Description : ToString注解测试
* @Date 13:26 2020/6/25
**/
@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;
public String getName() {
return this.name;
}
public static class Shape{
}
@ToString(callSuper=true, includeFieldNames=true)
public static class Square extends Shape {
private final int width, height;
public Square(int width, int height) {
this.width = width;
this.height = height;
}
}
}
编译结果:
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//
package study.lombok;
import java.util.Arrays;
public class ToStringExample {
private static final int STATIC_VAR = 10;
private String name;
private ToStringExample.Shape shape = new ToStringExample.Square(5, 10);
private String[] tags;
private int id;
public ToStringExample() {
}
public String getName() {
return this.name;
}
public String toString() {
return "ToStringExample(name=" + this.getName() + ", shape=" + this.shape + ", tags=" + Arrays.deepToString(this.tags) + ")";
}
public static class Square extends ToStringExample.Shape {
private final int width;
private final int height;
public Square(int width, int height) {
this.width = width;
this.height = height;
}
public String toString() {
return "ToStringExample.Square(super=" + super.toString() + ", width=" + this.width + ", height=" + this.height + ")";
}
}
public static class Shape {
public Shape() {
}
}
}
3.6.2 支持配置
配置项 | 可选值 | 默认值 | 配置说明 |
---|---|---|---|
lombok.toString.includeFieldNames | true false | true | 通常,lombok以fieldName = fieldValue的形式为每个字段生成toString响应的片段。如果设置成false,lombok将会省略名称字段,只部署一个逗号分隔的所有字段值列表。注解参数“includeFieldNames”,如果明确的指定,优先于此配置。 |
lombok.toString.doNotUseGetters | true false | false | 如果设置成true,lombok将会直接访问字段,跳过getters当生产生产toString方法时。这个注解参数“doNotUseGetters”,如果明确指定,则优先于此配置 |
lombok.toString.callSuper | call skip warn | skip | 如果设置成call,lombok将会调用父类实现的toString当你的类继承父类时。如果设置成skip,不会这调用。如果设置成warn,也没有生成这样的调用,但是lombok会生成一个警告来告诉你。 |
lombok.toString.flagUsage | warning error | 不设置 | 同其他注解 |
3.7 @EqualsAndHashCode
3.7.1 示例
3.7.2 支持配置
配置项 | 可选值 | 默认值 | 配置说明 |
---|
3.8 @NoArgsConstructor/@RequiredArgsConstructor/@AllArgsConstructor
3.8.1 示例
3.8.2 支持配置
配置项 | 可选值 | 默认值 | 配置说明 |
---|
3.9 @Data
3.9.1 示例
3.9.2 支持配置
配置项 | 可选值 | 默认值 | 配置说明 |
---|
3.10 @Value
3.10.1 示例
3.10.2 支持配置
配置项 | 可选值 | 默认值 | 配置说明 |
---|
3.11 @Builder
3.11.1 示例
3.11.2 支持配置
配置项 | 可选值 | 默认值 | 配置说明 |
---|
3.12 @SneakyThrows
3.12.1 示例
3.12.2 支持配置
配置项 | 可选值 | 默认值 | 配置说明 |
---|
3.13 @Getter(lazy=true)
3.13.1 示例
3.13.2 支持配置
配置项 | 可选值 | 默认值 | 配置说明 |
---|
3.14 @Log
你可以使用变量@Log在你的class中(保证对应的logging是你有用的,说白了就是你的依赖中要有它);之前的做法是你需要定义一个static final log的字段,初始化它各种巴拉巴拉的语句,现在只需要对应的@Log注解即可实现:
@CommonsLog
// 被翻译成如下
private static final org.apache.commons.logging.Log log = org.apache.commons.logging.LogFactory.getLog(LogExample.class);
@Flogger
// 被翻译成如下
private static final com.google.common.flogger.FluentLogger log = com.google.common.flogger.FluentLogger.forEnclosingClass();
@JBossLog
// 被翻译成如下
private static final org.jboss.logging.Logger log = org.jboss.logging.Logger.getLogger(LogExample.class);
@Log
// 被翻译成如下
private static final java.util.logging.Logger log = java.util.logging.Logger.getLogger(LogExample.class.getName());
@Log4j
// 被翻译成如下
private static final org.apache.log4j.Logger log = org.apache.log4j.Logger.getLogger(LogExample.class);
@Log4j2
// 被翻译成如下
private static final org.apache.logging.log4j.Logger log = org.apache.logging.log4j.LogManager.getLogger(LogExample.class);
@Slf4j
// 被翻译成如下
private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(LogExample.class);
@XSlf4j
// 被翻译成如下
private static final org.slf4j.ext.XLogger log = org.slf4j.ext.XLoggerFactory.getXLogger(LogExample.class);
@CustomLog
// 被翻译成如下
private static final com.foo.your.Logger log = com.foo.your.LoggerFactory.createYourLogger(LogExample.class);
3.14.1 示例
package study.dynamic.proxy.entity;
import lombok.extern.slf4j.Slf4j;
/**
* @Author LynHB
* @Description :
* Baby 实现来自IPerson接口的类
* @Date 23:17 2020/7/8
**/
@Slf4j
public class Baby implements IPerson {
@Override
public void eat(String dishName) {
log.info("mother feed me {}",dishName);
}
@Override
public void hungry() {
log.info("wa wa wa");
}
}
3.14.2 支持配置
配置项 | 可选值 | 默认值 | 配置说明 |
---|
网友评论