我正在研究泛型如何在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()方法正确吗?
答案 0 :(得分:2)
根据Object的equals方法,它们不是,List
overrides equals
规范:
将指定对象与此列表进行比较以获得相等性。当且仅当指定的对象也是列表时,返回true,两个列表具有相同的大小,并且两个列表中的所有对应元素对都相等。 (如果
e1
),则两个元素e2
和(e1==null ? e2==null : e1.equals(e2)
相等。)换句话说,如果两个列表包含相同顺序的相同元素,则它们被定义为相等。此定义确保equals
方法在List
接口的不同实现中正常工作。
答案 1 :(得分:1)
虽然您对Object
,Float.equals(Object)
和Integer.equals(Object)
覆盖 Object.equals
的信息是正确的。链接的Float
Javadoc说(部分)
请注意,在大多数情况下,对于
时,Float
,f1
和f2
类的两个实例,当{且仅当f1.equals(f2)
的值为真f1.floatValue() == f2.floatValue()
虽然Integer
Javadoc说
将此对象与指定对象进行比较。当且仅当参数不是
null
并且是包含与此对象相同的Integer
值的int
对象时,结果才为真。