【问题标题】:Java Raw Type and generics interactionJava 原始类型和泛型交互
【发布时间】:2010-11-15 09:59:11
【问题描述】:

如果我有一个 Stack 类

class Stack<E> {}

现在如果我这样做:

1)Stack&lt;Integer&gt; s = new Stack()

2)Stack s = new Stack&lt;Integer&gt;()

3)Stack s = new Stack()

谁能解释一下这些交互(通用原始)的原因?

主要是我的疑问在于第 1 点。事实上,如果我这样做是不安全的,因为该堆栈可以存储除整数以外的类型。是的,但如果我有推送方法并尝试存储 一个整数以外的值,编译器会阻止我......所以当我有那个不安全的操作时?

【问题讨论】:

  • 我不明白 - 你想要有一个堆栈,你可以在其中推送其他东西,然后是整数(例如整数和双精度数)还是只想使用一种类型的堆栈(整数) 让编译器帮你?
  • 不,我想要一个具有一种类型的堆栈,并且想知道如果我执行该任务会发生什么。

标签: java generics types


【解决方案1】:

它们都是不安全的,因为 Java 泛型,凭借type erasure,只是语法糖。例如,这是完全有效的 Java 代码:

Stack<Integer> s = new Stack<Integer>();
Stack<Double> s2 = (Stack<Double>)s;
s2.push(3.3d);

Java 泛型的意义在于,您不必明确地转换对象。而已。它们仅此而已(除了生成编译器和 IDE 警告)。

它们仍然很有用,可以使您的代码更具可读性和更不容易出错,但最终,在字节码级别,重要的是要了解它们没有做任何事情。

【讨论】:

  • 不是 OP 的第 2 种情况,编译器足够聪明地推断出 s 的泛型类型参数吗?
  • 是的,但在第 1 点编译器会建议我是否尝试(通过推送操作)放置除整数以外的对象。因此,泛型可能不仅是“语法糖”,而且第 1 点也改变了编译器的行为(语义)。所以我还是不明白哪里不安全......请给我一个更分析的解释吗?
【解决方案2】:

这三个都是完全合法的,因为StackStack&lt;Integer&gt; 之间没有实际的运行时差异,但是这三个都会导致编译器警告。

Stack<Integer> s = new Stack()

这将导致“未经检查的转换”警告,因为将原始类型转换为参数化类型通常是不安全的。但是,在这种情况下这样做是非常安全的:推送 Integer 值不会导致任何错误;推送非Integer 值将导致类型错误。

Stack s = new Stack<Integer>()

这是从参数化类型到原始类型的合法转换。您将能够推送任何类型的值。但是,任何此类操作都会导致“未经检查的调用”警告。

Stack s = new Stack()

同样,这是合法的,没有隐式转换。您将能够推送任何类型的值。但是,任何此类操作都会导致“未经检查的调用”警告。

您也可能在任何时候引用Stack 类型时收到“原始类型”警告。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-04-03
    • 1970-01-01
    • 1970-01-01
    • 2018-06-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多