Java Raw Type和泛型交互

xde*_*000 7 java generics types

如果我有一个Stack类

class Stack<E> {}
Run Code Online (Sandbox Code Playgroud)

现在,如果我这样做:

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

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

3) Stack s = new Stack()

任何人都能解释一下这些互动(通用< - > raw)会导致什么?

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

Chr*_*way 7

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

Stack<Integer> s = new Stack()
Run Code Online (Sandbox Code Playgroud)

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

Stack s = new Stack<Integer>()
Run Code Online (Sandbox Code Playgroud)

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

Stack s = new Stack()
Run Code Online (Sandbox Code Playgroud)

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

每次引用类型时,您也可能会收到"原始类型"警告Stack.


cle*_*tus 6

所有这些都是不安全的,因为Java泛型,由于类型擦除,只是语法糖.例如,这是完全有效的Java代码:

Stack<Integer> s = new Stack<Integer>();
Stack<Double> s2 = (Stack<Double>)s;
s2.push(3.3d);
Run Code Online (Sandbox Code Playgroud)

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

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