Guide to the Diamond Operator in Java – Java中的钻石运算符指南

最后修改: 2017年 9月 19日

中文/混合/英文(键盘快捷键:t)

1. Overview

1.概述

In this article, we’ll look at the diamond operator in Java and how generics and the Collections API influenced its evolution.

在这篇文章中,我们将探讨Java中的钻石运算符,以及generics和集合API是如何影响其发展的

2. Raw Types

2.原始类型

Prior to Java 1.5, the Collections API supported only raw types – there was no way for type arguments to be parameterized when constructing a collection:

在Java 1.5之前,集合API只支持原始类型–在构造一个集合时,没有办法将类型参数参数化。

List cars = new ArrayList();
cars.add(new Object());
cars.add("car");
cars.add(new Integer(1));

This allowed any type to be added and led to potential casting exceptions at runtime.

这允许添加任何类型,并且导致在运行时出现潜在的铸造异常

3. Generics

3.仿制药

In Java 1.5, Generics were introduced – which allowed us to parameterize the type arguments for classes, including those in the Collections API – when declaring and constructing objects:

在Java 1.5中,引入了泛型–它允许我们在声明和构造对象时对类的类型参数进行参数化,包括集合API中的类型参数。

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

At this point, we have to specify the parameterized type in the constructor, which can be somewhat unreadable:

此时,我们必须在构造函数中指定参数化的类型,这可能有点让人看不懂。

Map<String, List<Map<String, Map<String, Integer>>>> cars 
 = new HashMap<String, List<Map<String, Map<String, Integer>>>>();

The reason for this approach is that raw types still exist for the sake of backward compatibility, so the compiler needs to differentiate between these raw types and generics:

采用这种方法的原因是,为了向后兼容,原始类型仍然存在,所以编译器需要区分这些原始类型和泛型。

List<String> generics = new ArrayList<String>();
List<String> raws = new ArrayList();

Even though the compiler still allows us to use raw types in the constructor, it will prompt us with a warning message:

尽管编译器仍然允许我们在构造函数中使用原始类型,但它会以警告信息提示我们。

ArrayList is a raw type. References to generic type ArrayList<E> should be parameterized

4. Diamond Operator

4.钻石操作员

The diamond operator – introduced in Java 1.7 – adds type inference and reduces the verbosity in the assignments – when using generics:

钻石运算符–在Java 1.7中引入–增加了类型推理并减少了赋值中的冗长性–当使用泛型时

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

The Java 1.7 compiler’s type inference feature determines the most suitable constructor declaration that matches the invocation.

Java 1.7编译器的类型推理功能确定了与调用相匹配的最合适的构造函数声明

Consider the following interface and class hierarchy for working with vehicles and engines:

考虑以下用于处理车辆和发动机的接口和类的层次结构。

public interface Engine { }
public class Diesel implements Engine { }
public interface Vehicle<T extends Engine> { }
public class Car<T extends Engine> implements Vehicle<T> { }

Let’s create a new instance of a Car using the diamond operator:

让我们使用钻石操作符创建一个新的汽车实例。

Car<Diesel> myCar = new Car<>();

Internally, the compiler knows that Diesel implements the Engine interface and then is able to determine a suitable constructor by inferring the type.

在内部,编译器知道Diesel实现了Engine接口,然后能够通过推断类型确定一个合适的构造函数。

5. Conclusion

5.结论

Simply put, the diamond operator adds the type inference feature to the compiler and reduces the verbosity in the assignments introduced with generics.

简单地说,钻石运算符为编译器增加了类型推理功能,并减少了泛型引入的赋值中的繁琐程度。

Some examples of this tutorial can be found on the GitHub project, so feel free to download it and play with it.

本教程的一些例子可以在GitHub项目上找到,所以请随时下载并使用它。