【视频&交流平台】
http://study.163.com/course/introduction.htm?courseId=1004329008&utm_campaign=commission&utm_source=400000000155061&utm_medium=share
http://study.163.com/course/introduction.htm?courseId=1004638001&utm_campaign=commission&utm_source=400000000155061&utm_medium=share
https://gitee.com/happyangellxq520/spring-boot
http://412887952-qq-com.iteye.com/blog/2321532
需求缘起:
在发布了lombok相关的文章之后,有网友留言,最好讲下@EqualsAndHashCode。
==============
古有云:得民心者得天下,
今有云:得粉丝者得天下。
==============
粉丝的要求,还是好好满足的,另外对于@EqualsAndHashCode还是比较复杂的。
一、@EqualsAndHashCode
对于@EqualsAndHashCode大致有以下几点需要知道:
(1)此注解会生成equals(Object other) 和 hashCode()方法。
(2)它默认使用非静态,非瞬态的属性。
(3)可通过参数exclude排除一些属性
(4)可通过参数of指定仅使用哪些属性
(5)它默认仅使用该类中定义的属性且不调用父类的方法
(6)可通过callSuper=true解决(5)中的问题,让其生成的方法中调用父类的方法。
二、践践更通
好了,理论的东西都没有问题,还是来实际看下吧。
2.1 此注解会生成equals(Object other) 和 hashCode()方法
@EqualsAndHashCode() public class Girl2 { private int id;//主键. private String name;//姓名. private int age; //年龄. private int weight;//体重. private int height;//身高. }
这里使用了@EqualsAndHashCode注解,那么一旦使用此注解之后会生成hashCode()和equals(Object other)方法,具体生成的代码如下:
public int hashCode() { int PRIME = 59; int result = 1; result = result * 59 + this.id; Object $name = this.name; result = result * 59 + ($name == null ? 43 : $name.hashCode()); result = result * 59 + this.age; result = result * 59 + this.weight; result = result * 59 + this.height; return result; } protected boolean canEqual(Object other) { return other instanceof Girl2; } public boolean equals(Object o) { if (o == this) { return true; } if (!(o instanceof Girl2)) { return false; } Girl2 other = (Girl2) o; if (!other.canEqual(this)) { return false; } if (this.id != other.id) { return false; } Object this$name = this.name; Object other$name = other.name; if (this$name == null ? other$name != null : !this$name.equals(other$name)) { return false; } if (this.age != other.age) { return false; } if (this.weight != other.weight) { return false; } return this.height == other.height; }
对于hashCode()方法生成的时候,跟所有字段的hashCode有关系。
对于equals()方法就是判断所有的字段是否相等了,如果所有的字段都相等的话,那么就返回true,如果有一个字段不相等的话,就返回false。
2.2 它默认使用非静态,非瞬态的属性。
这个是怎么理解呢?也就是说变量使用了静态了,或者是瞬态了,那么在生成equals和hashcode方法的时候,静态和瞬态的属性是不会参与的。如下的字段定义:
private static int myCode = 1; private transient int myCode2 = 2;
mycode和myCode2不会参与hashCode的生成,不会参与equasl方法的判断,所以生成的hashCode和equals方法和上面的是一样的。
2.3 可通过参数exclude排除一些属性
这个很好理解,就是有些字段不用参与比较,那么就可以排除掉,比如:我们可以判处name、age、weight、height属性,通过判断id就能判断两个女孩是否同一个女孩,如下的代码:
@EqualsAndHashCode(exclude={"name","age","weight","height"}) public class Girl2{ private static int myCode = 1; private transient int myCode2 = 2; private int id; private String name; private int age; private int weight; private int height; }
那么对应生成的hashCode和equals方法如下:
public int hashCode() { int PRIME = 59; int result = 1; result = result * 59 + this.id; return result; } protected boolean canEqual(Object other) { return other instanceof Girl2; } public boolean equals(Object o) { if (o == this) { return true; } if (!(o instanceof Girl2)) { return false; } Girl2 other = (Girl2) o; if (!other.canEqual(this)) { return false; } return this.id == other.id; }
看到了,方法中只有和id有关系。看到这里有人会有疑问:这要是有n多个字段,但是equals只跟id有关系,那么排除很多的字段,感觉还是很麻烦的,其实有更简单的方式,接着往下看吧。(如果排除的字段比较少,可以使用这种方式)
2.4 可通过参数of指定仅使用哪些属性
这里的意思,可以通过of指定我们要的属性,比如:只和id有关系,那么就可以写成如下的代码:
@EqualsAndHashCode(of={"id"}) public class Girl2{ private static int myCode = 1; private transient int myCode2 = 2; private int id; private String name; private int age; private int weight; private int height; }
生成的代码的如下:
public int hashCode() { int PRIME = 59; int result = 1; result = result * 59 + this.id; return result; } protected boolean canEqual(Object other) { return other instanceof Girl2; } public boolean equals(Object o) { if (o == this) { return true; } if (!(o instanceof Girl2)) { return false; } Girl2 other = (Girl2) o; if (!other.canEqual(this)) { return false; } return this.id == other.id; }
细心的小伙伴会发现,这里生成的代码和在2.3是一样的。对于of和exclude只要还是看属性的多少,如果of配置的属性过多,那么就考虑使用exclude;如果exclude排除的属性过多,那么就应该使用of 。
2.5 使用callSuper=true解决继承问题
(1)默认仅使用该类中定义的属性且不调用父类的方法
这个的意思,就是默认情况下,子类的equals和hashCode方法,不会调用父类的super.hashCode方法。如下代码:
父类代码:
@EqualsAndHashCode public class Person { private int id; }
子类代码:
@EqualsAndHashCode public class Girl3 extends Person { private String name; private int age; private int weight; private int height; }
那么生成的代码为:
public int hashCode() { int PRIME = 59; int result = 1; Object $name = this.name; result = result * 59 + ($name == null ? 43 : $name.hashCode()); result = result * 59 + this.age; result = result * 59 + this.weight; result = result * 59 + this.height; return result; } protected boolean canEqual(Object other) { return other instanceof Girl3; } public boolean equals(Object o) { if (o == this) { return true; } else if (!(o instanceof Girl3)) { return false; } else { Girl3 other = (Girl3)o; if (!other.canEqual(this)) { return false; } else { Object this$name = this.name; Object other$name = other.name; if (this$name == null) { if (other$name != null) { return false; } } else if (!this$name.equals(other$name)) { return false; } if (this.age != other.age) { return false; } else if (this.weight != other.weight) { return false; } else if (this.height != other.height) { return false; } else { return true; } } }
我们会发现这里的的hashCode和equals方法只使用到了子类Girl3的属性,并没有和父类的相关。那么这样就会存在一个问题,id不一样,但是其它属性都一样的情况下,那么就会判断是同一个对象,然后实际上一旦id不一样了,是两个对象,这时候就需要使用到了callSuper=true的属性了,很简单,只需要在Girl3修改如下的代码:
@EqualsAndHashCode(callSuper=true) public class Girl3 extends Person { //省略其它代码; }
那么生成的代码如下:
protected boolean canEqual(Object other) { return other instanceof Girl3; } public int hashCode() { int PRIME = 59; int result = super.hashCode(); Object $name = this.name; result = result * 59 + ($name == null ? 43 : $name.hashCode()); result = result * 59 + this.age; result = result * 59 + this.weight; result = result * 59 + this.height; return result; } public boolean equals(Object o) { if (o == this) { return true; } else if (!(o instanceof Girl3)) { return false; } else { Girl3 other = (Girl3)o; if (!other.canEqual(this)) { return false; } else if (!super.equals(o)) { return false; } else { Object this$name = this.name; Object other$name = other.name; if (this$name == null) { if (other$name != null) { return false; } } else if (!this$name.equals(other$name)) { return false; } if (this.age != other.age) { return false; } else if (this.weight != other.weight) { return false; } else if (this.height != other.height) { return false; } else { return true; } } } }
注意:区别就是对于hashCode方法多了如下的代码:
int result = super.hashCode();
对于equals方法多了如下代码:
else if (!super.equals(o)) { return false; }好了本文就介绍到这里了,博主也要洗洗睡了。