泛型类型和赋值问题

4

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

这是来自Deitel书籍的内容。

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

根据这个,这个子代码必须是正确的。

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

E x=  new Double(2.2);

 }

但编译器告诉我在E x= new Double(2.2);处出现了编译错误,尽管这应该是正确的,因为double是数字

我知道如何通过强制转换来处理和解决一般问题,但我想知道为什么会出现这种情况?


你得到了什么错误? - bmargulies
4个回答

6
仅仅因为 E 是一个数字,并不意味着它是一个 Double
可以这样想,如果 E 是一个整数。E 仍然是一个数字,但现在你正在将 Double 赋给 Integer。所以强制转换的行为是一致的,Number 可以是各种不同的类型,E 也可以是。
编辑 Op:Deitel 的说法仍然是正确的,如果您将 Double 分配给 Number 或 Object,则不需要强制转换。但在这种情况下,E 不是向“上”分配,而是在两种可能不同的数字类型之间分配。“如果 E 是 Short 或 Integer,在这些情况下,您不希望能够将其分配给 Double 而无需强制转换。

这意味着Deitel书中的“Java编程入门”一书引用是错误的吗? - Aladdin
1
不完全正确。该语句准确地描述了泛型是如何在运行时实现的,但并不是关于你应该如何思考泛型的。 - Louis Wasserman
你能解释一下吗?泛型在运行时是如何实现的?我想消除我的疑虑。 - Aladdin
我更新了答案,我并不特别谈论运行时,但所有转换都发生在那个时刻。主要意思是,你没有赋值给一个 Number,而是赋值给一些可能的 Number 子类。这就像将 Double 赋值给 Short 或 BigInteger 赋值给 Integer 一样。所有这些都需要显式转换。 - greedybuddha
1
对象 <- 数字 <- 双精度浮点数。你可以将任何一个赋值给另一个而不需要强制转换。但是,如果假设 E 扩展自 Number,则 E 并不完全等同于 Number。对象 <- 数字 <- E 因此 E 和 Double 都继承自 Number。现在让我们用 Integer 替换 E。数字 <- 整数。你会期望能够将 Double 分配给该整数而无需强制转换吗?(不会)。你会期望能够将 Double 分配给该 E 而无需强制转换吗?(不会)。 - greedybuddha
显示剩余3条评论

3

然而,这个完美地运作了!

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();
  }

}

我们在这里向国内的读者说明... 这不是泛型应该使用的方式。

噢 - 顺便说一下,你遇到问题的原因是没有强制类型转换而导致类型不匹配。

你遇到的问题是一个概念性的问题。在泛型子句中传递的类型<E extends Number>并不是一个占位符,用于最终决定要使用的类型。你不仅仅是延迟了对你将要使用的类型的决定。你正在承诺只使用与子句匹配的类型,如果你打破了这个承诺,编译器必须警告你。

你的代码之所以被拒绝是因为你正在打破这个承诺。你说虽然调用者可以使用任何Number,但你将使用特定的NumberDouble),因此你正在违反你为自己和编译器制定的规则,编译器正在指责你。


3
当你指定 E extends Number 时,这意味着 ENumber 的任何子类型,或者是 Number 本身。例如,E 可以是 IntegerLongDouble 等。这就是为什么你的代码无法编译 - 如果 EInteger,那么将一个 Double 赋值给类型为 Integer 的变量是错误的。

0
你所知道的是 E 扩展了 Number。类型 E 可以是 Integer,它也是 Number 的子类。
new Double(2.2) 赋值给类型为 Integer 的变量 x 没有太多意义。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接