前言
从源码中学习,事因是看到项目代码中有所引用
@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
,因为它只会初始化那些在创建对象时必需的字段
总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持代码网。
发表评论