首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >效率提高 10 倍 !一份不可多得的 Lombok 学习指南

效率提高 10 倍 !一份不可多得的 Lombok 学习指南

作者头像
Bug开发工程师
发布2019-12-02 16:06:48
8590
发布2019-12-02 16:06:48
举报
文章被收录于专栏:码农沉思录码农沉思录

一、Lombok 简介

Lombok 是一款 Java 开发插件,使得 Java 开发者可以通过其定义的一些注解来消除业务工程中冗长和繁琐的代码,尤其对于简单的 Java 模型对象(POJO)。在开发环境中使用 Lombok 插件后,Java 开发人员可以节省出重复构建,诸如 hashCode 和 equals 这样的方法以及各种业务对象模型的 accessor 和 toString 等方法的大量时间。对于这些方法,Lombok 能够在编译源代码期间自动帮我们生成这些方法,但并不会像反射那样降低程序的性能。

二、Lombok 安装

2.1 构建工具
Gradle

build.gradle 文件中添加 lombok 依赖:

dependencies {
    compileOnly 'org.projectlombok:lombok:1.18.10'
    annotationProcessor 'org.projectlombok:lombok:1.18.10'
}

Maven

在 Maven 项目的 pom.xml 文件中添加 lombok 依赖:

<dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <version>1.18.10</version>
        <scope>provided</scope>
</dependency>
Ant

假设在 lib 目录中已经存在 lombok.jar,然后设置 javac 任务:

<javac srcdir="src" destdir="build" source="1.8">
    <classpath location="lib/lombok.jar" />
</javac>
2.2 IDE

由于 Lombok 仅在编译阶段生成代码,所以使用 Lombok 注解的源代码,在 IDE 中会被高亮显示错误,针对这个问题可以通过安装 IDE 对应的插件来解决。这里不详细展开,具体的安装方式可以参考 Setting up Lombok with Eclipse and IntelliJ 这篇文章。

三、Lombok 详解

注意:以下示例所使用的 Lombok 版本是 1.18.10

3.1 @Getter and @Setter 注解

你可以使用 @Getter@Setter 注释任何类或字段,Lombok 会自动生成默认的 getter/setter 方法。

@Getter 注解
@Target({ElementType.FIELD, ElementType.TYPE})
@Retention(RetentionPolicy.SOURCE)
public @interface Getter {
  
    lombok.AccessLevel value() default lombok.AccessLevel.PUBLIC;
    AnyAnnotation[] onMethod() default {};
  
    boolean lazy() default false;
}
@Setter 注解
@Target({ElementType.FIELD, ElementType.TYPE})
@Retention(RetentionPolicy.SOURCE)
public @interface Setter {
  
    lombok.AccessLevel value() default lombok.AccessLevel.PUBLIC;
    AnyAnnotation[] onMethod() default {};
    AnyAnnotation[] onParam() default {};
}
使用示例
package com.semlinker.lombok;

@Getter
@Setter
public class GetterAndSetterDemo {
    String firstName;
    String lastName;
    LocalDate dateOfBirth;
}
以上代码经过 Lombok 编译后,会生成如下代码:
package com.semlinker.lombok;

public class GetterAndSetterDemo {
    String firstName;
    String lastName;
    LocalDate dateOfBirth;

    public GetterAndSetterDemo() {
    }

    
    public String getFirstName() {
        return this.firstName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }
}
Lazy Getter

@Getter 注解支持一个 lazy 属性,该属性默认为 false。当设置为 true 时,会启用延迟初始化,即当首次调用 getter 方法时才进行初始化。

Tips:关注微信公众号:Java后端,每日获取博文的推送。

示例
package com.semlinker.lombok;

public class LazyGetterDemo {
    public static void main(String[] args) {
        LazyGetterDemo m = new LazyGetterDemo();
        System.out.println("Main instance is created");
        m.getLazy();
    }

    @Getter
    private final String notLazy = createValue("not lazy");

    @Getter(lazy = true)
    private final String lazy = createValue("lazy");

    private String createValue(String name) {
        System.out.println("createValue(" + name + ")");
        return null;
    }
}
以上代码经过 Lombok 编译后,会生成如下代码:
package com.semlinker.lombok;

public class LazyGetterDemo {
    private final String notLazy = this.createValue("not lazy");
    private final AtomicReference<Object> lazy = new AtomicReference();

    
    public String getNotLazy() {
        return this.notLazy;
    }

    public String getLazy() {
        Object value = this.lazy.get();
        if (value == null) {
            synchronized(this.lazy) {
                value = this.lazy.get();
                if (value == null) {
                    String actualValue = this.createValue("lazy");
                    value = actualValue == null ? this.lazy : actualValue;
                    this.lazy.set(value);
                }
            }
        }

        return (String)((String)(value == this.lazy ? null : value));
    }
}

通过以上代码可知,调用 getLazy 方法时,若发现 value 为 null,则会在同步代码块中执行初始化操作。

3.2 Constructor Annotations
@NoArgsConstructor 注解

使用 @NoArgsConstructor 注解可以为指定类,生成默认的构造函数,@NoArgsConstructor 注解的定义如下:

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.SOURCE)
public @interface NoArgsConstructor {
  
    String staticName() default "";
    AnyAnnotation[] onConstructor() default {};
  
    AccessLevel access() default lombok.AccessLevel.PUBLIC;
  
    boolean force() default false;
}
示例
package com.semlinker.lombok;

@NoArgsConstructor(staticName = "getInstance")
public class NoArgsConstructorDemo {
    private long id;
    private String name;
    private int age;
}

以上代码经过 Lombok 编译后,会生成如下代码:

package com.semlinker.lombok;

public class NoArgsConstructorDemo {
    private long id;
    private String name;
    private int age;

    private NoArgsConstructorDemo() {
    }

    public static NoArgsConstructorDemo getInstance() {
        return new NoArgsConstructorDemo();
    }
}
@AllArgsConstructor 注解

使用 @AllArgsConstructor 注解可以为指定类,生成包含所有成员的构造函数,@AllArgsConstructor 注解的定义如下:

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.SOURCE)
public @interface AllArgsConstructor {
  
    String staticName() default "";
    AnyAnnotation[] onConstructor() default {};
  
    AccessLevel access() default lombok.AccessLevel.PUBLIC;
}
示例
package com.semlinker.lombok;

@AllArgsConstructor
public class AllArgsConstructorDemo {
    private long id;
    private String name;
    private int age;
}

以上代码经过 Lombok 编译后,会生成如下代码:

package com.semlinker.lombok;

public class AllArgsConstructorDemo {
    private long id;
    private String name;
    private int age;

    public AllArgsConstructorDemo(long id, String name, int age) {
        this.id = id;
        this.name = name;
        this.age = age;
    }
}
@RequiredArgsConstructorDemo 注解

使用 @RequiredArgsConstructor 注解可以为指定类必需初始化的成员变量,如 final 成员变量,生成对应的构造函数,@RequiredArgsConstructor 注解的定义如下:

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.SOURCE)
public @interface RequiredArgsConstructor {
  
    String staticName() default "";
    AnyAnnotation[] onConstructor() default {};
  
    AccessLevel access() default lombok.AccessLevel.PUBLIC;
}
示例
package com.semlinker.lombok;

@RequiredArgsConstructor
public class RequiredArgsConstructorDemo {
    private final long id;
    private String name;
    private int age;
}

以上代码经过 Lombok 编译后,会生成如下代码:

package com.semlinker.lombok;

public class RequiredArgsConstructorDemo {
    private final long id;
    private String name;
    private int age;

    public RequiredArgsConstructorDemo(long id) {
        this.id = id;
    }
}
3.3 @EqualsAndHashCode 注解

使用 @EqualsAndHashCode 注解可以为指定类生成 equals 和 hashCode 方法, @EqualsAndHashCode 注解的定义如下:

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.SOURCE)
public @interface EqualsAndHashCode {
  
    String[] exclude() default {};

    String[] of() default {};
  
    boolean callSuper() default false;
    
    boolean doNotUseGetters() default false;
    
    AnyAnnotation[] onParam() default {};
    
    @Deprecated
    @Retention(RetentionPolicy.SOURCE)
    @Target({})
    @interface AnyAnnotation {}
    
    @Target(ElementType.FIELD)
    @Retention(RetentionPolicy.SOURCE)
    public @interface Exclude {}
    
    @Target({ElementType.FIELD, ElementType.METHOD})
    @Retention(RetentionPolicy.SOURCE)
    public @interface Include {
        String replaces() default "";
    }
}
示例
package com.semlinker.lombok;

@EqualsAndHashCode
public class EqualsAndHashCodeDemo {
    String firstName;
    String lastName;
    LocalDate dateOfBirth;
}

以上代码经过 Lombok 编译后,会生成如下代码:

package com.semlinker.lombok;

public class EqualsAndHashCodeDemo {
    String firstName;
    String lastName;
    LocalDate dateOfBirth;

    public EqualsAndHashCodeDemo() {
    }

    public boolean equals(Object o) {
        if (o == this) {
            return true;
        } else if (!(o instanceof EqualsAndHashCodeDemo)) {
            return false;
        } else {
            EqualsAndHashCodeDemo other = (EqualsAndHashCodeDemo)o;
            if (!other.canEqual(this)) {
                return false;
            } else {
              
        }
    }

    public int hashCode() {
        int PRIME = true;
        int result = 1;
        Object $firstName = this.firstName;
        int result = result * 59 + ($firstName == null ? 43 : $firstName.hashCode());
        Object $lastName = this.lastName;
        result = result * 59 + ($lastName == null ? 43 : $lastName.hashCode());
        Object $dateOfBirth = this.dateOfBirth;
        result = result * 59 + ($dateOfBirth == null ? 43 : $dateOfBirth.hashCode());
        return result;
    }
}
3.4 @ToString 注解

使用 @ToString 注解可以为指定类生成 toString 方法, @ToString 注解的定义如下:

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.SOURCE)
public @interface ToString {
  
    boolean includeFieldNames() default true;

    String[] exclude() default {};
  
    String[] of() default {};
    
  
    boolean callSuper() default false;
    
    boolean doNotUseGetters() default false;
    
    boolean onlyExplicitlyIncluded() default false;
    
    @Target(ElementType.FIELD)
    @Retention(RetentionPolicy.SOURCE)
    public @interface Exclude {}
    
    @Target({ElementType.FIELD, ElementType.METHOD})
    @Retention(RetentionPolicy.SOURCE)
    public @interface Include {
        int rank() default 0;
        String name() default "";
    }
}
示例
package com.semlinker.lombok;

@ToString(exclude = {"dateOfBirth"})
public class ToStringDemo {
    String firstName;
    String lastName;
    LocalDate dateOfBirth;
}

以上代码经过 Lombok 编译后,会生成如下代码:

package com.semlinker.lombok;

public class ToStringDemo {
    String firstName;
    String lastName;
    LocalDate dateOfBirth;

    public ToStringDemo() {
    }

    public String toString() {
        return "ToStringDemo(firstName=" + this.firstName + ", lastName=" +
          this.lastName + ")";
    }
}
3.5 @Data 注解

@Data 注解与同时使用以下的注解的效果是一样的:

  • @ToString
  • @Getter
  • @Setter
  • @RequiredArgsConstructor
  • @EqualsAndHashCode

@Data 注解的定义如下:

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.SOURCE)
public @interface Data {
    String staticConstructor() default "";
}
示例
package com.semlinker.lombok;

@Data
public class DataDemo {
    private Long id;
    private String summary;
    private String description;
}

以上代码经过 Lombok 编译后,会生成如下代码:

package com.semlinker.lombok;

public class DataDemo {
    private Long id;
    private String summary;
    private String description;

    public DataDemo() {
    }

    
    public Long getId() {
        return this.id;
    }
  
    public void setId(Long id) {
        this.id = id;
    }

    public boolean equals(Object o) {
        if (o == this) {
            return true;
        } else if (!(o instanceof DataDemo)) {
            return false;
        } else {
            DataDemo other = (DataDemo)o;
            if (!other.canEqual(this)) {
                return false;
            } else {
               
            }
        }
    }

    protected boolean canEqual(Object other) {
        return other instanceof DataDemo;
    }

    public int hashCode() {
        int PRIME = true;
        int result = 1;
        Object $id = this.getId();
        int result = result * 59 + ($id == null ? 43 : $id.hashCode());
        Object $summary = this.getSummary();
        result = result * 59 + ($summary == null ? 43 : $summary.hashCode());
        Object $description = this.getDescription();
        result = result * 59 + ($description == null ? 43 : $description.hashCode());
        return result;
    }

    public String toString() {
        return "DataDemo(id=" + this.getId() + ", summary=" + this.getSummary() + ", description=" + this.getDescription() + ")";
    }
}

3.6 @Log 注解

若你将 @Log 的变体放在类上(适用于你所使用的日志记录系统的任何一种);之后,你将拥有一个静态的 final log 字段,然后你就可以使用该字段来输出日志。

@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);

@CommonsLog
private static final org.apache.commons.logging.Log log = org.apache.commons.logging.LogFactory.getLog(LogExample.class);

3.7 @Synchronized 注解

@Synchronized 是同步方法修饰符的更安全的变体。与 synchronized 一样,该注解只能应用在静态和实例方法上。它的操作类似于 synchronized 关键字,但是它锁定在不同的对象上。synchronized 关键字应用在实例方法时,锁定的是 this 对象,而应用在静态方法上锁定的是类对象。对于 @Synchronized 注解声明的方法来说,它锁定的是 $LOCK$lock@Synchronized 注解的定义如下:

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface Synchronized {
  
    String value() default "";
}
示例
package com.semlinker.lombok;

public class SynchronizedDemo {
    private final Object readLock = new Object();

    @Synchronized
    public static void hello() {
        System.out.println("world");
    }

    @Synchronized
    public int answerToLife() {
        return 42;
    }

    @Synchronized("readLock")
    public void foo() {
        System.out.println("bar");
    }
}
以上代码经过 Lombok 编译后,会生成如下代码:
package com.semlinker.lombok;

public class SynchronizedDemo {
    private static final Object $LOCK = new Object[0];
    private final Object $lock = new Object[0];
    private final Object readLock = new Object();

    public SynchronizedDemo() {
    }

    public static void hello() {
        synchronized($LOCK) {
            System.out.println("world");
        }
    }

    public int answerToLife() {
        synchronized(this.$lock) {
            return 42;
        }
    }

    public void foo() {
        synchronized(this.readLock) {
            System.out.println("bar");
        }
    }
}
3.8 @Builder 注解

使用 @Builder 注解可以为指定类实现建造者模式,该注解可以放在类、构造函数或方法上。@Builder 注解的定义如下:

@Target({TYPE, METHOD, CONSTRUCTOR})
@Retention(SOURCE)
public @interface Builder {
    @Target(FIELD)
    @Retention(SOURCE)
    public @interface Default {}

  
    String builderMethodName() default "builder";
    
    String buildMethodName() default "build";
    
    String builderClassName() default "";
    
    boolean toBuilder() default false;
    
    AccessLevel access() default lombok.AccessLevel.PUBLIC;
    
    @Target({FIELD, PARAMETER})
    @Retention(SOURCE)
    public @interface ObtainVia {
        String field() default "";
        String method() default "";
        boolean isStatic() default false;
    }
}
示例
package com.semlinker.lombok;

@Builder
public class BuilderDemo {
    private final String firstname;
    private final String lastname;
    private final String email;
}

以上代码经过 Lombok 编译后,会生成如下代码:

package com.semlinker.lombok;

public class BuilderDemo {
    private final String firstname;
    private final String lastname;
    private final String email;

    BuilderDemo(String firstname, String lastname, String email) {
        this.firstname = firstname;
        this.lastname = lastname;
        this.email = email;
    }

    public static BuilderDemo.BuilderDemoBuilder builder() {
        return new BuilderDemo.BuilderDemoBuilder();
    }

    public static class BuilderDemoBuilder {
        private String firstname;
        private String lastname;
        private String email;

        BuilderDemoBuilder() {
        }

        public BuilderDemo.BuilderDemoBuilder firstname(String firstname) {
            this.firstname = firstname;
            return this;
        }

        public BuilderDemo.BuilderDemoBuilder lastname(String lastname) {
            this.lastname = lastname;
            return this;
        }

        public BuilderDemo.BuilderDemoBuilder email(String email) {
            this.email = email;
            return this;
        }

        public BuilderDemo build() {
            return new BuilderDemo(this.firstname, this.lastname, this.email);
        }

        public String toString() {
            return "BuilderDemo.BuilderDemoBuilder(firstname=" + this.firstname + ", lastname=" + this.lastname + ", email=" + this.email + ")";
        }
    }
}
3.9 @SneakyThrows 注解

@SneakyThrows 注解用于自动抛出已检查的异常,而无需在方法中使用 throw 语句显式抛出。@SneakyThrows 注解的定义如下:

@Target({ElementType.METHOD, ElementType.CONSTRUCTOR})
@Retention(RetentionPolicy.SOURCE)
public @interface SneakyThrows {
    
    Class<? extends Throwable>[] value() default java.lang.Throwable.class;
}
示例
package com.semlinker.lombok;

public class SneakyThrowsDemo {
    @SneakyThrows
    @Override
    protected Object clone() {
        return super.clone();
    }
}

以上代码经过 Lombok 编译后,会生成如下代码:

package com.semlinker.lombok;

public class SneakyThrowsDemo {
    public SneakyThrowsDemo() {
    }

    protected Object clone() {
        try {
            return super.clone();
        } catch (Throwable var2) {
            throw var2;
        }
    }
}
3.10 @NonNull 注解

你可以在方法或构造函数的参数上使用 @NonNull 注解,它将会为你自动生成非空校验语句。@NonNull 注解的定义如下:

@Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.LOCAL_VARIABLE, ElementType.TYPE_USE})
@Retention(RetentionPolicy.CLASS)
@Documented
public @interface NonNull {
}
示例
package com.semlinker.lombok;

public class NonNullDemo {
    @Getter
    @Setter
    @NonNull
    private String name;
}
以上代码经过 Lombok 编译后,会生成如下代码:
package com.semlinker.lombok;

public class NonNullDemo {
    @NonNull
    private String name;

    public NonNullDemo() {
    }

    @NonNull
    public String getName() {
        return this.name;
    }

    public void setName(@NonNull String name) {
        if (name == null) {
            throw new NullPointerException("name is marked non-null but is null");
        } else {
            this.name = name;
        }
    }
}

3.11 @Clean 注解

@Clean 注解用于自动管理资源,用在局部变量之前,在当前变量范围内即将执行完毕退出之前会自动清理资源,自动生成 try-finally 这样的代码来关闭流。

@Target(ElementType.LOCAL_VARIABLE)
@Retention(RetentionPolicy.SOURCE)
public @interface Cleanup {
  
    String value() default "close";
}

示例

package com.semlinker.lombok;

public class CleanupDemo {
    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);
        }
    }
}

以上代码经过 Lombok 编译后,会生成如下代码:

package com.semlinker.lombok;

public class CleanupDemo {
    public CleanupDemo() {
    }

    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.11 @With 注解

在类的字段上应用 @With 注解之后,将会自动生成一个 withFieldName(newValue) 的方法,该方法会基于 newValue 调用相应构造函数,创建一个当前类对应的实例。@With 注解的定义如下:

@Target({ElementType.FIELD, ElementType.TYPE})
@Retention(RetentionPolicy.SOURCE)
public @interface With {
    AccessLevel value() default AccessLevel.PUBLIC;

    With.AnyAnnotation[] onMethod() default {};

    With.AnyAnnotation[] onParam() default {};

    @Deprecated
    @Retention(RetentionPolicy.SOURCE)
    @Target({})
    public @interface AnyAnnotation {
    }
}
示例
public class WithDemo {
    @With(AccessLevel.PROTECTED)
    @NonNull
    private final String name;
    @With
    private final int age;

    public WithDemo(String name, int age) {
        if (name == null) throw new NullPointerException();
        this.name = name;
        this.age = age;
    }
}

以上代码经过 Lombok 编译后,会生成如下代码:

public class WithDemo {
    @NonNull
    private final String name;
    private final int age;

    public WithDemo(String name, int age) {
        if (name == null) {
            throw new NullPointerException();
        } else {
            this.name = name;
            this.age = age;
        }
    }

    protected WithDemo withName(@NonNull String name) {
        if (name == null) {
            throw new NullPointerException("name is marked non-null but is null");
        } else {
            return this.name == name ? this : new WithDemo(name, this.age);
        }
    }

    public WithDemo withAge(int age) {
        return this.age == age ? this : new WithDemo(this.name, age);
    }
}
3.12 其它特性
val

val 用在局部变量前面,相当于将变量声明为 final,此外 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());
    }
  }
}

以上代码等价于:

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());
    }
  }
}

四、参考资源

  • Lombok 官网
  • lombok-cheatsheet
  • Java开发神器Lombok的使用与原理

近期热文

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-11-30,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 码农沉思录 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 二、Lombok 安装
    • 2.1 构建工具
      • Gradle
      • Ant
    • 2.2 IDE
    • 三、Lombok 详解
      • 3.1 @Getter and @Setter 注解
        • @Getter 注解
        • @Setter 注解
        • 使用示例
        • 以上代码经过 Lombok 编译后,会生成如下代码:
        • Lazy Getter
        • 示例
        • 以上代码经过 Lombok 编译后,会生成如下代码:
      • 3.2 Constructor Annotations
        • @NoArgsConstructor 注解
        • 示例
        • @AllArgsConstructor 注解
        • 示例
        • @RequiredArgsConstructorDemo 注解
        • 示例
      • 3.3 @EqualsAndHashCode 注解
        • 示例
      • 3.4 @ToString 注解
        • 示例
      • 3.5 @Data 注解
        • 示例
        • 示例
        • 以上代码经过 Lombok 编译后,会生成如下代码:
      • 3.8 @Builder 注解
        • 示例
      • 3.9 @SneakyThrows 注解
        • 示例
      • 3.10 @NonNull 注解
        • 示例
        • 以上代码经过 Lombok 编译后,会生成如下代码:
      • 3.11 @With 注解
        • 示例
      • 3.12 其它特性
        • val
    • 四、参考资源
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档