Java中的equals和==

一、equals和==的区别

  1.根本的区别在于.equals(Object obj)是一个方法,而==是一个运算符。

  2.一般来说,==运比较的是在内存中的物理地址,equals比较的是哈希算法值是否相等(即hashcode),且基本数据类型只能用==来进行比较。如果比较的双方没有哈希值,那么此时==和equals比较的都是物理地址,可以互相替换(事实上在Object类中equals方法的底层就是用==实现的,只是在有的需要比较哈希值的类中equals方法被重写了,如String类、Integer包装类等)。

  3.equals可以重写,在set集合中,jvm就是根据hashcode(),和equals()这两个方法来判断元素是否重复,如果要重写,建议两个方法一起重写,否则可能会出现安全性问题。

        4.重写的equals方法,一般都会首先要判断类型是否相同,如"1".equals(1)结果为false。

二、String的equals和==

  众所周知,字符串是被存在字符串池中的,那么什么情况下String a=String b呢?下面贴代码。

public class CompareString {
    public static void main(String [] args){
        String a="Xiao";
        String b="Qiang";
        String c="XiaoQiang";
        String d=new String("XiaoQiang");
        String e=a+b;
        String f="Xiao"+"Qiang";
        System.out.println(c==d);            //false
        System.out.println(c==e);            //false
        System.out.println(c==f);            //true
    }
}

  1.c==d,因为c是在字符串池创建的,保存在常量池里,d是new创建的对象,保存在堆上,所以内存地址肯定不同。

        2.c==e,这个很常见,运行时结果相等,但编译时虚拟机并不能确定结果是否相等,所以为e开辟了新的内存空间,故结果不等。

        5.c和f,因为String类使用+运算符的本质是创建StringBuilder对象并运行append()方法,得到的值再运行toString()方法,而toString()方法会检查字符串池内是否存在当前字符串,故c==g。

三、Integer的equals和==注意

equals比较

在equals(Object obj)方法中,会先判断参数中的对象obj是否是Integer同类型的对象,如果是则判断值是否相同,值相同则返回true,值不同则返回false,如果obj不是Integer类的对象,则返回false。
需要注意的是:当参数是基本类型int时,编译器会给int自动装箱成Integer类,然后再进行比较。

1. 基本类型(值类型)之间无法使用equals比较。
2. equals参数为值类型,则参数会进行自动装箱为包装类型,之后请参见第3点。
3. equals参数为包装类型,则先比较是否为同类型,非同类型直接返回false,同类型再比较值。

示例:

boolean equals1 = new Long(0).equals(0)               //false,equals参数默认为int类型,装箱为Integer类型,不同类型直接返回false
boolean equals2 = new Integer(500).equals(500)        //true,equals参数默认为int类型,装箱为Integer类型,相同类型再比较值返回true
boolean equals3 = new Integer(500).equals((short)500) //false,equals参数为byte类型,装箱为Byte类型,不同类型直接返回false
boolean equals4 = new Long(0).equals(0L)              //true,equals参数为long类型,装箱为Long类型,相同类型再比较值返回true

“==”比较
1. 基本类型之间互相比较:以值进行比较
2. 一边是基本类型,一边是包装类型
    1) 同类型的进行比较,如Integer 与int,Long与long进行==比较时,会自动拆箱比较值
    2) 不同类型之间进行比较,则会自动拆箱,且会进行自动向上转型再比较值(低级向高级是隐式类型转换如:byte 3. 两边都是包装类型则直接比较引用地址,但是要注意IntegerCache除外。


IntegerCache 缓存
JAVA的Integer有IntegerCache会缓存-128~127之间的对象。
如:Integer x = 100,会调用Integer的valueOf()方法,这个方法就是返回一个Integer对象,但是在返回前,作了一个判断,判断要赋给对象的值是否在[-128,127]区间中,且IntegerCache(是Integer类的内部类,里面有一个Integer对象数组,用于存放已经存在的且范围在[-128,127]中的对象)中是否存在此对象,如果存在,则直接返回引用,否则,创建一个新对象返回。

Integer i02 = 59;

Integer i03 = Integer.valueOf(59);

Integer i04 = new Integer(59);

     

System.out.println(i02 == i03);  //true 因为59位于缓存区间直接从缓存中获取

System.out.println(i02 == i04);  //false

System.out.println(i03 == i04);  //false
Integer i02 = 200;

Integer i03 = Integer.valueOf(200);

Integer i04 = new Integer(200);

         

System.out.println(i02 == i03);  //false 因为200超出缓存区间从新创建对象

System.out.println(i02 == i04);  //false

System.out.println(i03 == i04);  //false

建议:在一般情况下,包装类都尽量使用equals。

你可能感兴趣的:(java)