首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >类型Erasure和Object的.equals()方法在泛型方法中返回意外结果

类型Erasure和Object的.equals()方法在泛型方法中返回意外结果
EN

Stack Overflow用户
提问于 2016-04-06 01:57:54
回答 2查看 175关注 0票数 2

我正在学习泛型在Java中是如何工作的,我正在阅读Deitel & Deitel "Java - how to Program“一书中的练习,以获得这个主题的一些熟练程度。我对以下项目的结果感到困惑:

代码语言:javascript
复制
/*
*   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中传递的对象引用同一个对象时,我才会期望该方法返回true,因为object的API中相等方法的定义是这样的:

摘自:https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html#equals-java.lang.Object- 类对象的等号方法实现了对象上最具区别性的可能的等价关系;也就是说,对于任何非空引用值x和y,该方法都返回true当且仅当x和y引用同一个对象(x == y的值为true)。

但是,正如您可以从我的注释中看到的,当我传入两个具有相同状态的不同对象时,输出是真的。下面是代码中意外行为的相关部分:

代码语言:javascript
复制
// 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>类型参数被更改为它的上限,在本例中它是对象,因为这里没有任何扩展或超级关键字。如果是这样的话,floatList1和floatList2是不同的对象,因此它们不应该根据Object的equals()方法相等,对吗?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2016-04-06 02:05:08

虽然您对Object的看法是正确的,但Float.equals(Object)Integer.equals(Object) 重写了 Object.equals;链接Float Javadoc表示(部分)

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

Integer Javadoc说

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

票数 1
EN

Stack Overflow用户

发布于 2016-04-06 02:02:13

根据Object的等价物方法,它们不是,而是List 覆盖,即equals规范:

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

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/36440129

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档