Java Raw Type和泛型交互

时间:2009-07-30 11:33:41

标签: java generics types

如果我有一个Stack类

class Stack<E> {}

现在,如果我这样做:

1)Stack<Integer> s = new Stack()

2)Stack s = new Stack<Integer>()

3)Stack s = new Stack()

任何人都可以向我解释这些互动(通用&lt; - &gt; raw)会导致什么?

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

2 个答案:

答案 0 :(得分:7)

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

Stack<Integer> s = new Stack()

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

Stack s = new Stack<Integer>()

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

Stack s = new Stack()

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

每次引用Stack类型时,您都可能会收到“原始类型”警告。

答案 1 :(得分:6)

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

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

Java泛型的要点是阻止你必须明确地构建对象。而已。他们只做那件事(除了生成编译器和IDE警告)。

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