欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Lombok的@Data、@Accessors、@EqualsAndHashCode使用细节

程序员文章站 2024-01-16 10:52:19
Java编辑器现在有一个Lombok的插件,使用非常方便,IDEA、Eclipse都有对应的插件。Lombok能通过注解的方式,在编译时自动为属性生成构造器、getter/setter、equals、hashcode、toString方法。出现的神奇就是在源码中没有getter和setter方法,但是在编译生成的字节码文件中有getter和setter方法。这样就省去了手动重建这些代码的麻烦,使代码看起来更简洁些。实际项目中看到如下使用片段:/** * xx信息 * * @Author wang...

Java编辑器现在有一个Lombok的插件,使用非常方便,IDEA、Eclipse都有对应的插件。

Lombok能通过注解的方式,在编译时自动为属性生成构造器、getter/setter、equals、hashcode、toString方法。出现的神奇就是在源码中没有getter和setter方法,但是在编译生成的字节码文件中有getter和setter方法。这样就省去了手动重建这些代码的麻烦,使代码看起来更简洁些。

实际项目中看到如下使用片段:

/**
 * xx信息
 *
 * @Author wanglingqiang
 * @Date 2020/6/30 上午10:01
 **/
@Data
@ApiModel(value = "Team(xx信息)")
@Accessors(chain = true)
@EqualsAndHashCode(callSuper = false)
public class Team implements Serializable {
    private static final long serialVersionUID = 7618841591717042342L;

   // ...其他类属性

类上Lombok相关的注解有:

@Data
@Accessors(chain = true)
@EqualsAndHashCode(callSuper = false)

Entity、DTO、VO类建好后,如上的注解大家都是直接拷贝(至于这些注解都是干嘛的,不知道!别人这么用,我也这么用呗)。但心里还是不放心,于是自己写Demo测试了一下。

@Data:是Lombok的基础注解,这个不用说了。

接下来说说另外两个注解:

@Accessors注解

@Accessors(chain = true)

@Target({ElementType.TYPE, ElementType.FIELD})
@Retention(RetentionPolicy.SOURCE)
public @interface Accessors {
    boolean fluent() default false;

    boolean chain() default false;

    String[] prefix() default {};
}

源码默认是false,我们代码里设置了true。有什么区别呢?直接上图说明:
Lombok的@Data、@Accessors、@EqualsAndHashCode使用细节值为true时 setXxx()方法。

Lombok的@Data、@Accessors、@EqualsAndHashCode使用细节值为false时 setXxx()方法。

发现了没,setXxx()方法的返回值不同,chain=true表示链路开启,setXxx()操作后返回对象,可以继续做其他操作。

@Accessors(fluent = true)

又是什么意思呢?直接上图说明:
Lombok的@Data、@Accessors、@EqualsAndHashCode使用细节getXxx()方法变成了xxx()。

Lombok的@Data、@Accessors、@EqualsAndHashCode使用细节setXxx(String xx)方法变成了xxx(String xx)。

@Accessors(fluent = true) 总结,也即去掉get、set的前缀,直接使用类属性。

@Accessors(prefix = “xxx”)

点进源码,我们看到@Accessors还有prefix这个属性,从语义上理解是前缀的意思,我们来试试它怎么实现前缀的。

Lombok的@Data、@Accessors、@EqualsAndHashCode使用细节没加prefix属性前,可以看到是常规的getXxx()、setXxx()。然后对teamNo属性加上前缀:

    @Accessors(prefix = "team")
    private String teamNo;

再看看teamNo属性的getXxx()、setXxx() ,如下:
Lombok的@Data、@Accessors、@EqualsAndHashCode使用细节
Lombok的@Data、@Accessors、@EqualsAndHashCode使用细节发现了没,teamNo生成的getXxx()、setXxx()去掉了prefix = "team"的“team”前缀。

@EqualsAndHashCode

接下来,再看看我们代码里的 @EqualsAndHashCode(callSuper = false)是什么用意。

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.SOURCE)
public @interface EqualsAndHashCode {
    String[] exclude() default {};

    String[] of() default {};

    boolean callSuper() default false;

    boolean doNotUseGetters() default false;

可以看出,源码里callSuper默认值就是false,所以说我们代码里面写这一行是多余的。

然后,再看看callSuper的作用,查找资料给的解释是,在重写hashcode()和equals()方法时是否调用父类的属性。是不是是懂非懂,直接上图说明:

父类Page:

/**
 * 分页公共类
 *
 * @author wanglingqiang
 * @date 2020/7/16 下午6:25
 **/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Page {

    /**
     * 当前页
     */
    private Integer current = 1;

    /**
     * 每页数量
     */
    private Integer size = 10;
}

子类User,继承Page(callSuper默认值是false,所以这里就没写):

/**
 * 用户查询DTO
 *
 * @author wanglingqiang
 * @date 2020/7/16 下午6:27
 **/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class User extends Page {

    private Integer id;

    private String name;

    public User(Integer current, Integer size, Integer id, String name) {
        super(current, size);
        this.id = id;
        this.name = name;
    }
}

测试类Test:

/**
 * 测试类
 *
 * @author wanglingqiang
 * @date 2020/7/16 下午6:29
 **/
public class Test {

    public static void main(String[] args) {
        User user1 = new User(1, 10, 1, "张三");
        User user2 = new User(2, 10, 1, "张三");
        boolean flag = user1.equals(user2);
        System.out.println("flag = " + flag);
    }
}

@EqualsAndHashCode(callSuper = false)时,运行结果:

flag = true

奇怪不,明明属性值不一样,但equal()比较时竟然相等。

@EqualsAndHashCode(callSuper = true)时,运行结果:

flag = false

可以看出,callSuper = true时,子类在重写hashcode()和equals()方法时才会调用父类的属性,即把父类属性包含在一起重写hashcode()和equals()方法。

callSuper有它的实用场景,为true、为false可以根据实际需要设值。

扩展:
上面的示例中我们还演示了另外两个Lombok注释:

@NoArgsConstructor
@AllArgsConstructor

这两个注解比较加单,从语义上就能理解,是生成构造方法用的。写上这两个注解的效果,如图:
Lombok的@Data、@Accessors、@EqualsAndHashCode使用细节

本文地址:https://blog.csdn.net/WLQ0621/article/details/107388831

相关标签: Java Lombok