java - 比较 "T extends Number"是否相等

标签 java generics

我有一个矩阵类,它接受一个扩展 Number 的通用对象。

例如:

public class Matrix<T extends Number>

我正在尝试比较具有相同值的两个矩阵:

Matrix:
row=[0] 273 455 
row=[1] 243 235 
row=[2] 244 205 
row=[3] 102 160 

Matrix:
row=[0] 273 455 
row=[1] 243 235 
row=[2] 244 205 
row=[3] 102 160 

在 Matrix 类中,我有一个 equals 方法,如下所示:

public boolean equals(Object obj) {
    if (obj == null)
        return false;
    if (!(obj instanceof Matrix))
        return false;

    Matrix<T> m = (Matrix<T>) obj;
    if (this.rows != m.rows)
        return false;
    if (this.cols != m.cols)
        return false;
    for (int i=0; i<matrix.length; i++) {
        T t1 = matrix[i];
        T t2 = m.matrix[i];
        if (!t1.equals(t2))
            return false;
    }
    return true;
}

这一行失败了:

t1.equals(t2)

即使两个数字相等。例如“273”和“273”

当我调试 equals 方法时,它失败了,因为它假设数字是 Longs:

这是来自 Java SDK Long.class:

public boolean equals(Object obj) {
if (obj instanceof Long) {
    return value == ((Long)obj).longValue();
}
return false;
}

本质上,它失败是因为 obj 不是 Long 的实例。

我可以很容易地改变我的 equals 方法来做:

        if (t1.longValue()!=t2.longValue())
            return false;

但我想知道在这种情况下检查相等性的正确方法是什么,以及为什么泛型 T 上的 equals 方法假设它是一个 Long。

编辑:

我的测试代码定义了“整数的矩阵泛型类型”,这让相等性测试(使用 Long 进行比较)对我来说很奇怪。

测试代码:

    Matrix<Integer> matrix1 = new Matrix<Integer>(4, 3);
    matrix1.set(0, 0, 14);
    matrix1.set(0, 1, 9);
    matrix1.set(0, 2, 3);
    matrix1.set(1, 0, 2);
    matrix1.set(1, 1, 11);
    matrix1.set(1, 2, 15);
    matrix1.set(2, 0, 0);
    matrix1.set(2, 1, 12);
    matrix1.set(2, 2, 17);
    matrix1.set(3, 0, 5);
    matrix1.set(3, 1, 2);
    matrix1.set(3, 2, 3);

    Matrix<Integer> matrix2 = new Matrix<Integer>(3, 2);
    matrix2.set(0, 0, 12);
    matrix2.set(0, 1, 25);
    matrix2.set(1, 0, 9);
    matrix2.set(1, 1, 10);
    matrix2.set(2, 0, 8);
    matrix2.set(2, 1, 5);

    Matrix<Integer> result1 = new Matrix<Integer>(4,2);
    result1.set(0, 0, 273);
    result1.set(0, 1, 455);
    result1.set(1, 0, 243);
    result1.set(1, 1, 235);
    result1.set(2, 0, 244);
    result1.set(2, 1, 205);
    result1.set(3, 0, 102);
    result1.set(3, 1, 160);

    Matrix<Integer> matrix3 = matrix1.multiply(matrix2);
    if (!matrix3.equals(result1)) {
        System.err.println("Matrix multiplication error. matrix3="+matrix3+" result1"+result1);
        return false;
    }

Here是未定义 equals() 方法的 Matrix 代码的链接。我还没有 checkin equals() 代码。

最佳答案

程序使用 Long.equals 的原因,即使您所有的测试代码都使用 Matrix<Integer> , 只是你存储了一个 Long在里面。代码是这样的:

public class Matrix<T extends Number> {

    private T[] matrix = null;

然后在构造函数中:

    this.matrix = (T[]) new Number[rows * cols];

这当然会创建一个 null 的数组引用。但是当您使用 multiply 创建数组时,

Long result = 0l;
for (int i = 0; i < cols; i++) {
     Long l = row[i].longValue() * column[i].longValue();
     result += l;
}
output.set(r, c, (T) result);

哪里set看起来像

public void set(int row, int col, T value) {
    matrix[getIndex(row, col)] = value;
}

问题是,即使您尝试将 (T)投在结果上,它什么都不做。请注意,该语言不允许您在 Long 之间进行转换。和 Integer类型:

Long x = 3L;
Integer y = 4;
x = (Long)y;     // illegal
y = (Integer)x;  // illegal

由于类型删除,编译器不会尝试检查转换为 (T) 的类型, 但如果您不禁止显示警告,则会显示未经检查的警告。 (它会检查以确保您要转换的内容是 Number,仅此而已。)它不会生成任何可以进行转换的代码。因此,即使在 Matrix<Integer> 上调用 multiply 方法,代码不会尝试转换您的 LongInteger .转换无效,结果是对 Long 的引用存储在您的 matrix 中大批。 (这运行正常,因为代码无法检查以确保类型与 T 相同,再次由于类型删除。)所以稍后,当您使用 matrix[i].equals 时, 因为 Long存储在 matrix 中, Long.equals被称为。

不幸的是,我认为没有什么好的方法可以将数字转换为某些 Number 的对象。编译时未知的类。你可以通过 T的类作为构造函数的参数,然后使用反射尝试为该类查找采用 long 的构造函数参数,但这很难看。

关于java - 比较 "T extends Number"是否相等,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24188078/

相关文章:

ios - RxSwift - 无法推断通用参数 'Self'

java - 为什么不能扩展集合泛型类型

Django : Generic Foreign key dumpdata: Can't resolve dependencies

Java正则表达式前面的字符

javascript - 我的 css 和 js 资源的本地链接在从链接重定向到页面时附加了 localhost

java - 除非 JFrame.validate(),否则 JPanel JComponent 不会重新绘制;将组件添加到可见框架后调用

java - 如何使用 java 有效地加载 native 共享对象

c# - 如何抑制 StyleCop 错误 SA0102 : CSharp. CsParser:使用泛型类型参数属性时在文件中发现语法错误

java - 使用通配符的 Kotlin 泛型自定义类型

java - 如何将变量从一个 JFrame 传递到另一个 JFrame