4

我知道,每个泛型类型变量都替换为从方法“类型参数部分”开头的泛型定义确定的上限。

这是来自 Deitel 的书

实际上,所有类型参数都替换为类型参数的所谓上限,该上限在 type-parameter 部分中指定。

据此,此子代码必须为真

public  static <E extends Number> void A(  )
 {

E x=  new Double(2.2);

 }

但编译器告诉我是 E x= new Double(2.2); 中的编译错误;,尽管这必须是真的,因为double 是 number

我知道如何通过铸造来处理和解决一般问题,但我问为什么会发生这种情况?

4

4 回答 4

6

仅仅因为E是一个数字并不意味着它是一个Double

可以这样想,如果 E 是整数会怎样。E 仍然是一个数字,但现在您将一个 Double 分配给一个整数。所以转换行为是一致的,Number可以是各种不同的 Type,E 也可以。

编辑操作:Deitel 语句仍然正确,如果您将 Double 分配给数字或对象,那么您不需要强制转换。不过,在这种情况下,E 不是“向上”分配,而是在两种可能的不同数字类型之间“横向”分配。如果 E 是一个 Short 或 Integer 怎么办,在这些情况下,您不会期望能够在不强制转换的情况下为它们分配 Double。

于 2013-05-29T21:43:37.253 回答
3

当您指定 时E extends Number,这意味着ENumber或的任何子类型Number。例如,E可能是Integer, Long,Double等。这就是您的代码无法编译的原因 - 例如,如果EInteger,那么能够将 a 分配给Doubletype 的变量是错误的Integer

于 2013-05-29T21:44:46.633 回答
2

然而,这完美无缺!

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) 所以你违反了你为自己制定的规则并且编译器正在告诉你。

于 2013-05-29T21:50:55.063 回答
0

你所知道的就是Eextends Number。类型E可以是Integer,它也是 的子类Number

将 assign 分配new Double(2.2)给名为xtype的变量没有多大意义Integer

于 2013-05-29T21:46:34.870 回答