来讲说 Java中的“==”和“equals”


千里之行,始于足下。

在Java平常开发中,常常会碰见判断两个对象或者两个值是否相等的状况,而经常使用的判断方法就是“==”和“equals”,今天就来讲说这两个的区别。缓存


“==”

主要用来判断两个对象的引用地址是否相同;
因此若是“==”两边的是两个对象,那么判断的就是是否为同一对象;
注1:若是对象的引用值是放在常量池中,例如字符串,相同字符串的引用地址相同,因此“abc"=="abc"的结果为true。而经过new String()来声明的,因为引用地址不一样,new String("abc") == new String("abc") 结果为false。this

String A = "abc";  
String B = "abc";  
System.out.println(A == B); //true

String a = new String("abc");  
String b = new String("abc");  
System.out.println(a == b); //false
//ps:这里String推荐使用equals来判断是否相等,由于是举例说明问题,因此强行用了==

注2:当判断基本类型时,是直接比较引用指向堆里面的具体值。code


“equals”

equals是Object类中的一个方法,其默认是使用“==”来判断两个对象是否相等:对象

public boolean equals(Object obj) {  
    return (this == obj);  
}

因此若是一个对象没有重写equals方法,那么对比都是引用地址。开发

equals要求知足几个特性:字符串

  1. 自反性:对任意引用值X,x.equals(x)的返回值必定为true. 
  2. 对称性:对于任何引用值x,y,当且仅当y.equals(x)返回值为true时,x.equals(y)的返回值必定为true; 
  3. 传递性:若是x.equals(y)=true, y.equals(z)=true,则x.equals(z)=true 
  4. 一致性:若是参与比较的对象没任何改变,则对象比较的结果也不该该有任何改变 
  5. 非空性:任何非空的引用值X,x.equals(null)的返回值必定为false

而在平常使用中已经重写了equals的经常使用类,有String,Integer等。源码

String:

直接上源码:hash

public boolean equals(Object anObject) {  
    if (this == anObject) {  //判断引用地址是否相等
        return true;  
    }  
    if (anObject instanceof String) {  //传入的参数是否为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;  
}

能够看到,当引用地址不相同时,String的equals时判断两个字符串的长度和每一位字符是否相等。循环

Integer:

仍是直接上源码:引用

public boolean equals(Object obj) {  
    if (obj instanceof Integer) {  
        return value == ((Integer)obj).intValue();  //这里的value是int类型的
    }  
    return false;  
}

Integer的equals是把两个Integer对象转化成基本类型int再经过==进行比较。
说到Integer,说一个遇到的坑:

Integer a = Integer.valueOf("127");  
Integer b = Integer.valueOf("127");  
Integer c = Integer.valueOf("128");  
Integer d = Integer.valueOf("128");  
  
System.out.println(a==b);  //true
System.out.println(c==d);  //false

这里是由于,对于Integer的valueOf存在一个-128~127缓存:

public static Integer valueOf(int i) {  
    if (i >= IntegerCache.low && i <= IntegerCache.high)  //low=-128,high=127
        return IntegerCache.cache[i + (-IntegerCache.low)];  
    return new Integer(i);  
}

因此当值在缓存里的时候,valueOf并无new 对象,从而致使里a==b为true。因此对于Integer大小的判断,推荐使用equals。


总结

“==”和“equals”在没有重写Object里equals方法的类里,他们是同样的。
而在平常的开发过程当中,类里能够重写equals方法用来判断两个类是否相同。例如对于一个以手机号为惟一标识的项目里,能够只判断手机号就能确认两个对象是否相等。
ps:再多说一句,通常重写equals时也会重写hashCode方法,至于为何重写hashCode方法,下次再说吧。

相关文章
相关标签/搜索