13

List<String> list = new ArrayList();将导致编译器警告。

但是,以下示例编译时没有任何警告:List<String> list = new ArrayList<>();

我很好奇为什么需要引入钻石运算符。如果类型参数不存在,为什么不只对构造函数进行类型推断(因为它已经为 java 中的静态方法完成并被 google guava 等集合库利用)

编辑:使用毫驼答案作为起点,我查看了实际上是什么类型的擦除,而不仅仅是删除所有类型信息。编译器实际上做了更多(从官方文档复制):

  • 如果类型参数是无界的,则将泛型类型中的所有类型参数替换为其边界或 Object。因此,生成的字节码只包含普通的类、接口和方法。
  • 必要时插入类型转换以保持类型安全。
  • 生成桥方法以保留扩展泛型类型中的多态性。
4

6 回答 6

7

Java 开发人员非常努力地避免改变现有程序的行为。List<String> list = new ArrayList();确实编译,并创建一个原始的 ArrayList。如果对其应用类型推断,结果将是ArrayList<String>,改变其行为并可能导致程序中其他地方的运行时错误。

==================================================== ===========================

经过进一步考虑和@millimoose 的评论,我发现行为的变化将是初始化程序的本地更改,并在编译时检测到。考虑以下程序:

import java.util.ArrayList;
import java.util.List;


public class Test {
  public static void main(String[] args) throws Exception {
    List<Integer> integers = new ArrayList<Integer>();
    integers.add(Integer.valueOf(3));
    integers.add(Integer.valueOf(4));
    List<String> list = new ArrayList(integers);
    System.out.println(list);
  }
}

没有类型推断,它会运行并打印,尽管包含 Integer 引用[3, 4]的 a 存在不良情况。List<String>

ArrayList(Collection<? extends E> c)使用类型推断,它不会编译,因为List<Integer>在创建ArrayList<String>.

于 2013-02-16T11:46:57.460 回答
7

明确的答案必须来自设计该功能的人,但我假设这是为了将其与使用原始类型区分开来,这使得编译器为了兼容性而完全不同。带有原始类型的表达式的处理方式与涉及泛型的表达式的处理方式略有不同,在这个 SO 问题中可以找到一个示例:

于 2013-02-16T11:48:36.763 回答
5

java 5 和 6 的编译器所需的完整语法是:

List<String> list = new ArrayList<String>();

他们决定为我们简化语法,并允许不要在赋值运算符的两侧编写相同的类型参数。但是,<>仍然需要操作员确保您了解自己在做什么。通过写new ArrayList<>()你说“我知道我正在创建泛型类型的实例,并且泛型参数是我在赋值左侧声明的参数。”

于 2013-02-16T11:47:05.697 回答
3

这是Java 7 中对Java 泛型
的改进的一部分。 在您必须编写之前

final List<String> list = new ArrayList<String>();

现在你可以写

final List<String> list = new ArrayList<>();

这是等效的-编译器将为您解决。这不一样

final List list = new ArrayList();

这是一个无类型的List.

于 2013-02-16T11:46:24.917 回答
1

有趣的情况是使用菱形调用构造函数并作为 rawtype成功编译但产生不同的代码。当与方法重载特性混合时,这样的例子是可能的。IIRC,在 OpenJDK 硬币邮件列表的某处有一个示例(不,我不会尝试找到它)。

完全相同的代码在 Java SE 6 和 Java SE 7 上成功运行但产生不同的结果是不可接受的。

为了我的钱,如果在 7 中选择的推理算法会产生不同的代码(与 J2SE 5.0 中的方法泛型类型推理基本相同),我会省略菱形并给出警告(视为错误)。如果您编写了这样的代码,那么确定它是否可编译可能并不明显。

于 2013-07-24T09:33:29.063 回答
0

如果您的项目是在 maven 上构建的,请在 pom.xml 的 tag 下添加以下内容。它完美地工作.. <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.7.0</version> <configuration> <source>1.8</source> <target>1.8</target> </configuration> </plugin> </plugins>

于 2017-10-03T10:20:09.350 回答