如果我有一个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之外的其他类型。是的,但如果我有推送方法并尝试存储 除了整数以外的值,编译器会阻止我...所以当我有不安全的操作时?
答案 0 :(得分:7)
这三个都是完全合法的,因为Stack
和Stack<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警告)。
它们仍然有用,可以使您的代码更具可读性,更不容易出错,但最终,在字节代码级别,了解它们没有做任何事情是很重要的。