这些泛型类型之间有什么区别?

3
我是一位有用的助手,以下是您需要翻译的内容:

我有两个问题

1.下面这两种声明有什么区别吗?
(情况i)

List<String> li = new ArrayList();  

(case ii)
(情况二)
List<String> li = new ArrayList<String>();  

2. 我知道泛型的好处是在编译时进行更强的类型检查
那么为什么我们需要像case ii中声明一样呢?
因为对象创建只发生在运行时,而声明是在编译时。


2
首先,第一个会生成一个警告。 - Jon Skeet
3个回答

8

代码执行方面没有区别,但第一种形式会生成警告。如果您没有为泛型启用linting,则可能会收到以下消息:

Note: Test.java uses unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.

有了建议的标志,您将获得以下内容:
Test.java:6: warning: [unchecked] unchecked conversion
        List<String> li = new ArrayList();
                          ^
  required: List<String>
  found:    ArrayList
1 warning

警告的原因是,你正在使用一个 new ArrayList()原始类型表达式作为赋值给List<String>类型变量的值,这样做有点不安全。编译器不知道这个原始类型值是否最初就是用来保存其他值的。例如:
List numbers = new ArrayList(); // Raw types on both sides
numbers.add(Integer.valueOf(10));
List<String> li = numbers;
String first = li.get(0);

甚至可以这样做:
List<Integer> numbers = new ArrayList<Numbers>();
numbers.add(Integer.valueOf(10));
List raw = numbers;
List<String> li = raw;
String first = li.get(0);

在这两种情况下,当我们到达最后一行时会出现异常... 如果我们使用通用类型来表示所有表达式,那么它甚至不会编译:

List<Integer> numbers = new ArrayList<Numbers>();
numbers.add(Integer.valueOf(10));
List<String> li = numbers; // Compile-time error
String first = li.get(0);

原始类型仅为向后兼容而存在,在任何可能的情况下应避免使用。

有关更多详细信息,请参见Java 泛型 FAQ


1
末尾的链接损坏了吗? - rocketboy
@Prabhaker:你应该要么得到一个实际的警告,要么得到一个带有-Xlint:unchecked标记的警告指示。我已经编辑了我的答案来表明这一点。 - Jon Skeet
是的,你说得对,我正在收到警告(-Xlint:unchecked)。@Jon Skeet非常感谢您详细的解释。 - Prabhaker A

2
不。钻石语法只是编码/打字的一种简写方式。这两个是相同的。
List<String> a = new ArrayList<String>();  
List<String> a = new ArrayList<>();  

它们在编译过程中被视为相同的,对编译器来说只是一些提示。即使在类型擦除之前,它们也被视为相同。这只是为了方便你而已。


1
这两个 声明 是相同的:它们都是:
List<String>

这两个赋值有所不同。

在运行时(由于类型擦除),它们也是相同的,但在编译时第一个会得到警告,因为你将原始类型分配给了一个有类型的变量。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接