我知道,每个泛型类型变量都替换为上限,这是从方法“类型参数部分”的开头的通用定义中确定的。
这是来自Deitel的书
实际上,所有类型的参数都被所谓的鞋面所取代 type参数的绑定,在type-parameter中指定 部分。
据此,该子代码必须为真
public static <E extends Number> void A( )
{
E x= new Double(2.2);
}
但是编译器告诉我 E x = new Double(2.2); 中的编译错误,虽然这必须是真的,因为 double是数字。
我知道如何通过施法来处理和解决问题,但我想问为什么会发生这种情况?
答案 0 :(得分:6)
仅因为E
是一个数字并不意味着它是Double
。
想想这样,如果E是整数,那该怎么办? E仍然是一个数字,但现在您将Double分配给整数。因此,铸造行为是一致的,Number可以是各种不同的类型,因此E.
编辑操作:Deitel语句仍然正确,如果您将Double分配给一个数字或一个对象,那么您将不需要转换。但在这种情况下,E不分配“向上”,它在两个可能的不同数字类型之间“横向”分配。如果E是Short或Integer,在这些情况下你不希望能够在没有强制转换的情况下为它们分配Double。
答案 1 :(得分:3)
当您指定E extends Number
时,这意味着E
是Number
或Number
本身的任何子类型。例如,E
可以是Integer
,Long
,Double
等。这就是您的代码无法编译的原因 - 如果E
为{{1}例如,能够将Integer
分配给Double
类型的变量是错误的。
答案 2 :(得分:1)
然而这完美无缺!
public static <E extends Number> void A() {
E x = (E)new Double(2.2);
}
对你的编译器很好,这对你很好。你需要做的就是告诉它你的意思。
而且 - 当然 - 因为我们实际上是在骗我们的编译器现在它让我们做了可怕的事情,如:
public class Test {
public static <E extends Number> E makeOne() {
E x = (E) new Double(2.2);
return x;
}
// Some real compiler abuse.
public void test() {
Integer one = Test.<Integer>makeOne();
Double two = Test.<Double>makeOne();
Number three = Test.<Double>makeOne();
}
}
对于我们在家的读者......这是不如何使用泛型。
哦 - 顺便说一下,你看到你的问题的原因是你没有选择不匹配的类型。
你的问题是一个概念问题。 Generic子句<E extends Number>
中传递的类型不是您最终决定使用的类型的占位符。您不只是在推迟决定使用哪种类型。您承诺只使用与该子句匹配的类型,如果您违反该承诺,编译器必须警告您。
您的代码不被接受的原因是因为您正在这样做,您违背了承诺。您是说虽然来电者可以使用任何 Number
,但您会使用特定的Number
(Double
),因此您违反了规定的规则你自己和编译器告诉你。
答案 3 :(得分:0)
你所知道的是E
延伸Number
。类型E
可以是Integer
,它也是Number
的子类。
将new Double(2.2)
分配给名为x
的名为Integer
的变量没有多大意义。