Перейти к основному содержимому

Руководство по оператору Diamond в Java

· 2 мин. чтения

1. Обзор

В этой статье мы рассмотрим оператор Diamond в Java и то, как дженерики и Collections API повлияли на его эволюцию .

2. Необработанные типы

До Java 1.5 API коллекций поддерживал только необработанные типы — не было возможности параметризовать аргументы типа при создании коллекции:

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

Это позволяло добавлять любой тип и приводило к потенциальным исключениям приведения типов во время выполнения .

3. Дженерики

В Java 1.5 были введены Generics — которые позволили нам параметризовать аргументы типа для классов , в том числе и в Collections API — при объявлении и конструировании объектов:

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

На этом этапе мы должны указать параметризованный тип в конструкторе , который может быть несколько нечитаемым:

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

Причина такого подхода в том, что необработанные типы все еще существуют ради обратной совместимости , поэтому компилятору необходимо различать эти необработанные типы и дженерики:

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

Несмотря на то, что компилятор по-прежнему позволяет нам использовать необработанные типы в конструкторе, он выдаст предупреждающее сообщение:

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

4. Алмазный оператор

Алмазный оператор, представленный в Java 1.7 , добавляет вывод типа и уменьшает многословие в присваиваниях — при использовании дженериков :

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

Функция определения типа компилятора Java 1.7 определяет наиболее подходящее объявление конструктора, соответствующее вызову .

Рассмотрим следующий интерфейс и иерархию классов для работы с транспортными средствами и двигателями:

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

Давайте создадим новый экземпляр Car с помощью оператора Diamond:

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

Внутри компилятор знает, что Diesel реализует интерфейс Engine , а затем может определить подходящий конструктор, выведя тип.

5. Вывод

Проще говоря, алмазный оператор добавляет компилятору возможность вывода типов и уменьшает количество детализации присваиваний, введенных с помощью дженериков.

Некоторые примеры этого туториала можно найти в проекте GitHub , так что не стесняйтесь загружать его и играть с ним.