Lombok实验室之@Accessors使用

x33g5p2x  于2021-12-25 转载在 其他  
字(3.3k)|赞(0)|评价(0)|浏览(436)

一. 为什么要用@Accessors?

通常,在创建对象的时候,我们使用构造函数为成员变量赋值。一个对象的初始化,参数有时候不固定,所以就有了参数不同的构造函数。但是,如果一个类的成员变量很多,那么就有可能产生很多的构造函数。当然,你可以使用无参的构造函数先创建一个对象,再去调用setter方法为需要初始化的变量赋值。这样做的弊端很明显,就是一行行的setter方法费时费力。不然,也不会有不同的构造函数。但是,即使有了很多不同的构造函数,对于创建一个复杂的对象(拥有很多成员变量)也很棘手。因为在new的过程中,当我们传入构造函数的参数很多,会出现这样一种情况——不知道这个参数具体是干什么的。这时候构造函数,似乎不如setter方法那样清晰明了,因为setter方法名可以帮助我们了解这个参数具体的作用。
那么有没有办法,让我们在创建对象的过程中,既能拥有多个构造函数的参数不确定的特点,同时又能够像setter方法那样知道每个参数具体的作用呢?其实这就是我们常说的建造者模式,在《Lombok之@Builder使用》中,我们知道了@Builder可以实现这样的功能。不过,它也有点缺陷——无法在创建对象后继续使用链式赋值。幸运的是,Lombok出了一个@Accessors注解,完美地解决了这个问题,它可以让你随时随地使用链式赋值。

二. @Accessors如何使用?

在@Accessors的官方文档中,对于@Accessors的总结是——A more fluent API for getters and setters.意为:面向getter和setter的更流畅的API。所以,@Accessors是配合@Getter/@Setter注解一起使用的。代码如下:

@Getter
@Setter
@Accessors(fluent = true, chain = true)
public class Student {

    private String name;

    private Integer age;

}

反编译后的代码如下:

public class Student {
    private String name;
    private Integer age;

    public Student() {
    }

    public String name() {
        return this.name;
    }

    public Integer age() {
        return this.age;
    }

    public Student name(String name) {
        this.name = name;
        return this;
    }

    public Student age(Integer age) {
        this.age = age;
        return this;
    }
}

可以看到,所有的getter和setter方法都使用了变量名的作为方法名。setter方法的返回值全是Student类型。代码演示:

三. @Accessors源码

package lombok.experimental;

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

/** * A container for settings for the generation of getters and setters. * <p> * Complete documentation is found at <a href="https://projectlombok.org/features/experimental/Accessors">the project lombok features page for &#64;Accessors</a>. * <p> * Using this annotation does nothing by itself; an annotation that makes lombok generate getters and setters, * such as {@link lombok.Setter} or {@link lombok.Data} is also required. */
@Target({ElementType.TYPE, ElementType.FIELD})
@Retention(RetentionPolicy.SOURCE)
public @interface Accessors {
	/** * If true, accessors will be named after the field and not include a {@code get} or {@code set} * prefix. If true and {@code chain} is omitted, {@code chain} defaults to {@code true}. * <strong>default: false</strong> * * @return Whether or not to make fluent methods (named {@code fieldName()}, not for example {@code setFieldName}). */
	boolean fluent() default false;
	
	/** * If true, setters return {@code this} instead of {@code void}. * <strong>default: false</strong>, unless {@code fluent=true}, then <strong>default: true</strong> * * @return Whether or not setters should return themselves (chaining) or {@code void} (no chaining). */
	boolean chain() default false;
	
	/** * If present, only fields with any of the stated prefixes are given the getter/setter treatment. * Note that a prefix only counts if the next character is NOT a lowercase character or the last * letter of the prefix is not a letter (for instance an underscore). If multiple fields * all turn into the same name when the prefix is stripped, an error will be generated. * * @return If you are in the habit of prefixing your fields (for example, you name them {@code fFieldName}, specify such prefixes here). */
	String[] prefix() default {};
}
  • 元注解:@Target({ElementType.TYPE, ElementType.FIELD}),@Retention(RetentionPolicy.SOURCE)
  • 注解属性:fluent注解默认值为false,则保留getter和setter方法前面的get和set前缀。如果为true,则不保留前缀,直接使用变量名作为方法名,也就构成了方法的重载。
    值得注意的是,当fluent为true时,chain注解属性的值就自动设置成了true。chain的默认值是false,意味不启用链式赋值,也就是setter方法返回体为void。
    prefix注解属性处理变量名前缀的,只有拥有前缀的变量才会生成getter/setter方法,而且它的匹配原则是——匹配到的变量去掉前缀后第一个字母不能是小写。通俗地说就是,运用驼峰命名规则去匹配。

四. 特别说明

本文已经收录在Lombok注解系列文章总览中,并继承上文中所提的特别说明。
源码地址:gitee

相关文章