[英]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)
),則兩個元素e1
和e2
相等。)換句話說,如果兩個列表包含相同順序的相同元素,則它們被定義為相等。 。 此定義確保equals
方法可在List
接口的不同實現中正常工作。
雖然您對Object
是正確的,但是Float.equals(Object)
和Integer.equals(Object)
會覆蓋 Object.equals
; 鏈接的Float
Javadoc說(部分)
請注意,在大多數情況下,對於類
Float
,f1
和f2
兩個實例,當且僅當f1.equals(f2)
值為true時,f1.floatValue() == f2.floatValue()
雖然Integer
Javadoc說
將此對象與指定對象進行比較。 當且僅當參數不為
null
且是一個包含與此對象相同的int
值的Integer
對象時,結果才為true。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.