我有以下两个类:
public class GenericNumberOperation {
public GenericNumberOperation() {}
public <T extends Number> T getSomeValue (boolean tf) {
T number;
if(tf) {
number = new Double(1.0);
}
else {
number = new Integer(11);
}
return (T) number;
}
}
并且:
public class GenericNumberTest {
public GenericNumberTest() {}
public static void main(String[] args) {
GenericNumberOperation gno = new GenericNumberOperation();
Double d = gno.getSomeValue(true);
Integer i = gno.getSomeValue(false);
}
}
当我进行测试时,一切都很笨拙。如果我将类型参数化更改为:
public <T> T getSomeValue(boolean tf)
编译器抱怨,报告:
错误:不兼容的类型整数无法转换为T. number = new整数(11); 其中T是一个类型变量 T扩展了方法getSomeValue(boolean)
中声明的Object它同样抱怨Double。为什么呢?
编辑: 我犯了一个错误。这实际上是有效的代码。
public class GenericNumberOperation {
public GenericNumberOperation() {}
public <T extends Number> T getSomeValue (boolean tf) {
Number number;
if(tf) {
number = new Double(1.0);
}
else {
number = new Integer(11);
}
return (T) number;
}
}
现在我明白了@Sotirios的目标。
答案 0 :(得分:5)
忘记你正在尝试使用它的内容。我们只是从语言的角度来看待这个问题。
声明
public <T extends Number> T getSomeValue (boolean tf) {
定义了一个由T
限定的新类型Number
。这意味着调用者只能在调用方法时将Number
或Number
的任何子类型绑定到T
。在该方法中,您不知道该类型可能是什么。
你无法做到
T number = new Double(1.0);
因为您不知道T
是Double
。如果我调用该方法为
Float f = genOp.getSomeValue(true);
T
应该是Float
。编译器不能保证类型安全,因此拒绝它(方法中的赋值,如果允许的话,将在运行时抛出ClassCastException
)。如果你使用演员,你告诉编译器你确定你正在做什么。它会警告你,但它会信任你。
同样,声明
public <T> T getSomeValue(boolean tf)
定义了一个无限制的新类型T
。这意味着您可以将任何类型绑定到T
,这会使问题更严重。我现在可以做了
String f = genOp.getSomeValue(true);
答案 1 :(得分:-2)
@Sotirios Delimanolis写道,你甚至无法运行该代码。
试试这个:
@SuppressWarnings("unchecked")
public <T extends Number> T getSomeValue(boolean tf) {
T number;
if (tf) {
number = (T) new Double(1.0);
} else {
number = (T) new Integer(11);
}
return number;
}