java 中的 equals、==与hashcode
一、== 详解
public class test { public static void main(String[] args) { int i1=10; int i2=10; int i3=15; boolean bool1=false; boolean bool2=false; boolean bool3=true; char c1='x'; char c2='x'; char c3='y'; short s1=255; short s2=255; short s3=128; byte b1=64; byte b2=64; byte b3=32; long l1=100; long l2=100; long l3=200; float f1=3.14f; float f2=3.14f; float f3=6.28f; double d1=2.78; double d2=2.78; double d3=5.56; System.out.print("i1==i2?"); System.out.println(i1==i2); System.out.print("i2==i3?"); System.out.println(i2==i3); System.out.print("l1==l2?"); System.out.println(l1==l2); System.out.print("l2==l3?"); System.out.println(l2==l3); System.out.print("bool1==bool2?"); System.out.println(bool1==bool2); System.out.print("bool2==bool3?"); System.out.println(bool2==bool3); System.out.print("s1==s2?"); System.out.println(s1==s2); System.out.print("s2==s3?"); System.out.println(s2==s3); System.out.print("c1==c2?"); System.out.println(c1==c2); System.out.print("c2==c3?"); System.out.println(c2==c3); System.out.print("b1==b2?"); System.out.println(b1==b2); System.out.print("b2==b3?"); System.out.println(b2==b3); System.out.print("f1==f2?"); System.out.println(f1==f2); System.out.print("f2==f3?"); System.out.println(f2==f3); System.out.print("d1==d2?"); System.out.println(d1==d2); System.out.print("d2==d3?"); System.out.println(d2==d3); } }输出如下:
i1==i2?true i2==i3?false l1==l2?true l2==l3?false bool1==bool2?true bool2==bool3?false s1==s2?true s2==s3?false c1==c2?true c2==c3?false b1==b2?true b2==b3?false f1==f2?true f2==f3?false d1==d2?true d2==d3?false
public class test { public static void main(String[] args) { String str1 = new String("abc"); String str2 = new String("abc"); String str3 = str1; Date date1 = new Date(); Date date2 = new Date(); Date date3 = date1; Person p1=new Person(); Person p2=new Person(); Person p3=p1; System.out.print("str1==str2?"); System.out.println(str1==str2); System.out.print("str1==str3?"); System.out.println(str1==str3); System.out.print("Date1==Date2?"); System.out.println(date1==date2); System.out.print("date1==date3?"); System.out.println(date1==date3); System.out.print("p1==p2?"); System.out.println(p1==p2); System.out.print("p1==p3?"); System.out.println(p1==p3); } }输出如下:
str1==str2?false str1==str3?true Date1==Date2?false date1==date3?true p1==p2?false p1==p3?true
String str1 = "abc";
public class test { public static void main(String[] args) { String str1 = "abc"; String str2 = "abc"; String str3=new String("abc"); System.out.print("str1==str2?"); System.out.println(str1==str2); System.out.print("str1==str3?"); System.out.println(str1==str3); } }输出如下:
str1==str2?true str1==str3?false由于str1与str2都是通过引号字符串建立的,当str2建立时,字符串池中已经存在“abc”,因此JVM直接返回这个引用,所以str==str2成立;而str3由new建立,没有保存在字符串池中,也就是在堆栈中保存的str3内容与stre1的内容不相同,所以str3==str1不成立。
public class test { public static void main(String[] args) { String str1 = "abc"; String str2 = "abc"; String str3=new String("abc"); str3=str3.intern(); System.out.print("str1==str2?"); System.out.println(str1==str2); System.out.print("str1==str3?"); System.out.println(str1==str3); } }这是的输出如下:
str1==str2?true str1==str3?true可以看到,通过intern(),str3变成了对字符串池中的与str1和stre2相同的引用。
基本类型 | 大小 | 包装器类型 |
boolean | - | Boolean |
char | 16bit | Character |
byte | 8bit | Byte |
short | 16bit | Short |
int | 32bit | Integer |
long | 64bit | Long |
float | 32bit | Float |
double | 64bit | Double |
void | - | Void |
public class test { public static void main(String[] args) { Integer i1 = 10; Integer i2 = 10; Boolean bool1 = false; Boolean bool2 = false; Character c1 = 'x'; Character c2 = 'x'; Short s1 = 255; Short s2 = 255; Byte b1 = 64; Byte b2 = 64; Long l1 = 100l; Long l2 = 100l; Float f1 = 3.14f; Float f2 = 3.14f; Double d1 = 2.78; Double d2 = 2.78; System.out.print("i1==i2?"); System.out.println(i1 == i2); System.out.print("l1==l2?"); System.out.println(l1 == l2); System.out.print("bool1==bool2?"); System.out.println(bool1 == bool2); System.out.print("c1==c2?"); System.out.println(c1 == c2); System.out.print("b1==b2?"); System.out.println(b1 == b2); System.out.print("s1==s2?"); System.out.println(s1 == s2); System.out.print("f1==f2?"); System.out.println(f1 == f2); System.out.print("d1==d2?"); System.out.println(d1 == d2); } }运行结果如下:
i1==i2?true l1==l2?true bool1==bool2?true c1==c2?true b1==b2?true s1==s2?false f1==f2?false d1==d2?false而对于Short、Float和Double类型,值相等的情况下,==仍然得到false。
public class test { public static void main(String[] args) { Integer i1 = new Integer(10); Integer i2 = new Integer(10); Boolean bool1 = new Boolean(false); Boolean bool2 = new Boolean(false); Character c1 = new Character('x'); Character c2 = new Character('x'); System.out.print("i1==i2?"); System.out.println(i1 == i2); System.out.print("bool1==bool2?"); System.out.println(bool1 == bool2); System.out.print("c1==c2?"); System.out.println(c1 == c2); } }运行结果如下:
i1==i2?false bool1==bool2?false c1==c2?false
二、 equals() 详解
public boolean equals(Object obj) { return (this == obj); }也就是当且仅当obj与this指向同一对象时返回true。
public boolean equals(Object anObject) { if (this == anObject) { return true; } if (anObject instanceof String) { String anotherString = (String)anObject; int n = value.length; if (n == anotherString.value.length) { char v1[] = value; char v2[] = anotherString.value; int i = 0; while (n-- != 0) { if (v1[i] != v2[i]) return false; i++; } return true; } } return false; }Java的documention中建议自定义类override这个方法,并且要求equals方法遵循下面四个约定:
public class Person { private String id; private String name; private int age; public Person(String id, String name, int age) { super(); this.id = id; this.name = name; this.age = age; } public String getId() { return id; } public void setId(String id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } @Override public boolean equals(Object obj) { // TODO Auto-generated method stub if(obj==null) return false; if(!(obj instanceof Person)) return false; Person person=(Person)obj; if(this.id==null){ return person.getId()==null; } return this.id.equals(person.getId()); } }
三、hashcode()
public class test { public static void main(String[] args) { HashMap<Person,String>map=new HashMap<Person, String>(); Person p1=new Person("101", "jack", 20); Person p2=new Person("101", "jack", 20); System.out.print("p1.equals(p2)?"); System.out.println(p1.equals(p2)); map.put(p1, "test"); System.out.println(map.get(p2)); } }上面的代码输出结果为:
p1.equals(p2)?true null由于equals为true对象hashCode也应相同,并且HashMap也需要得到hashCode来计算对象的存储索引,因此如果两个对象的hashCode不同,hashMao就认为是不同的对象。在get的时候,也是根据对象的hashCode来计算得到相应的索引,再去查看对应的位置有没有对象。
public class Person { private String id; private String name; private int age; public Person(String id, String name, int age) { super(); this.id = id; this.name = name; this.age = age; } public String getId() { return id; } public void setId(String id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } @Override public boolean equals(Object obj) { // TODO Auto-generated method stub if(obj==null) return false; if(!(obj instanceof Person)) return false; Person person=(Person)obj; if(this.id==null){ return person.getId()==null; } return this.id.equals(person.getId()); } @Override public int hashCode() { // TODO Auto-generated method stub if(id==null) return 0; return this.id.hashCode(); } }Java已经对String的hashCode进行了重写,可以保证相同的String内容会得到相同的hashCode。下面是String中的hashCode代码:
public int hashCode() { int h = hash; if (h == 0 && value.length > 0) { char val[] = value; for (int i = 0; i < value.length; i++) { h = 31 * h + val[i]; } hash = h; } return h; }
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。