类型Erasure和Object的.equals()方法返回通用方法

时间:2016-04-06 01:57:55

标签: java generics

我正在研究泛型如何在Java中工作,我正在Deitel& amp; Deitel“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方法实现最具辨别力   对象可能的等价关系;也就是说,对于任何非null   引用值x和y,当且仅当x时,此方法返回true   和y引用相同的对象(x == y的值为true)。

但是,正如您在我的评论中所看到的,当我传入两个具有相同状态的DIFFERENT对象时的输出为真。以下是代码意外行为的相关部分:

// 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,因为此处我没有任何扩展或超级关键字。如果是这种情况,floatList1和floatList2是不同的对象,所以它们不应该根据Object的equals()方法正确吗?

2 个答案:

答案 0 :(得分:2)

根据Object的equals方法,它们不是,List overrides equals规范:

  

将指定对象与此列表进行比较以获得相等性。当且仅当指定的对象也是列表时,返回true,两个列表具有相同的大小,并且两个列表中的所有对应元素对都相等。 (如果e1),则两个元素e2(e1==null ? e2==null : e1.equals(e2)相等。)换句话说,如果两个列表包含相同顺序的相同元素,则它们被定义为相等。此定义确保equals方法在List接口的不同实现中正常工作。

答案 1 :(得分:1)

虽然您对ObjectFloat.equals(Object)Integer.equals(Object) 覆盖 Object.equals的信息是正确的。链接的Float Javadoc说(部分)

  

请注意,在大多数情况下,对于Floatf1f2类的两个实例,当{且仅当

时,f1.equals(f2)的值为真
f1.floatValue() == f2.floatValue()

虽然Integer Javadoc说

  

将此对象与指定对象进行比较。当且仅当参数不是null并且是包含与此对象相同的Integer值的int对象时,结果才为真。