1. введение
Вывод типов был введен в Java 5 в дополнение к введению универсальных средств и был существенно расширен в следующих выпусках Java, что также называется Обобщенным выводом целевого типа.
В этом уроке мы рассмотрим эту концепцию с примерами кода.
2. Дженерики
Дженерики предоставили нам множество преимуществ, таких как повышенная безопасность типов, предотвращение ошибок приведения типов и универсальные алгоритмы. Вы можете прочитать больше о дженериках в этой статье .
Однако внедрение дженериков привело к необходимости написания шаблонного кода из-за необходимости передачи параметров типа . Вот некоторые примеры:
Map> mapOfMaps = new HashMap >(); List strList = Collections. emptyList(); List intList = Collections. emptyList();
3. Введите Вывод Перед Java 8
Чтобы уменьшить ненужную многословность кода, в Java был введен вывод типов, который представляет собой процесс автоматического вывода неопределенных типов данных выражения на основе контекстной информации.
Теперь мы можем вызывать одни и те же универсальные типы и методы без указания типов параметров. Компилятор автоматически определяет типы параметров, когда это необходимо.
Мы можем увидеть тот же код, используя новую концепцию:
ListstrListInferred = Collections.emptyList(); List intListInferred = Collections.emptyList();
В приведенном выше примере на основе ожидаемых возвращаемых типов List<Строка> и List<Целое число> компилятор может вывести параметр типа для следующего универсального метода:
public static finalList emptyList()
Как мы видим, полученный код лаконичен. Теперь мы можем вызывать универсальные методы как обычный метод, если можно вывести параметр типа.
В Java 5 мы могли бы выполнять вывод типов в определенных контекстах, как показано выше.
Java 7 расширила контексты, в которых это могло быть выполнено. Он представил алмазного оператора <> . Вы можете прочитать больше об алмазном операторе в этой статье .
Теперь мы можем выполнить эту операцию для конструкторов универсальных классов в контексте назначения. Одним из таких примеров является:
Map> mapOfMapsInferred = new HashMap<>();
Здесь компилятор Java использует ожидаемый тип назначения для вывода параметров типа в HashMap конструктор.
4. Обобщенный вывод целевого типа – Java 8
Java 8 еще больше расширила область вывода типов. Мы называем эту расширенную возможность вывода Обобщенным выводом целевого типа. Вы можете ознакомиться с техническими подробностями здесь .
Java 8 также представила Лямбда-выражения. Лямбда-выражения не имеют явного типа. Их тип определяется путем анализа целевого типа контекста или ситуации. Целевой тип выражения-это тип данных, который ожидает компилятор Java в зависимости от того, где появляется выражение.
Java 8 поддерживает вывод с использованием целевого типа в контексте метода. Когда мы вызываем универсальный метод без явных аргументов типа, компилятор может просмотреть вызов метода и соответствующие объявления методов, чтобы определить аргумент типа (или аргументы), которые делают вызов применимым.
Давайте рассмотрим пример кода:
staticList 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. Затем он просматривает параметры, передаваемые при разных вызовах.
Он выполняет вывод применимости вызова анализ, чтобы определить, применим ли метод к этим вызовам . Если из-за перегрузки применимо несколько методов, компилятор выберет наиболее конкретный метод.
Затем компилятор выполняет вывод типа вызова анализ для определения аргументов типа. В этом анализе также используются ожидаемые целевые типы . Он выводит аргументы в трех экземплярах как ArrayList<Строка> , ArrayList<Целое число> и ArrayList<Число> .
Вывод целевого типа позволяет нам не указывать типы для параметров лямбда-выражения:
ListintList = 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 не имеют явно определенных типов. Их типы выводятся как Целое число в первом лямбда-выражении и как Строка во втором.
5. Заключение
В этой краткой статье мы рассмотрели вывод типов, который наряду с универсальными и лямбда-выражениями позволяет нам писать сжатый Java-код.
Как обычно, полный исходный код можно найти на Github .