我刚接触 Java 的泛型,所以我为自己建立了一个小项目。我想制作一个向量/点,您可以在其中指定Number
(例如Double
,、、Integer
等Long
)。
我最终得到了一个像样的类对象,但是注意到有关方法的一些问题。
import java.math.BigDecimal;
@SuppressWarnings("WeakerAccess") // Suppresses weaker access warnings
public class Vector<T extends Number> {
private T x;
private T y;
public Vector() {}
public Vector(T x, T y) {
this.x = x;
this.y = y;
}
public T getX() {
return x;
}
public void setX(T x) {
this.x = x;
}
public T getY() {
return y;
}
public void setY(T y) {
this.y = y;
}
public void dislocate(T offsetX, T offsetY) {
this.setX(addNumbers(getX(), offsetX));
this.setY(addNumbers(getY(), offsetY));
}
public void dislocate(Vector vector) {
this.setX(addNumbers(getX(), vector.getX()));
this.setY(addNumbers(getY(), vector.getY()));
}
@SuppressWarnings("unchecked") // Suppresses cast unchecked warnings
private T addNumbers(Number... numbers) {
BigDecimal bd = new BigDecimal(0);
for(Number number : numbers) {
bd = bd.add(new BigDecimal(number.toString()));
}
return (T) bd;
}
}
最后一个方法,即加数方法,会引发未经检查的强制转换警告。在我做了一些研究之后,我发现它的行为很奇怪,因为我对泛型比较陌生,无法正确排除故障。
如何return (T) bd;
创建警告?T
必须是 a 的一个实例Number
,所以它应该可以转换为 a BigDecimal
,对吧?
所以我创建了我的小测试方法,
Vector<Double> vec = new Vector<>(1.0, 3.0);
Vector<Double> vec2 = new Vector<>(2.2, 3.9);
vec.dislocate(1.0, 2.7);
System.out.println(vec.getX() + " " + vec.getY());
vec.dislocate(vec2);
System.out.println(vec.getX() + " " + vec.getY());
它工作得很好,打印出来2.0 5.7
和4.2 9.6
.
那么问题是当我使用来自 的方法时Double
,例如Double#isNaN()
. 然后它抛出 ClassCastException, Exception in thread "main" java.lang.ClassCastException: java.base/java.math.BigDecimal cannot be cast to java.base/java.lang.Double
。
这似乎与人们遇到的其他问题很常见,但是,尽管查看了资源,但我不明白为什么使用这些Double
方法会引发错误。对象应该是Double
演员后的,对吧?