java常識1:弄清楚equals()和“==”

一、傳統認知

運算

基本數據類型比較的對象

引用數據類型比較的對象

==

堆內存空間

equals

默認堆內存空間,覆寫的方法除外

二、通過程序找問題

import com.leon.java.reflect.Person;

class Dog{
    private String name ;
    Dog(){}
    Dog(String name){
        this.name = name;
    }
}

public class EqualsDemo<T> {

     void test(T t1,T t2){
        System.out.println("t1是否==t2:" + (t1 == t2));
        System.out.println("t1是否equals t2:" + (t1.equals(t2)));
    }

    public static void main(String[] args) {

        // == 比較 基本類型
        System.out.println("\n--------比較基本類型-------");

        System.out.println("\n1.比較Byte");
        new EqualsDemo<Byte>().test((byte)123,(byte)123);

        System.out.println("\n2.比較Short");
        new EqualsDemo<Short>().test((short)123,(short)123);

        System.out.println("\n3.比較Integer");
        new EqualsDemo<Integer>().test(1,1);

        System.out.println("\n4.比較Long");
        new EqualsDemo<Long>().test(123L,123L);

        System.out.println("\n5.比較Float");
        new EqualsDemo<Float>().test(1.4f,1.4f);

        System.out.println("\n6.比較Double");
        new EqualsDemo<Double>().test(1.433333,1.433333);

        System.out.println("\n7.比較char");
        new EqualsDemo<Character>().test('a','a');

        System.out.println("\n8.比較Boolean");
        new EqualsDemo<Boolean>().test(true,true);

        //發現的問題1:浮點型兩個“相同的數” == 比較結果不同。解決方法:浮點型數據比較是否相等時,轉化成包裝類型,使用equals進行比較。

        //比較引用類型
        System.out.println("\n--------比較引用類型-------");

        Dog d1 = new Dog("旺旺");
        Dog d2 = new Dog("旺旺");
        System.out.println("\n比較自定義的Dog類");
        new EqualsDemo<Dog>().test(d1,d2);

        System.out.println("\n比較String");
        new EqualsDemo<String>().test("aaa","aaa");

        //發現問題:String是引用類型,==比較引用類型時,比較的應該是地址纔對。爲什麼在這裏兩個String對象的比較結果是true。
    }
}

JDK1.8下輸出結果爲:

--------比較基本類型-------

1.比較Byte
t1是否==t2:true
t1是否equals t2:true

2.比較Short
t1是否==t2:true
t1是否equals t2:true

3.比較Integer
t1是否==t2:true
t1是否equals t2:true

4.比較Long
t1是否==t2:true
t1是否equals t2:true

5.比較Float
t1是否==t2:false
t1是否equals t2:true

6.比較Double
t1是否==t2:false
t1是否equals t2:true

7.比較char
t1是否==t2:true
t1是否equals t2:true

8.比較Boolean
t1是否==t2:true
t1是否equals t2:true

--------比較引用類型-------

比較自定義的Dog類
t1是否==t2:false
t1是否equals t2:false

比較String
t1是否==t2:true
t1是否equals t2:true

這裏我們不難發現兩個問題:

       問題1:浮點型兩個“相同的數” == 比較結果爲什麼不同?

       問題2:String是引用類型,==比較引用類型時,比較的應該是地址纔對。爲什麼在這裏兩個String對象的比較結果是true?

三、解決問題

       1.浮點型數據判斷是否相等

答:這個問題的由來比較古老,是浮點型這種數據類型的設計導致了這種情況。當然,JDK的開發人員也知道這個問題,於是他們提供了這樣的解決方法:

意思是:只要參數傳入的對象是Double類型,且當前對象和傳入對象的“doubleToLongBits()”相同即認定爲兩者相等。

我們來看doubleToLongBits(double value)方法。

第一行就調用了另一個方法:

doubleToRawLongBits();

        java.lang.Double.doubleToRawLongBits() 方法返回根據IEEE754浮點“雙精度格式”位佈局,不是非數字(NaN)值,返回指定浮點值的表示。它包括以下要點:

  •    如果參數爲正無窮大,其結果是 0x7ff0000000000000L.
  •    如果參數爲負無窮大,其結果是 0xfff0000000000000L.
  •    如果參數爲NaN,那麼結果是長整型表示實際NaN值。doubleToLongBits方法不同,doubleToRawLongBits不垮所有的位模式NaN編碼爲一個單一的“規範”NaN值。

簡單理解:

上面的內容有點多不想看,可以簡單理解爲:Double的equals()方法是通過將double型轉換成long型變量,來進行數值比較的。

 

2.String是引用類型,==比較引用類型時,比較的應該是堆內存纔對。爲什麼在這裏兩個String對象的比較結果是true?

答:java代碼實際的執行引擎是jvm,jvm爲String型變量提供了緩存機制,只要內容相同的String實例,不會重新創建對象,而是重用已經存在的對象。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章