溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

java==和equalse的區(qū)別是什么

發(fā)布時(shí)間:2021-11-24 15:25:12 來源:億速云 閱讀:146 作者:iii 欄目:大數(shù)據(jù)

這篇文章主要介紹“java==和equalse的區(qū)別是什么”,在日常操作中,相信很多人在java==和equalse的區(qū)別是什么問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”java==和equalse的區(qū)別是什么”的疑惑有所幫助!接下來,請跟著小編一起來學(xué)習(xí)吧!

1.總的來說==和equalse 比較的都是地址值;

2.==在對比基本數(shù)據(jù)類型和包裝類的常量池的時(shí)候,比較的是值

3.equalse是方法,只能作用于對象數(shù)據(jù)(Integer等封裝類也是對象哈),默認(rèn)也是比較地址值,但是大多數(shù)情況下我們是覆寫equalse方法來對比其屬性值是否一樣;

4.但是equalse方法可以被重寫。基本類型中封裝類Integer和String的equalse方法都是被重寫過的,所以比較的是值

5.Integer的常量池很好理解 -128   127,String也有常量池,我們字面創(chuàng)建String a=“xxx”這種都是進(jìn)入常量池

    String的常量池說明可以參考這篇文章: https://www.cnblogs.com/tongkey/p/8587060.html

分開講述==和equalse

一、先說==,在比較不同數(shù)據(jù)的時(shí)候效果

1. 基礎(chǔ)數(shù)據(jù)類型:

        比較的是他們的值是否相等,比如兩個(gè)int類型的變量,比較的是變量的值是否一樣。

2. 引用數(shù)據(jù)類型:

        比較的是引用的地址是否相同,比如說新建了兩個(gè)User對象,比較的是兩個(gè)User的地址是否一樣。

3.基本類型的包裝類問題

    3.1包裝類,通過new創(chuàng)建對象

        基本類型的包裝類 也算是對象,不管是否使用常量池,只要一方通過new創(chuàng)建對象,那就一定是比較的地址值

    以Integer舉例

不使用常量池:-128  127 
 public static void equalsTest(){
    Integer A=new Integer(1);
    Integer B=new Integer(1);;
    if(A==B){
      System.out.println("A=B");
    }else{
      System.out.println("A!=B");
    }
  }

輸出結(jié)果為:A!=B

使用常量池
  public static void equalsTest(){
    Integer A=new Integer(128);
    Integer B=new Integer(128);;
    if(A==B){
      System.out.println("A=B");
    }else{
      System.out.println("A!=B");
    }
  }

輸出結(jié)果為:A!=B

        

    3.2基本類型的包裝類 不使用new創(chuàng)建對象的時(shí)候

       以Integer舉例

     在-128  127的時(shí)候,會使用常量池?cái)?shù)據(jù),從而比較對象值;不使用常量池的時(shí)候,會比較地址值

 使用常量池的時(shí)候-128  127
  public static void equalsTest(){
    Integer A=-127;
    Integer B=-127;;
    if(A==B){
      System.out.println("A=B");
    }else{
      System.out.println("A!=B");
    }
  }
輸出結(jié)果為:A=B

不使用常量池的時(shí)候,比較的是地址值

 public static void equalsTest(){
    Integer A=128;
    Integer B=128;;
    if(A==B){
      System.out.println("A=B");
    }else{
      System.out.println("A!=B");
    }
  }
輸出結(jié)果為:A!=B

    3.3Integer的特殊情況 Integer在用==對比int類型的時(shí)候,無論何時(shí)都是對比的值

賦值128,沒有使用到常量池  

public static void equalsTest(){
    Integer A=new Integer(128);
    int B=128;
    if(A==B){
      System.out.println("A=B");
    }else{
      System.out.println("A!=B");
    }
  }
輸出結(jié)果為:A=B
查看源碼 發(fā)現(xiàn) Integer只會對int作值的比較

/**
     * Compares this object to the specified object.  The result is
     * {@code true} if and only if the argument is not
     * {@code null} and is an {@code Integer} object that
     * contains the same {@code int} value as this object.
     *
     * @param   obj   the object to compare with.
     * @return  {@code true} if the objects are the same;
     *          {@code false} otherwise.
     */
    public boolean equals(Object obj) {
        if (obj instanceof Integer) {
            return value == ((Integer)obj).intValue();
        }
        return false;
    }

    3.4 String類型的使用常量池對比的也是值(絕大多數(shù)情況都是用到常量池)

      我們通常使用String A="hello";這種方式創(chuàng)建的所有變量所有的都進(jìn)了字符串常量池

  這種創(chuàng)建方式都是會使用到常量池
public static void equalsTest(){
    String A="hello";
    String B="hello";
    if(A==B){
      System.out.println("A=B");
    }else{
      System.out.println("A!=B");
    }
  }
輸出結(jié)果為: A=B

我們通常使用String A="hello";這種方式創(chuàng)建的所有變量所有的都進(jìn)了字符串常量池

String類的final修飾的,以字面量的形式創(chuàng)建String變量時(shí),jvm會在編譯期間就把該字面量(“hello”)放到字符串常量池中,由Java程序啟動的時(shí)候就已經(jīng)加載到內(nèi)存中了。這個(gè)字符串常量池的特點(diǎn)就是有且只有一份相同的字面量,如果有其它相同的字面量,jvm則返回這個(gè)字面量的引用,如果沒有相同的字面量,則在字符串常量池創(chuàng)建這個(gè)字面量并返回它的引用

                3.5  String類型不使用常量池的情況,比較的是地址值

  public static void equalsTest(){
    String A="hello";
    String B=new String("hello");;
    if(A==B){
      System.out.println("A=B");
    }else{
      System.out.println("A!=B");
    }
  }
輸出結(jié)果為:A!=B
通過new創(chuàng)建對象,使用的是新的對象,結(jié)果自然不相等


  public static void equalsTest(){
    String A="hello";
    String B=new String("hello");
    //B引用變?yōu)槌A砍氐膆ello的引用
    B=B.intern();
    if(A==B){
      System.out.println("A=B");
    }else{
      System.out.println("A!=B");
    }
  }
輸出結(jié)果為:A=B

二、equalse是方法,只能作用于對象數(shù)據(jù)(Integer等封裝類也是對象哈),默認(rèn)也是比較地址值

        1.equalse方法默認(rèn)還是比較地址值。但是可以被重寫

                在大多數(shù)Java類庫中的類中 如基本類型中封裝類Integer和String的equalse方法都是被重寫過的,所以比較的是值

                通常我們使用equalse都是自己覆寫方法來對比對象內(nèi)部的屬性值是否相同

三、值相同的時(shí)候,hashcode不一定相同

    結(jié)論:hashcode相同,值不一定相同,值相同hashCode一定相同(重寫hashCode方法)

                

    1. 為什么ashcode相同,值一定相同,值相同hashCode不一定相同

                hashCode是所有java對象的固有方法,如果不重寫的話,返回的實(shí)際上是該對象在jvm的堆上的內(nèi)存地址,而不同對象的內(nèi)存地址肯定不同,所以這個(gè)hashCode也就肯定不同了。如果重寫了的話,由于采用的算法的問題,有可能導(dǎo)致兩個(gè)不同對象的hashCode相同。

    2.hashCode和equalse的關(guān)聯(lián)關(guān)系

                    hashCode和equals兩個(gè)方法是有語義關(guān)聯(lián)的,它們需要滿足:

                    A.equals(B)==true --> A.hashCode()==B.hashCode()

                    因此重寫其中一個(gè)方法時(shí)也需要將另一個(gè)也重寫。

    3.HashCode方法重寫需要滿足規(guī)范

             如果根據(jù) equals(Object) 方法,兩個(gè)對象是相等的,那么對這兩個(gè)對象中的每個(gè)對象調(diào)用 hashCode 方法都必須生成相同的整數(shù)結(jié)果。

         3.1 hashCode的重寫實(shí)現(xiàn)需要滿足不變性,即一個(gè)object的hashCode不能前一會是1,過一會就變成2了。

         3.2 hashCode的重寫實(shí)現(xiàn)最好依賴于對象中的final屬性,從而在對象初始化構(gòu)造后就不再變化。一方面是jvm便于代碼優(yōu)化,可以緩存這個(gè)hashCode;另一方面,在使用hashMap或hashSet的場景中,如果使用的key的hashCode會變化,將會導(dǎo)致bug,比如放進(jìn)去時(shí)key.hashCode()=1,等到要取出來時(shí)key.hashCode()=2了,就會取不出來原先的數(shù)據(jù)。

    4.hashCode為什么會存在相同的情況

        以hashSet舉例,hashSet JDK1.8以前底層結(jié)構(gòu)是數(shù)組+鏈表的形式,1.8之后是數(shù)組+鏈表+紅黑樹

           以1.8舉例:

         在向hashSet集合中添加元素時(shí),需要經(jīng)過兩個(gè)步驟

  • 計(jì)算hashcode并與hashSet數(shù)組中的hashcode進(jìn)行比較

  • 如果有相同的hashcode,則對該hash的內(nèi)容使用equals進(jìn)行比較,如果不同則存入集合

         因此相同的hashcode不一定有相同的值,但是如果值相同,那他的hashcode一定相同  

   4. 只要使用HashSet存儲自定義類型的數(shù)據(jù)切記要重寫equals和hashCode方法

到此,關(guān)于“java==和equalse的區(qū)別是什么”的學(xué)習(xí)就結(jié)束了,希望能夠解決大家的疑惑。理論與實(shí)踐的搭配能更好的幫助大家學(xué)習(xí),快去試試吧!若想繼續(xù)學(xué)習(xí)更多相關(guān)知識,請繼續(xù)關(guān)注億速云網(wǎng)站,小編會繼續(xù)努力為大家?guī)砀鄬?shí)用的文章!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI