我有一个矩阵类,它接受一个扩展 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 方法,代码不会尝试转换您的 Long
到Integer
.转换无效,结果是对 Long
的引用存储在您的 matrix
中大批。 (这运行正常,因为代码无法检查以确保类型与 T
相同,再次由于类型删除。)所以稍后,当您使用 matrix[i].equals
时, 因为 Long
存储在 matrix
中, Long.equals
被称为。
不幸的是,我认为没有什么好的方法可以将数字转换为某些 Number
的对象。编译时未知的类。你可以通过 T
的类作为构造函数的参数,然后使用反射尝试为该类查找采用 long
的构造函数参数,但这很难看。
关于java - 比较 "T extends Number"是否相等,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24188078/