【小家Java】Lombok的使用详解(最详尽的解释,覆盖讲解所有可用注解),解决@Builder.Default默认值问题(上)

简介: 【小家Java】Lombok的使用详解(最详尽的解释,覆盖讲解所有可用注解),解决@Builder.Default默认值问题(上)

前言


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>

image.png


先介绍这一波最常用的注解:


@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更适合只读性更强的类,所以特殊情况下,还是可以使用的。



相关文章
|
1月前
|
XML Java 编译器
Java学习十六—掌握注解:让编程更简单
Java 注解(Annotation)是一种特殊的语法结构,可以在代码中嵌入元数据。它们不直接影响代码的运行,但可以通过工具和框架提供额外的信息,帮助在编译、部署或运行时进行处理。
88 43
Java学习十六—掌握注解:让编程更简单
|
27天前
|
Java 开发者 Spring
[Java]自定义注解
本文介绍了Java中的四个元注解(@Target、@Retention、@Documented、@Inherited)及其使用方法,并详细讲解了自定义注解的定义和使用细节。文章还提到了Spring框架中的@AliasFor注解,通过示例帮助读者更好地理解和应用这些注解。文中强调了注解的生命周期、继承性和文档化特性,适合初学者和进阶开发者参考。
47 14
|
27天前
|
前端开发 Java
[Java]讲解@CallerSensitive注解
本文介绍了 `@CallerSensitive` 注解及其作用,通过 `Reflection.getCallerClass()` 方法返回调用方的 Class 对象。文章还详细解释了如何通过配置 VM Options 使自定义类被启动类加载器加载,以识别该注解。涉及的 VM Options 包括 `-Xbootclasspath`、`-Xbootclasspath/a` 和 `-Xbootclasspath/p`。最后,推荐了几篇关于 ClassLoader 的详细文章,供读者进一步学习。
32 12
|
20天前
|
Java 编译器
Java进阶之标准注解
Java进阶之标准注解
29 0
|
1月前
|
JSON Java 数据库
java 常用注解大全、注解笔记
关于Java常用注解的大全和笔记,涵盖了实体类、JSON处理、HTTP请求映射等多个方面的注解使用。
36 0
java 常用注解大全、注解笔记
|
1月前
|
IDE Java 编译器
java的反射与注解
java的反射与注解
16 0
|
1月前
|
XML Java 数据格式
Java-spring注解的作用
Java-spring注解的作用
23 0
|
Java
4.15.1下面那一个属性与Java解释程序有关?
下面那一个属性与Java解释程序有关?
179 0
|
7天前
|
Java 开发者
Java多线程编程中的常见误区与最佳实践####
本文深入剖析了Java多线程编程中开发者常遇到的几个典型误区,如对`start()`与`run()`方法的混淆使用、忽视线程安全问题、错误处理未同步的共享变量等,并针对这些问题提出了具体的解决方案和最佳实践。通过实例代码对比,直观展示了正确与错误的实现方式,旨在帮助读者构建更加健壮、高效的多线程应用程序。 ####
|
6天前
|
安全 Java 开发者
Java 多线程并发控制:深入理解与实战应用
《Java多线程并发控制:深入理解与实战应用》一书详细解析了Java多线程编程的核心概念、并发控制技术及其实战技巧,适合Java开发者深入学习和实践参考。
下一篇
无影云桌面