簡體   English   中英

類型擦除和對象的.equals()方法以通用方法返回意外結果

[英]Type Erasure and Object's .equals() Method Returning Unexpected Results in Generic Method

我正在研究泛型在Java中的工作方式,並且正在Deitel和Deitel的“ Java-How to Program”(Java-如何編程)書中進行練習,以期熟練掌握該主題。 我對以下程序的結果感到困惑:

/*
*   Exercise 20.7 from "Java - How To Program". This program will implement a 
*   generic isEqualTo() method that calls the equals() method on 
*   the passed in references. I suspect it will only return true if the 
*   passed in references refer to the same object, as the generic param will
*   be replaced with Object after compilation, which means that the equals()
*   method will be that of Object, which compares if two Objects are the SAME
*   object.
*/

import java.util.ArrayList;
import java.util.Arrays;

public class EqualTo {

    public static void main(String[] args) {

        Integer[] intArray1 = {3, 4, 6, 2};
        Integer[] intArray2 = {5, 0, 7, 1};

        // identical content, but will become different lists, so should be
        // false when compared in isEqualTo to each other
        Float[] floatArray1 = {3.3f, 4.4f, 1.2f};
        Float[] floatArray2 = {3.3f, 4.4f, 1.2f};

        ArrayList<Integer> intList1 = new ArrayList<>(Arrays.asList(intArray1));
        ArrayList<Integer> intList2 = new ArrayList<>(Arrays.asList(intArray2));
        ArrayList<Float> floatList1 = new ArrayList<>(Arrays.asList(floatArray1));
        ArrayList<Float> floatList2 = new ArrayList<>(Arrays.asList(floatArray2));

        // CONSOLE OUTPUT: false - expected
        System.out.println(isEqualTo(intList1, intList2));
        // CONSOLE OUTPUT: true - expected
        System.out.println(isEqualTo(intList1, intList1));

        // ****CONSOLE OUTPUT: true - unexpected *****
        System.out.println(isEqualTo(floatList1, floatList2));

        // CONSOLE OUTPUT: true - expected
        System.out.println(isEqualTo(floatList1, floatList1));
    }

    public static <T> boolean isEqualTo(ArrayList<T> list1, ArrayList<T> list2) {
        return (list1.equals(list2) ? true : false);
    }
}

練習指出,我應該通過調用equals()方法來實現isEqualTo()。 我希望僅當傳入的list1和list2引用SAME對象時該方法才能返回true,因為Object的API中equals方法的定義如下:

取自: https : //docs.oracle.com/javase/8/docs/api/java/lang/Object.html#equals-java.lang.Object-

類Object的equals方法在對象上實現了最有區別的對等關系。 也就是說,對於任何非空參考值x和y,當且僅當x和y引用同一個對象(x == y的值為true)時,此方法才返回true。

但是,正如您從我的評論中看到的那樣,當我傳入兩個具有相同狀態的DIFFERENT對象時,輸出為true。 這是代碼的異常相關部分:

// identical content, but will become different lists, so should be
// false when compared in isEqualTo to each other
Float[] floatArray1 = {3.3f, 4.4f, 1.2f};
Float[] floatArray2 = {3.3f, 4.4f, 1.2f};

ArrayList<Float> floatList1 = new ArrayList<>(Arrays.asList(floatArray1));
ArrayList<Float> floatList2 = new ArrayList<>(Arrays.asList(floatArray2));

// ****CONSOLE OUTPUT: true - unexpected *****
System.out.println(isEqualTo(floatList1, floatList2));

怎么了 我以為在編譯時,通用的<T>類型參數已更改為其上限,在本例中為Object,因為我在這里沒有任何extend或super關鍵字。 如果是這樣,floatList1和floatList2是不同的對象,因此根據Object的equals()方法正確,它們不應該相等嗎?

根據Object的equals方法,它們不是,但是List 覆蓋equals規范:

比較指定對象與此列表是否相等。 當且僅當指定對象也是一個列表,並且兩個列表具有相同的大小,並且兩個列表中所有對應的元素對相等時,才返回true。 (如果(e1==null ? e2==null : e1.equals(e2) ),則兩個元素e1e2相等。)換句話說,如果兩個列表包含相同順序的相同元素,則它們被定義為相等。 。 此定義確保equals方法可在List接口的不同實現中正常工作。

雖然您對Object是正確的,但是Float.equals(Object)Integer.equals(Object) 會覆蓋 Object.equals 鏈接的Float Javadoc說(部分)

請注意,在大多數情況下,對於類Floatf1f2兩個實例,當且僅當f1.equals(f2)值為true時,

 f1.floatValue() == f2.floatValue() 

雖然Integer Javadoc說

將此對象與指定對象進行比較。 當且僅當參數不為null且是一個包含與此對象相同的int值的Integer對象時,結果才為true。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM