openjdk.ruOpenJDK на русском

JEP 101: Generalized Target-Type Inference

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

ОтветственныйMaurizio Cimadamore
ТипFeature
ОбластьSE
СтатусClosed / Delivered
Выпуск8
Компонентspecification / language
JSR335
Обсуждениеlambda dash dev at openjdk dot java dot net
ТрудоёмкостьM
ДлительностьM
Зависит отJEP 126: Lambda Expressions & Virtual Extension Methods
РецензентыBrian Goetz
ОдобренBrian Goetz
Создан2011/02/22 20:00
Обновлён2015/02/26 22:25
Задача8046091

Аннотация

Плавно расширить область применения вывода типов для методов, чтобы поддерживались (i) вывод в контексте метода и (ii) вывод в цепочках вызовов.

Цели

  • Добавить поддержку вывода параметров типа метода в контексте метода
  • Добавить поддержку вывода параметров типа метода в цепочках вызовов

Что не является целью

  • Глобальный вывод типов

Критерии успеха

Сделать generics удобнее, сократив число пограничных случаев вывода типов для методов. Сделать код понятнее, сократив число явных аргументов типа в вызовах обобщённых методов.

Мотивация

Начиная с JDK 5 компилятор автоматически выводит аргументы типа в вызовах обобщённых методов. Вывод типов важен не только потому, что явные аргументы типа несколько неудобны и многословны, но прежде всего потому, что многие программисты с ними незнакомы и поэтому не могут справиться с ситуациями, в которых вывод аргументов типа не даёт правильного результата. Поэтому важно свести к минимуму случаи, в которых вывод типов для методов не срабатывает; мы считаем, что вывод типов для методов можно значительно улучшить, добавив поддержку следующих возможностей: (i) вывод в позиции аргумента и (ii) вывод в цепочках вызовов.

Описание

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

i. Вывод в позиции аргумента

Рассмотрим следующее объявление класса:

class List<E> {
   static <Z> List<Z> nil() { ... };
   static <Z> List<Z> cons(Z head, List<Z> tail) { ... };
   E head() { ... }
}

Тип результата обобщённого метода, например List.nil(), может быть выведен из правой части присваивания:

List<String> ls = List.nil();

Механизм вывода типов компилятора определяет, что аргумент типа в вызове List.nil() действительно String. Кажется разумным, чтобы компилятор мог выводить тип и тогда, когда результат такого вызова обобщённого метода передаётся в другой метод, как показано ниже:

List.cons(42, List.nil()); //error: expected List<Integer>, found List<Object>

К сожалению, в JDK 5/6/7 это не разрешено — программисту остаётся только указать аргумент типа явно:

List.cons(42, List.<Integer>nil());

Было бы хорошо, если бы вывод аргументов типа учитывал тип формального параметра в вызове метода (target typing).

ii. Вывод в цепочках вызовов

Другая довольно частая проблема возникает, когда вызовы обобщённых методов объединены в цепочку, как показано ниже:

String s = List.nil().head(); //error: expected String, found Object

Тип в правой части приведённого выше присваивания при выводе аргументов типа не используется — поэтому программисту (снова) остаётся только указать аргументы типа вручную, например:

String s = List.<String>nil().head();

И здесь было бы хорошо избавить программиста от явных аргументов типа, позволив типу в правой части присваивания (String) распространяться по цепочке вызовов обобщённых методов.

Альтернативы

Указывать параметры типа вручную (как сейчас).

Тестирование

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

Особых требований к платформе или оборудованию нет.

Риски и допущения

Как отмечено выше, главный риск этого изменения в том, что любое изменение, затрагивающее вывод типов для методов, может нарушить обратную совместимость. Поскольку описанные в этом документе изменения затрагивают тонкую область языка/компилятора Java (систему типов), нужны ресурсы на тестирование, чтобы проверить, что предлагаемое изменение не нарушает обратную совместимость неожиданным образом. При необходимости прототип с поддержкой описанной возможности можно предоставить в относительно короткий срок (т. е. до завершения проекта Lambda).

Зависимости

Эта работа зависит от JEP проекта Lambda — проекту Lambda нужен новый способ вывода типов, называемый выводом по целевому типу (target-typing inference); с его помощью типы формальных параметров лямбда-выражения выводятся из контекста, в котором это выражение используется. Одна часть этой работы (вывод в контексте метода) — просто обобщение подхода, применённого в проекте Lambda. Другая часть этой работы (вывод в цепочках вызовов) — улучшение вывода, которое поможет применять проект Lambda для разработки LinQ-подобных.

Влияние

  • Клиенты: более понятный код (меньше явных аргументов типа) — проще использовать обобщённые методы/конструкторы/diamond.
  • CCC: для изменений вывода типов потребуется CCC
  • Совместимость: новая схема вывода может незаметно изменить множество компилируемых программ — крайне важно, чтобы команда JCK протестировала изменения.
  • Документация: нет
  • JCP: нет
  • L10N: минимальное влияние: вероятно, добавятся новые сообщения об ошибках