java程序中测试两个变量是否相等有两种方式,一种是利用==运算符,一种是利用equals()方法。
(1)“==”
==是判断的意思,对于局部变量的基本类型(byte,short,int,long,float,double,char,boolean)存储在栈之中,比较的是值,只要值相等,就返回True
int i=0;
double x=0.00;
System.out.println(i==x); // true
而对于引用类型来说,它比较的是变量(栈)内存中存放的对象的(堆)内存地址,用来判断两个对象的地址是否相同,即是否是指相同一个对象。
String i=new String("x");
String n=new String("x");
System.out.println(i==n); // false
在举个例子,对于在常量池的变量来说,又有新情况
String s3="hello";
String s4="hello";
System.out.println(s3==s4); // true
这是因为hello已经在常量池中了,s4只是重新指向了它,并没有新建一个对象,所以也就没有对象地址不同的情况了
(2)“equals”
其用于比较对象的地址,所以其对引用类型的比较和==的作用相同
源码
基础版
public boolean equals(Object obj) {
return (this == obj);
}
分析:从源码可以看出,一般情况下,equals和==是等价的
一般引用的equals
对于Integer、Boolean等封装类来说,重写了equals
源码如下
(注: instaninstanceof是指,前面的对象是否是后面类的引用)
public boolean equals(Object obj) {
if (obj instanceof Integer) {
return value == ((Integer)obj).intValue();
}
return false;
}
public boolean equals(Object obj) {
if (obj instanceof Boolean) {
return value == ((Boolean)obj).booleanValue();
}
return false;
}
分析:虽然增加了一个判断,但实质上仍然是==的比较
String字符串的equals
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;
}
分析:这个代码的意思是,如果两个对象==成立,那么就返回true,如果对象中有String,那么就会一个字符一个字符的比较,判断字符串中每个字符是否相同。
equals扩展
对于equals,jdk给出了一些解释
equals方法在非空对象引用上实现等价关系:
- 自反性 :对于任何非空的参考值x , x.equals(x)应该返回true 。
- 它是对称的 :对于任何非空引用值x和y , x.equals(y)应该返回true当且仅当y.equals(x)回报true 。
- 传递性 :对于任何非空引用值x , y和z ,如果x.equals(y)回报true个y.equals(z)回报true ,然后x.equals(z)应该返回true 。
- 它是一致的 :对于任何非空引用值x和y ,多次调用x.equals(y)始终返回true或始终返回false ,没有设置中使用的信息equals比较上的对象被修改。
- 对于任何非空的参考值x , x.equals(null)应该返回false 。
还有需要注意的:
该equals类方法Object实现对象上差别可能性最大的相等关系; 也就是说,对于任何非空的参考值x和y ,当且仅当x和y引用相同的对象( x == y具有值true )时,该方法返回true 。
请注意,无论何时覆盖该方法,通常需要覆盖hashCode方法,以便维护hashCode方法的通用合同,该方法规定相等的对象必须具有相等的哈希码。
equals和hashcode
equals相等就一定有一样的hashcode,hashcode一样,equals不一定返回true
简单解释hashcode
对于JVM虚拟机来说,在堆中有很多很多的对象,那么如何去寻找他们,难道从头遍历吗?JVM选择使用一张表来记录各个对象的位置,一般由哈希编码来记录,每个哈希编码是独一无二的,可以根据哈希编码找到对象地址(也有极少数特殊情况暂不赘述)
hashcode方法在object中定义
public native int hashCode();
native 关键字也就说明了这个方法的底层不由Java来实现,该方法会返回object的整型数字
hashcode能大大降低对象比较次数,提高查找效率!
解释: equals相等就一定有一样的hashcode,hashcode一样,equals不一定返回true
如果两个Java对象A和B,A和B相等(eqauls结果为true),但A和B的哈希码不同,则A和B存入HashMap时的哈希码计算得到的HashMap内部数组位置索引可能不同,那么A和B很有可能允许同时存入HashMap,显然相等/相同的元素是不允许同时存入HashMap,HashMap不允许存放重复元素。
假如两个Java对象A和B,A和B不相等(eqauls结果为false),但A和B的哈希码相等,将A和B都存入HashMap时会发生哈希冲突,也就是A和B存放在HashMap内部数组的位置索引相同这时HashMap会在该位置建立一个链接表,将A和B串起来放在该位置,显然,该情况不违反HashMap的使用原则,是允许的。
参考博客:https://www.cnblogs.com/Qian123/p/5703507.html#_label1