Обобщенный вывод типа цели в Java

Обобщенный вывод типа цели в Java

1. Вступление

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

В этом руководстве мы рассмотрим эту концепцию на примерах кода.

2. Дженерики

Обобщения дали нам много преимуществ, таких как повышение безопасности типов, избежание ошибок приведения типов и универсальные алгоритмы. Вы можете узнать больше о дженериках в этомarticle.

Однако введениеgenerics resulted in the necessity of writing boilerplate code due to the need to pass type parameters. Вот некоторые примеры:

Map> mapOfMaps = new HashMap>();
List strList = Collections.emptyList();
List intList = Collections.emptyList();

3. Вывод типа перед Java 8

Чтобы уменьшить ненужную многословность кода, в Java был введен вывод типов, который is the process of automatically deducing unspecified data types of an expression based on the contextual information.

Теперь мы можем вызывать одни и те же универсальные типы и методы без указания типов параметров. Компилятор автоматически определяет типы параметров при необходимости.

Мы можем увидеть тот же код, используя новую концепцию:

List strListInferred = Collections.emptyList();
List intListInferred = Collections.emptyList();

В приведенном выше примере на основе ожидаемых возвращаемых типовList<String> иList<Integer> компилятор может вывести параметр типа для следующего универсального метода:

public static final  List emptyList()

Как мы видим, полученный код является лаконичным. Now, we can call generic methods as an ordinary method if the type parameter can be inferred.с

В Java 5 мы могли бы делать Type-Inference в определенных контекстах, как показано выше.

Java 7 расширила контексты, в которых это могло быть выполнено. Он ввел алмазный оператор<>. Вы можете узнать больше о ромбовидном операторе в этомarticle.

Теперьwe can perform this operation for generic class constructors in an assignment context.  Один из таких примеров:

Map> mapOfMapsInferred = new HashMap<>();

Здесь компилятор Java использует ожидаемый тип присвоения для вывода параметров типа конструкторуHashMap.

4. Обобщенный вывод типа цели - Java 8

Java 8 еще больше расширила возможности вывода типов. Мы называем эту расширенную возможность вывода обобщенным выводом типа цели. Вы можете прочитать технические подробностиhere.

Java 8 также представила лямбда-выражения. Lambda Expressions do not have an explicit type.  Their type is inferred by looking at the target type of the context or situation. Целевой тип выражения - это тип данных, ожидаемый компилятором Java в зависимости от того, где появляется выражение.

Java 8 поддерживает вывод с использованием Target-Type в контексте метода. When we invoke a generic method without explicit type arguments, the compiler can look at the method invocation and corresponding method declarations to determine the type argument (or arguments) that make the invocation applicable.с

Давайте посмотрим на пример кода:

static  List add(List list, T a, T b) {
    list.add(a);
    list.add(b);
    return list;
}

List strListGeneralized = add(new ArrayList<>(), "abc", "def");
List intListGeneralized = add(new ArrayList<>(), 1, 2);
List numListGeneralized = add(new ArrayList<>(), 1, 2.0);

В кодеArrayList<> явно не предоставляет аргумент типа. Таким образом, компилятор должен сделать вывод. Сначала компилятор изучает аргументы метода add. Затем он просматривает параметры, передаваемые при разных вызовах.

It performs invocation applicability inference analysis to determine whether the method applies to these invocations. Если из-за перегрузки применимо несколько методов, компилятор выберет наиболее конкретный метод.

Тогдаthe compiler performs invocation type inference analysis to determine the type arguments.The expected target types are also used in this analysis. Он выводит аргументы в трех экземплярах какArrayList<String>,ArrayList<Integer> иArrayList<Number>.

Вывод типа цели позволяет нам не указывать типы для параметров лямбда-выражения:

List intList = Arrays.asList(5, 2, 4, 2, 1);
Collections.sort(intList, (a, b) -> a.compareTo(b));

List strList = Arrays.asList("Red", "Blue", "Green");
Collections.sort(strList, (a, b) -> a.compareTo(b));

Здесь параметрыa иb не имеют явно определенных типов. Их типы выводятся какInteger в первом лямбда-выражении и какString во втором.

5. Заключение

В этой быстрой статье мы рассмотрели вывод типа, который наряду с обобщениями и лямбда-выражениями позволяет нам писать краткий код Java.

Как обычно, полный исходный код можно найтиover on Github.