用`new`实例化泛型时,包含类型参数之间是否存在实际差异?

And*_*ong 1 java generics syntax

我开始学习Java了,在我的程序中它出现了

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

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

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

所有编译并产生我期望的输出.

有什么实际区别吗?哪个更受欢迎?

Dav*_*rad 5

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

首次引入泛型时,Java 5和Java 6中需要此表单.但是,自Java 7以来,它比必要的更冗长.

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

这个表单是在Java 7中引入的,并且与上面相同,只是编译器推断出类型,以便程序员不需要重复它.这是首选形式.

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

这是使用原始类型而且很糟糕.它允许与Java 5之前的版本向后兼容,但编译器会抱怨原始Stack类型的raw的分配Stack<Integer>是"未经检查的转换".

在这个例子中并不是很清楚,类型安全性正在丢失,因为虽然Stack创建的是原始的Stack<Object>,没有对原始的引用,但是不Stack保留raw ,并且Stack不允许传递参数来填充它,但是可能发生在另一种类型,如ArrayList:

List<Integer> numbers = List.of(12, 34, 56);
List<String> names = new ArrayList(numbers); // "unchecked conversion" warning
for (String name : names) {    // ClassCastException
    System.out.println(name);
}
Run Code Online (Sandbox Code Playgroud)

即使Stack我们打破了创建和分配,问题也变得清晰:

Stack rawStack = new Stack();           // create Stack of raw types
Stack<String> typedStack = rawStack;    // "unchecked conversion" to
                                        //     strongly-typed Stack
rawStack.push(123);                     // push an Integer
typedStack.pop();                       // ClassCastException
Run Code Online (Sandbox Code Playgroud)

在这种情况下,我们保留了对原始堆栈的引用,这使我们违反了类型安全性.你可能会说,"好吧,我永远不会这样做",但是创建它的另一种方法是开始强力输入new Stack<>(),只是两个额外的字符.