.equals()与==
equals是所有类都具有的方法,注意基本八种数据类型是不具备equals方法的,只有他们对应的包装类才具备。
//Character
public boolean equals(Object obj) {
if (obj instanceof Character) {
return value == ((Character)obj).charValue();
}
return false;
}
//Byte
public boolean equals(Object obj) {
if (obj instanceof Byte) {
return value == ((Byte)obj).byteValue();
}
return false;
}
//Short
public boolean equals(Object obj) {
if (obj instanceof Short) {
return value == ((Short)obj).shortValue();
}
return false;
}
//Integer
public boolean equals(Object obj) {
if (obj instanceof Integer) {
return value == ((Integer)obj).intValue();
}
return false;
}
//Long
public boolean equals(Object obj) {
if (obj instanceof Long) {
return value == ((Long)obj).longValue();
}
return false;
}
//Float
public boolean equals(Object obj) {
return (obj instanceof Float)
&& (floatToIntBits(((Float)obj).value) == floatToIntBits(value));
}
//Double
public boolean equals(Object obj) {
return (obj instanceof Double)
&& (doubleToLongBits(((Double)obj).value) ==
doubleToLongBits(value));
}
//Boolean
public boolean equals(Object obj) {
if (obj instanceof Boolean) {
return value == ((Boolean)obj).booleanValue();
}
return false;
}
可以看到基本上都是先判断被equals的对象是不是同一个类型,如果不是则直接返回false。
如果是同一个类型则直接进行类似于.value()的方法,获取这个value。进一步查看源码可以发现最后这个方法的返回值都是基本数据类型。
String对象的具体实现的源码如下:
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;
}
除了上述类型之外,我们来看看普通的类如果没有重写.equals()方法,那他的底层实现是什么样:
public boolean equals(Object obj) {
return (this == obj);
}
我们可以看到无论如何包装类也好,String也好,还是任何没有重写.equals的类也好,都进行了==的比较,如果两个对象==那么久说明为true,如果不等则返回false。那么关于==的问题呢?什么情况下==等于true呢?
下面先写几行代码,猜一猜最后的结果。
int 类型:
Integer a1 = new Integer(1111);
Integer c1 = new Integer(1111);
System.out.println(c1==a1);
System.out.println(c1.equals(a1));
Integer a2 = new Integer(22);
Integer c2 = new Integer(22);
System.out.println(c2==a2);
System.out.println(c2.equals(a2));
int a3 = 3333;
Integer c3 = new Integer(3333);
System.out.println(c3==a3);
System.out.println(c3.equals(a3));
// System.out.println(a3.equals(c3));
int a4 = 4444;
int c4 = 4444;
System.out.println(c4==a4);
// System.out.println(c4.equals(a4));
下面大家思考一下结果是什么:
false
true
false
true
true
true
true
至于Integer和int比较为什么为True,请了解一下自动拆箱。
String 类型:
String a1 = "1111";
String c1 = "1111";
System.out.println(c1==a1);
String a2 = new String("2222");
String c2 = new String("2222");
System.out.println(c2==a2);
String a3 = "3333";
String c3 = new String("3333");
System.out.println(c2==a2);
答案:
true
false
false
通过上述的分析可以得出如下结论:
1、基本数据类型不存在.equals方法
2、基本数据类型的==比较的是数值是否相等。
3、基本数据类型包装类的==比较的是对象是否是相同的,也就是地址。new出来的东西就是不同的。
4、基本数据类型包装类的.equals()方法比较的是值。
5、String类型的.equals()方法首先会比较是不是相同的对象,其次如果不是相同的对象会比较对象中的每一个字符是不是一样的
6、String类型和其他Object类型的== 都是比较对象的地址,也就是是否是同一个对象。
7、如果没有重写equals方法 那么默认对象相同equals为true
hashCode与==
下面我们看看hashCode方法与==方法的差异
System.out.println("==================");
Integer a1 = new Integer(1111);
Integer c1 = new Integer(1111);
System.out.println(c1==a1);
System.out.println(a1.hashCode());
System.out.println(c1.hashCode());
System.out.println("==================");
Integer a2 = new Integer(22);
Integer c2 = new Integer(22);
System.out.println(c2==a2);
System.out.println(a2.hashCode());
System.out.println(c2.hashCode());
System.out.println("==================");
int a3 = 3333;
Integer c3 = new Integer(3333);
System.out.println(c3==a3);
System.out.println(c3.hashCode());
// System.out.println(a3.hashCode());
System.out.println("==================");
Byte a4 = new Byte((byte) 1);
Byte c4 = new Byte((byte) 1);
System.out.println(c4==a4);
System.out.println(a4.hashCode());
System.out.println(c4.hashCode());
System.out.println("==================");
Long a5 = new Long(1);
Long c5 = new Long(1);
System.out.println(c5==a5);
System.out.println(a5.hashCode());
System.out.println(c5.hashCode());
System.out.println("==================");
String a6 = new String("123");
String c6 = new String("123");
System.out.println(c6==a6);
System.out.println(a6.hashCode());
System.out.println(c6.hashCode());
System.out.println("==================");
JDKProxyForUser jpu1 = new JDKProxyForUser();
JDKProxyForUser jpu2 = new JDKProxyForUser();
System.out.println(jpu1==jpu2);
System.out.println(jpu1.hashCode());
System.out.println(jpu2.hashCode());
==================
false
1111
1111
==================
false
22
22
==================
true
3333
==================
false
1
1
==================
false
1
1
==================
false
48690
48690
==================
false
1252169911
2101973421
下面我们查看Byte类型的HashCode源码(其余基本类型包装类基本如此)
/**
* Returns a hash code for this {@code Byte}; equal to the result
* of invoking {@code intValue()}.
*
* @return a hash code value for this {@code Byte}
*/
@Override
public int hashCode() {
return Byte.hashCode(value);
}
/**
* Returns a hash code for a {@code byte} value; compatible with
* {@code Byte.hashCode()}.
*
* @param value the value to hash
* @return a hash code value for a {@code byte} value.
* @since 1.8
*/
public static int hashCode(byte value) {
return (int)value;
}
下面我们再查看其他类型hashCode源码
/**
* Returns a hash code value for the object. This method is
* supported for the benefit of hash tables such as those provided by
* {@link java.util.HashMap}.
* <p>
* The general contract of {@code hashCode} is:
* <ul>
* <li>Whenever it is invoked on the same object more than once during
* an execution of a Java application, the {@code hashCode} method
* must consistently return the same integer, provided no information
* used in {@code equals} comparisons on the object is modified.
* This integer need not remain consistent from one execution of an
* application to another execution of the same application.
* <li>If two objects are equal according to the {@code equals(Object)}
* method, then calling the {@code hashCode} method on each of
* the two objects must produce the same integer result.
* <li>It is <em>not</em> required that if two objects are unequal
* according to the {@link java.lang.Object#equals(java.lang.Object)}
* method, then calling the {@code hashCode} method on each of the
* two objects must produce distinct integer results. However, the
* programmer should be aware that producing distinct integer results
* for unequal objects may improve the performance of hash tables.
* </ul>
* <p>
* As much as is reasonably practical, the hashCode method defined by
* class {@code Object} does return distinct integers for distinct
* objects. (This is typically implemented by converting the internal
* address of the object into an integer, but this implementation
* technique is not required by the
* Java™ programming language.)
*
* @return a hash code value for this object.
* @see java.lang.Object#equals(java.lang.Object)
* @see java.lang.System#identityHashCode
*/
public native int hashCode();
可以得出结论:
1、基本数据类型没有hashCode()方法。
2、基本数据类型的包装类的hashCode为包装类的基本类型的值。
3、hashCode相同并不代表==等于true,也就是并不是同一个对象。
4、hashCode不同则肯定不是同一个对象。
5、两个对象equals则hashCode一定相同。