Java 键入擦除和对象';在泛型方法中返回意外结果的s.equals()方法

Java 键入擦除和对象';在泛型方法中返回意外结果的s.equals()方法,java,generics,Java,Generics,我正在学习泛型如何在Java中工作,我正在通过Deitel&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 refere

我正在学习泛型如何在Java中工作,我正在通过Deitel&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);
    }
}
/*
*来自“Java-如何编程”的练习20.7。该计划将实施
*在上调用equalto()方法的泛型isEqualTo()方法
*传入的引用。我怀疑只有当
*传入的引用引用与泛型参数引用的对象相同
*编译后将替换为Object,这意味着
*方法将是Object的方法,该方法比较两个对象是否相同
*反对。
*/
导入java.util.ArrayList;
导入java.util.array;
公开课{
公共静态void main(字符串[]args){
整数[]intArray1={3,4,6,2};
整数[]intArray2={5,0,7,1};
//相同的内容,但将成为不同的列表,因此应该
//当在等质量中相互比较时为假
Float[]floatArray1={3.3f,4.4f,1.2f};
Float[]floatArray2={3.3f,4.4f,1.2f};
ArrayList intList1=新的ArrayList(Arrays.asList(intArray1));
ArrayList intList2=新的ArrayList(Arrays.asList(intarrary2));
ArrayList floatList1=新的ArrayList(Arrays.asList(floatArray1));
ArrayList floatList2=新的ArrayList(Arrays.asList(floatArray2));
//控制台输出:false-应为
System.out.println(isEqualTo(intList1,intList2));
//控制台输出:true-应为
System.out.println(isEqualTo(intList1,intList1));
//****控制台输出:真-意外*****
System.out.println(isEqualTo(floatList1,floatList2));
//控制台输出:true-应为
System.out.println(isEqualTo(floatList1,floatList1));
}
公共静态布尔isEqualTo(ArrayList list1,ArrayList list2){
返回(列表1.equals(列表2)?真:假);
}
}
这个练习说明,我应该通过调用equalto()方法来实现isEqualTo(),就像我所做的那样。只有当传入的list1和list2引用同一个对象时,我才希望该方法返回true,因为对象API中equals方法的定义声明:

摘自:

类对象的equals方法实现了最有区别的 对象上可能的等价关系;也就是说,对于任何非空 参考值x和y,当且仅当x 和y引用同一个对象(x==y的值为true)

但是,正如您从我的注释中看到的,当我传入两个具有相同状态的不同对象时,输出为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));
//相同的内容,但会变成不同的列表,所以应该是
//当在等质量中相互比较时为假
Float[]floatArray1={3.3f,4.4f,1.2f};
Float[]floatArray2={3.3f,4.4f,1.2f};
ArrayList floatList1=新的ArrayList(Arrays.asList(floatArray1));
ArrayList floatList2=新的ArrayList(Arrays.asList(floatArray2));
//****控制台输出:真-意外*****
System.out.println(isEqualTo(floatList1,floatList2));

这是怎么回事?我认为在编译时,泛型
类型参数被更改为它的上限,在本例中是Object,因为这里没有任何extends或super关键字。如果是这种情况,floatList1和floatList2是不同的对象,因此根据对象的equals()方法,它们不应该相等,对吗?

根据对象的equals方法,它们不会相等,但是
列表
表示
等于
规范:

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


虽然您对
对象
的理解是正确的,并且覆盖
对象。等于
;链接的
Float
Javadoc表示(部分)

请注意,在大多数情况下,对于类
Float
f1
f2
的两个实例,
f1.equals(f2)
的值为真当且仅当

f1.floatValue() == f2.floatValue()
整数
Javadoc表示

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


从技术上讲,
List
指定了行为,但实际上是
AbstractList
超越了它。@PaulBoddington
List
细化了合同<代码>抽象列表
实现它。公平?是的,公平。我只是不想使用overrides这个词,但我想
List
确实会重写规范。@PaulBoddington但由于这是一个通用方法,所以不是list1和list2对象的类型,不是Float或Integer吗?我想这就是我困惑的地方,我想在编译时泛型参数被更改为Object,所以它在整个方法中成为对象引用。@Daniel.Schroeder我明白你的意思,但它不是这样工作的。无论是
列表
列表
还是原始的
列表
都无关紧要。由于
Float
覆盖了
equals
,因此当您尝试comp时使用
Float
中的
equals
版本