首页 > 代码库 > 步步深入Java — ==和equals

步步深入Java — ==和equals


    当你在程序中遇到判断变量或对象是否相等的情况,想到的应该是用equals或==,两者的区别在哪?先来了解一下内存中的堆和栈。
 
    栈:基本类型的变量和对象的引用变量
    堆:实际对象
    例如:int i=1; 
          int j=2;
          Object_A a=new Object_A();
          注:Object_A a 只是定义了一个变量;new Object_A()创建对象

 
基本数据类型:
   
 对象内存图:
      

 
 概括 基础类型在“栈”中存的是内容值,对象类型在“栈”中存的是地址,而这些地址指向“堆”中的对象。    
    1、==:比较两个变量所对应的内存中所存储的数值是否相等。
    2、equals:用于比较两个独立对象的内容是否相同。

一、基本数据类型
public class TestEquals {    public static void main(String[] args){               int a=1;        int b=1;        int c=2;                System.out.println(a==b);             //true        System.out.println(a==c);             //false        System.out.println(a.equals(b));      //编译不通过    }}     <span style="LINE-HEIGHT: 1.5; FONT-SIZE: 10.5pt"></span>
 小结:
      基本数据类型只能用==,比较的是内容;不能用equals。equals被用来对象之间的比较。
 
二、基本数据类型包装类(Boolean、Integer……)
    
 public class TestEquals {        public static void main(String[] args){        Integer intA=new Integer("123");        Integer intB=new Integer("123");        Integer intC=new Integer("456");                //比较的是地址,intA和intB为不同的对象,故其地址不同        System.out.println(intA==intB);              //false                //同上,此对象内容也不同        System.out.println(intA==intC);              //false                //比较的是对象的内容        System.out.println(intA.equals(intB));       //true                //对象内容不同        System.out.println(intA.equals(intC));       //false    }   }<span style="BACKGROUND-COLOR: rgb(255,255,255)"><span style="font-family:宋体;"><span style="FONT-SIZE: 12pt"><span style="font-size:18px;">   </span></span><span style="LINE-HEIGHT: 21px"></span></span></span>
小结:
     基础类型包装类的普通类相同,==比较的是对象地址(是否指向同一对象);equals比较的是对象内容。
   
基础数据和包装类区别:
 
     包装类是对象,拥有方法和字段。当需要往ArrayList,HashMap中放东西时,像int,double这种基本类型是放不进去的,因为容器都是装object的,这是就需要这些基本类型的包装类。                
 
三、普通类
 
 public class TestEquals {        public static void main(String[] args){        Person a=new Person(123);        Person b=new Person(123);        Person c=new Person(456);                    //比较的栈中保存的地址        System.out.println(a==b);             //false        System.out.println(a==c);             //false                //引用类型比较两个对象的引用地址        System.out.println(a.equals(b));     //false        System.out.println(a.equals(c));     //false    }}
小结:
 
    Person为引用类型,当使用"=="使比较的是栈中地址,所以为false;当使用equals时,默认采用Object的equals,比较的是两个对象所引用的地址,故为false;

四、String、StringBuffer、StringBuilder

情况1:String a="";
  
public class TestString {    public static void main(String[] args){        String strA="123";        String strB="123";        String strC="456";                //比较内容是否相同,在常量池中只存在一个变量strA的值123,strB直接去用这个值即可        System.out.println(strA==strB);                 //true        //内容不同                                                    System.out.println(strA==strC);                 //false                //比较的是内容        System.out.println(strA.equals(strB));          //true        //内容不同        System.out.println(strA.equals(strC));          //false                    }}

   常量池/字符串连接池:在JVM内,存在字符串池,其中保存着很多String对象,并且可以被共享使用,因此它提高了效率.字符串池由String类维护,我们可以调用intern()方法来访问字符串池。当用“”创建对象时,所创建的对象会加入到字符串连接池里。如果要创建下一个字符串对象,JVM会到字符串池中寻找,
   若存在,则共享一个(返回一个已经存在对象的引用给要创建的对象引用)。
   不存在,则创建一个新对象(返回一个新对象的对象的引用给要创建的对象引用)
 
小结:
 
    "=="和equals:比较的都是内容

情况2:String a=new String();  
public class TestString {    public static void main(String[] args){        String strA=new String("123");        String strB=new String("123");        String strC=new String("456");                        //比较的两个对象的地址        System.out.println(strA==strB);                //false        //地址不同                                                    System.out.println(strA==strC);                //false                //比较的是内容        System.out.println(strA.equals(strB));         //true        //内容不同        System.out.println(strA.equals(strC));         //false                    }}

小结:   
   使用new创建对象,“==”比较的栈中的引用地址;这里的equlas重写了Object中的equals方法,比较的是两个对象中保存的值,所以为true。

 
总结:
     ==
        比较内容:基本数据类型、String中引号创建对象 
        比较地址:类(包装类、普通类、String)   
    equals:
         比较内容:包装类和String(重写了Object的equals方法
         比较地址:一般类
  
    ==用来比较栈内存中变量值或者对象地址,equals默认情况比较栈内对象地址。包装类、String构造器重写了equals方法后比较的是堆内对象的内容。 

步步深入Java — ==和equals