实习见闻


11.15

@EqualsAndHashCode(callSuper = true) 注解

当 callSuper 为 true 时,equals 比较的值包括从父类继承过来的属性

例如:

1
2
3
4
5
6
// BaseModel.java
@Data
public class BaseModel {
@TableId(value = "id", type = IdType.AUTO)
private Integer id;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// TPointsDO.java
/*
* 此处代码应该有误,@Data 已经涵盖了 @EqualsAndHashCode 注解
*/
@Data
@EqualsAndHashCode(callSuper = true)
@Accessors(chain = true)
@TableName("t_points")
public class TPointsDO extends BaseModel {


/**
* 点位名称
*/
private String placename;


}

如果 callSuperfalse

1
2
3
4
5
6
7
8
9
10
11
12
public class EqualsAndHashCodeTest {
public static void main(String args[]) {
TPointsDO tp1 = new TPointsDO();
tp1.setId(1);
tp1.setPlacename("途记");
TPointsDO tp2 = new TPointsDO();
tp2.setId(2);
tp2.setPlacename("途记");
System.out.println(tp1.equlas(tp2));
// 输出结果为 true
}
}

反之,如果 callSupertrue,则

1
2
3
4
5
6
7
8
9
10
11
12
public class EqualsAndHashCodeTest {
public static void main(String args[]) {
TPointsDO tp1 = new TPointsDO();
tp1.setId(1);
tp1.setPlacename("途记");
TPointsDO tp2 = new TPointsDO();
tp2.setId(2);
tp2.setPlacename("途记");
System.out.println(tp1.equlas(tp2));
// 输出结果为 false
}
}

以下是百度的结论:

官方文档:@EqualsAndHashCode

原文中提到的大致有以下几点:

  1. 此注解会生成equals(Object other) 和 hashCode()方法。

  2. 它默认使用非静态,非瞬态的属性

  3. 可通过参数exclude排除一些属性

  4. 可通过参数of指定仅使用哪些属性

  5. 它默认仅使用该类中定义的属性且不调用父类的方法

  6. 可通过callSuper=true解决上一点问题。让其生成的方法中调用父类的方法。

另:@Data相当于@Getter @Setter @RequiredArgsConstructor @ToString @EqualsAndHashCode这5个注解的合集。

通过官方文档,可以得知,当使用@Data注解时,则有了@EqualsAndHashCode注解,那么就会在此类中存在equals(Object other) 和 hashCode()方法,且不会使用父类的属性,这就导致了可能的问题。

比如,有多个类有相同的部分属性,把它们定义到父类中,恰好id(数据库主键)也在父类中,那么就会存在部分对象在比较时,它们并不相等,却因为lombok自动生成的equals(Object other) 和 hashCode()方法判定为相等,从而导致出错。

修复此问题的方法很简单:

  1. 使用@Getter @Setter @ToString代替@Data并且自定义equals(Object other) 和 hashCode()方法,比如有些类只需要判断主键id是否相等即足矣。

  2. 或者使用在使用@Data时同时加上@EqualsAndHashCode(callSuper=true)注解。

@Accessors 注解

此注解只针对 chain 属性

当 chain 为 true 时,生成setter方法返回this(也就是返回的是对象),代替了默认的返回void。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
@Data
@Accessors(chain=true)
public class User {
private Integer userId;
private String name;
private Integer age;

public static void main(String[] args) {
//开起chain=true后可以使用链式的set
User user=new User().setAge(27).setName("kevin");//返回对象
System.out.println(user);
}

}

可以在创建对象的同时进行 setter


文章作者: Water monster
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Water monster !
评论
  目录