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



相关文章
|
4月前
|
IDE 安全 Java
Lombok 在企业级 Java 项目中的隐性成本:便利背后的取舍之道
Lombok虽能简化Java代码,但其“魔法”特性易破坏封装、影响可维护性,隐藏调试难题,且与JPA等框架存在兼容风险。企业级项目应优先考虑IDE生成、Java Records或MapStruct等更透明、稳健的替代方案,平衡开发效率与系统长期稳定性。
220 1
|
10月前
|
Java 编译器 开发者
注解的艺术:Java编程的高级定制
注解是Java编程中的高级特性,通过内置注解、自定义注解及注解处理器,可以实现代码的高度定制和扩展。通过理解和掌握注解的使用方法,开发者可以提高代码的可读性、可维护性和开发效率。在实际应用中,注解广泛用于框架开发、代码生成和配置管理等方面,展示了其强大的功能和灵活性。
236 25
|
XML Java 编译器
Java注解的底层源码剖析与技术认识
Java注解(Annotation)是Java 5引入的一种新特性,它提供了一种在代码中添加元数据(Metadata)的方式。注解本身并不是代码的一部分,它们不会直接影响代码的执行,但可以在编译、类加载和运行时被读取和处理。注解为开发者提供了一种以非侵入性的方式为代码提供额外信息的手段,这些信息可以用于生成文档、编译时检查、运行时处理等。
245 7
|
Java 编译器 数据库
Java 中的注解(Annotations):代码中的 “元数据” 魔法
Java注解是代码中的“元数据”标签,不直接参与业务逻辑,但在编译或运行时提供重要信息。本文介绍了注解的基础语法、内置注解的应用场景,以及如何自定义注解和结合AOP技术实现方法执行日志记录,展示了注解在提升代码质量、简化开发流程和增强程序功能方面的强大作用。
428 5
|
Java 编译器
Java进阶之标准注解
Java进阶之标准注解
138 0
|
XML Java 编译器
Java学习十六—掌握注解:让编程更简单
Java 注解(Annotation)是一种特殊的语法结构,可以在代码中嵌入元数据。它们不直接影响代码的运行,但可以通过工具和框架提供额外的信息,帮助在编译、部署或运行时进行处理。
307 43
Java学习十六—掌握注解:让编程更简单
|
IDE Java 编译器
java的反射与注解
java的反射与注解
120 0
|
XML Java 数据格式
Java-spring注解的作用
Java-spring注解的作用
142 0
|
IDE Java API
Lombok:让JAVA代码更优雅
Lombok:让JAVA代码更优雅
192 0
Lombok:让JAVA代码更优雅
|
Java 开发工具 IDE