记一次@EqualsAndHashCode的疑惑
Lombok的使用真的是让开发人员欲罢不能,一个@Data不管有多少属性全部搞定,以后加字段也不用从新生成get和set方法。不过这里还是有一个小坑需要注意一下,举个例子:
public class EqualsAndHashCodeTest {
@Data
public class BasePo implements Serializable {
public final static String DEFAULT_USERNAME = "system";
private Long id = 0L;
private String createdBy = DEFAULT_USERNAME;
private String updatedBy = DEFAULT_USERNAME;
private Date createdTime = Date.from(ZonedDateTime.now().toInstant());
private Date updatedTime = Date.from(ZonedDateTime.now().toInstant());
}
@Data
@NoArgsConstructor
@Accessors(chain = true)
public class Resource extends BasePo {
private String code;
private String name;
private String type;
private String url;
private String method;
private String description;
}
@Data
@NoArgsConstructor
@Accessors(chain = true)
public class Resource1{
private String code;
private String name;
private String type;
private String url;
private String method;
private String description;
}
public void test(){
// 创建两个相同对象
Resource resource1 = new Resource();
Resource resource2 = new Resource();
// 两个对象父类属性设置不同的值
resource1.setId(1L);
resource1.setCreatedBy("123456");
resource1.setName("123456");
resource2.setId(2L);
resource2.setCreatedBy("654321");
resource2.setName("123456");
// 看下两个对象的打印,明明是两个不同对象,但是他们的hashCode确相同,equals方法更是判定两个对象一样
System.out.println(JSONObject.toJSONString(resource1));
System.out.println(JSONObject.toJSONString(resource2));
System.out.println("resource1 hashCode : " + resource1.hashCode());
System.out.println("resource2 hashCode : " + resource2.hashCode());
System.out.println(resource1.equals(resource2));
// 正确使用,在Resource对象上面添加@EqualsAndHashCode(callSuper = true),保证从写hashCode和equals方法时加入父类属性
}
public static void main(String[] args) {
new EqualsAndHashCodeTest().test();
}
}
看下打印:
{"createdBy":"123456","createdTime":1564137042686,"id":1,"name":"123456","updatedBy":"system","updatedTime":1564137042687}
{"createdBy":"654321","createdTime":1564137042687,"id":2,"name":"123456","updatedBy":"system","updatedTime":1564137042687}
resource1 hashCode : 1342316317
resource2 hashCode : 1342316317
true
我们明明创建了两个不同对象,但是的出来的hashCode确相同,是不是很悲催。
@Data相当于@Getter @Setter @RequiredArgsConstructor @ToString @EqualsAndHashCode这5个注解的合集。其中@EqualsAndHashCode这个属性重写hashCode和equals方法,它默认是不添加父类属性的重写,所以如果继承父类时候使用@Data需要加上@EqualsAndHashCode(callSuper = true)添加上父类属性重写hashCode和equals。
{"createdBy":"123456","createdTime":1564137336096,"id":1,"name":"123456","updatedBy":"system","updatedTime":1564137336097}
{"createdBy":"654321","createdTime":1564137336097,"id":2,"name":"123456","updatedBy":"system","updatedTime":1564137336097}
resource1 hashCode : -496642359
resource2 hashCode : -839607981
false
这才是我们想要的结果。