Java中@RequiredArgsConstructor注解的基本用法

 更新时间:2024年09月04日 10:30:35   作者:码农研究僧  
这篇文章主要介绍了Java中@RequiredArgsConstructor注解的基本用法,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教

前言

从源码中学习,事因是看到项目代码中有所引用

@RequiredArgsConstructor 是 Lombok 提供的一个注解,用于自动生成一个包含所有 final 字段和带有 @NonNull 注解字段的构造函数

这可以减少样板代码,尤其是在需要依赖注入时

1. 基本知识

Lombok 是一个 Java 库,通过注解简化代码

常用注解包括 @Getter, @Setter, @ToString, @EqualsAndHashCode, 和 @Data 等

针对@RequiredArgsConstructor 注解会生成一个包含所有 final 字段和带有 @NonNull 注解字段的构造函数 

这对于构造必须初始化这些字段的对象非常有用

基本的语法如下:

@RequiredArgsConstructor
public class MyClass {
    private final String name;
    private final int age;
    private String address;
    
    @NonNull
    private String phoneNumber;
}

对应生成的构造函数如下:

public MyClass(String name, int age, String phoneNumber) {
    this.name = name;
    this.age = age;
    this.phoneNumber = phoneNumber;
}

对应需要注意的事项如下:

  • 字段的顺序:生成的构造函数中的参数顺序是按照字段在类中定义的顺序
  • @NonNull 注解:如果某个字段带有 @NonNull 注解,它也会包含在构造函数中,即使它不是 final 的。

与其他构造函数冲突:如果手动定义了构造函数,@RequiredArgsConstructor 生成的构造函数可能会与其冲突

与其他注解比较:

  • @NoArgsConstructor:生成一个无参构造函数。
  • @AllArgsConstructor:生成一个包含所有字段(包括非 final 字段)的构造函数

2. 源码解读

先看源码的对应属性

对应的属性分析如下:

staticName:

  • 设置了这个属性,会生成一个静态方法,该方法调用私有构造函数
  • 这个静态方法主要用于推断类型参数

onConstructor:

  • 允许在生成的构造函数上添加指定的注解
  • JDK 7 和 JDK 8 的语法稍有不同。

access:

  • 设置构造函数的访问级别
  • 默认是 public,可以设置为 private, protected 或 package

针对源码结合以下Demo进行展示

3. Demo

3.1 简易Demo

import lombok.NonNull;
import lombok.RequiredArgsConstructor;

@RequiredArgsConstructor
public class test {
    private final String firstName;
    private final String lastName;
    @NonNull
    private String email;
    private int age;

    public static void main(String[] args) {
        // 正确使用示例
        test person = new test("码农", "研究僧", "https://blog.csdn.net/weixin_47872288");
        System.out.println("Person created: " + person);

        // 错误使用示例(会导致编译错误)
        // Person person2 = new Person("Jane", "Doe");
    }

    @Override
    public String toString() {
        return "Person{" +
                "firstName='" + firstName + '\'' +
                ", lastName='" + lastName + '\'' +
                ", email='" + email + '\'' +
                ", age=" + age +
                '}';
    }
}

明确需要3个属性,不可超过4个

再者对应的字段属性是按照顺序的,如果更换顺序会出现如下场景:

test person = new test("码农","https://blog.csdn.net/weixin_47872288","研究僧");

3.2 staticName属性

@RequiredArgsConstructor(staticName = "of") 

会生成一个静态方法 of 来实例化对象,而不是直接调用构造函数

import lombok.AllArgsConstructor;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;

@RequiredArgsConstructor(staticName = "of")
public class test {
    private final String firstName;

    private final String lastName;
    private final String email;

    public static void main(String[] args) {
        test example = test.of("码农","研究僧","https://blog.csdn.net/weixin_47872288");
        System.out.println(example);
    }

    @Override
    public String toString() {
        return "StaticConstructorExample{" +
                "firstName='" + firstName + '\'' +
                ", lastName='" + lastName + '\'' +
                ", email='" + email + '\'' +
                '}';
    }
}

截图如下:

3.3 onConstructor属性

@RequiredArgsConstructor(onConstructor_ = @__(@CustomAnnotation("Custom Constructor"))) 

会在生成的构造函数上添加 @CustomAnnotation

import lombok.AllArgsConstructor;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target({ElementType.CONSTRUCTOR})
@Retention(RetentionPolicy.RUNTIME)
@interface CustomAnnotation {
    String value();
}
@RequiredArgsConstructor(onConstructor_ = @__(@CustomAnnotation("Custom Constructor")))
public class test {
    private final String firstName;

    private final String lastName;
    private final String email;

    public static void main(String[] args) {
        test example = new test("码农","研究僧","https://blog.csdn.net/weixin_47872288");
        System.out.println(example);
    }

    @Override
    public String toString() {
        return "StaticConstructorExample{" +
                "firstName='" + firstName + '\'' +
                ", lastName='" + lastName + '\'' +
                ", email='" + email + '\'' +
                '}';
    }
}

3.4 access属性

@RequiredArgsConstructor(access = AccessLevel.PRIVATE, staticName = "of")
public class test {
    private final String firstName;

    private final String lastName;
    private final String email;

    public static void main(String[] args) {
        test example = test.of("码农", "研究僧", "https://blog.csdn.net/weixin_47872288");
        System.out.println(example);
    }

    @Override
    public String toString() {
        return "StaticConstructorExample{" +
                "firstName='" + firstName + '\'' +
                ", lastName='" + lastName + '\'' +
                ", email='" + email + '\'' +
                '}';
    }
}

不需要构造函数是私有的,可以将构造函数的访问级别设置为 public 或 protected,直接进行new

但是我的private它竟然可以new(神奇=-=)

4. @AllArgsConstructor比较

使用 @RequiredArgsConstructor 时,只有 final 字段和 @NonNull 字段会被初始化

但是@AllArgsConstructor 生成一个构造函数,该构造函数包含类中所有字段,无论它们是否为 final 或带有 @NonNull 注解

@AllArgsConstructor
public class test {
    private final String firstName;
    private  String lastName;
    @NonNull
    private String email;
    private int age;

    public static void main(String[] args) {
        // 正确使用示例
        test person = new test("码农","研究僧","https://blog.csdn.net/weixin_47872288",18);
        System.out.println("Person created: " + person);

        // 错误使用示例(会导致编译错误)
        // Person person2 = new Person("Jane", "Doe");
    }

    @Override
    public String toString() {
        return "Person{" +
                "firstName='" + firstName + '\'' +
                ", lastName='" + lastName + '\'' +
                ", email='" + email + '\'' +
                ", age=" + age +
                '}';
    }
}

截图如下:(必须要有四个参数)

这两者都可以实用构造函数注入,但推荐使用@RequiredArgsConstructor,因为它只会初始化那些在创建对象时必需的字段

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • Java常用锁synchronized和ReentrantLock的区别

    Java常用锁synchronized和ReentrantLock的区别

    这篇文章主要介绍了Java常用锁synchronized和ReentrantLock的区别,二者的功效都是相同的,但又有很多不同点,下面我们就进入文章了解具体的相关内容吧。需要的小伙伴也可以参考一下
    2022-05-05
  • 详解5种Java中常见限流算法

    详解5种Java中常见限流算法

    在高并发系统中,出于系统保护角度考虑,通常会对流量进行限流;不但在工作中要频繁使用,而且也是面试中的高频考点。本文就为大家整理了5种Java中常见限流算法,需要的可以参考一下
    2023-04-04
  • Spring Boot 3 集成 RabbitMQ 实践指南(原理解析)

    Spring Boot 3 集成 RabbitMQ 实践指南(原理解析

    本文介绍了SpringBoot 3集成RabbitMQ的实践指南,涵盖了RabbitMQ的核心原理、核心概念、高级特性、应用场景、环境搭建、核心配置类、消息生产者、消息消费者、接口控制器、监控与运维、最佳实践以及常见问题与解决方案等内容,感兴趣的朋友一起看看吧
    2025-02-02
  • Springboot日期转换器实现代码及示例

    Springboot日期转换器实现代码及示例

    这篇文章主要介绍了Springboot日期转换器实现代码及示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-08-08
  • SpringCloud Feign高级配置详解

    SpringCloud Feign高级配置详解

    这篇文章主要介绍了SpringCloud Feign高级配置,feign是netflix提供的服务间基于http的rpc调用框架,在spring cloud得到广泛应用
    2022-09-09
  • Java常见异常全面梳理(含分类+含义+典型场景)

    Java常见异常全面梳理(含分类+含义+典型场景)

    异常是指程序在执行过程中,出现的非正常情况,可能由程序员错误、系统错误或用户输入错误引起,下面这篇文章主要介绍了Java常见异常全面梳理的相关资料,文中通过代码介绍的非常详细,需要的朋友可以参考下
    2026-03-03
  • IDEA中git不提交指定文件的问题

    IDEA中git不提交指定文件的问题

    文章主要介绍了在使用IntelliJ IDEA进行Git提交时,如何排除特定文件或文件夹不提交到Git仓库,通过创建一个新的Changelist并将其命名为“不提交的文件”,然后将不需要提交的文件移动到这个Changelist中,可以在提交时选择不包含这个Changelist中的文件
    2025-10-10
  • SpringBoot登录验证码实现过程详解

    SpringBoot登录验证码实现过程详解

    这篇文章主要介绍了SpringBoot登录验证码实现过程详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-04-04
  • IDEA配置Tomcat创建web项目的详细步骤

    IDEA配置Tomcat创建web项目的详细步骤

    Tomcat是一个Java Web应用服务器,实现了多个Java EE规范(JSP、Java Servlet等),这篇文章主要给大家介绍了关于IDEA配置Tomcat创建web项目的详细步骤,需要的朋友可以参考下
    2023-12-12
  • Spring多数据源切换失败,发现与事务相关问题

    Spring多数据源切换失败,发现与事务相关问题

    这篇文章主要介绍了Spring多数据源切换失败,发现与事务相关问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-01-01

最新评论