假设我有这个Foo
类,它具有扩展E
的泛型类型变量Number
。由于每个Number
对象应该具有double值,因此在实例化类型E
的新实例时,我想给它一个double值。可能吗?怎么样?
public class Foo<E extends Number> {
...
public void someMethod() {
... // some computation
Class<E> typeClass;
E newInstance = typeClass.newInstance();
// Because every Number has a doubleValue(),
// I would like to give newInstance a double value, how?
}
}
或者我应该放弃泛型类型变量,而是使用Double
代替?但我不想限制用户使用Byte
或Integer
的自由。这些数字类是否可以互换,即可以Byte
以某种方式转换为Double
?
谢谢!
编辑:
我正在使用泛型实现Dijkstra算法,该算法计算最小加权路径。这意味着边缘标签可以以某种方式累积,为此我可以想到的最通用的类是Number
。
答案 0 :(得分:1)
首先,你的假设是
由于每个Number对象都应该具有double值,因此在实例化E类型的新实例时,我想给它一个double值。
不正确。
例如,如何使用double值1.5实例化Integer?它应该通过舍入来实例化吗?通过截断?我可以很好地定义Number的子类,它甚至不支持任意整数,如下所示:
public static class Zero extends Number {
@Override
public double doubleValue() {
return 0;
}
@Override
public float floatValue() {
return 0;
}
@Override
public int intValue() {
return 0;
}
@Override
public long longValue() {
return 0;
}
}
如何使用像1.5这样的双精度值实例化零?
由于没有通用逻辑可以使用任意双值实例化Number的任意子类(这就是为什么Number不具有带双参数的构造函数的原因),唯一合理的方法是询问客户端提供一个工厂,它可以使用适用于该特定子类的自定义逻辑给定一个任意double值的Number子类的实例。如下所示:
public class Foo<E extends Number> {
public static interface NumberFactory<T extends Number> {
T createByDoubleValue(double value);
}
private final NumberFactory<E> factory;
public Foo(NumberFactory<E> factory) {
this.factory = factory;
}
...
public void someMethod() {
... // some computation
// Because every Number has a doubleValue(),
// I would like to give newInstance a double value, how?
E instance = factory.createByDoubleValue(1.5);
}
}
要使用Foo类,客户端需要定义工厂,如下所示:
Foo<Float> foo = new Foo<>(new Foo.NumberFactory<Float>() {
@Override
public Float createByDoubleValue(double value) {
return new Float(value);
}
});