На этом шаге мы рассмотрим обобщенные методы
Java имеется также возможность определить отдельный метод с параметрами (или переменными) типа следующим образом:
class ArrayAlg { ... public static <T> T getMiddle(T... a) { return a[a.length >> 1]; } ... }
Этот метод определен в обычном, а не в обобщенном классе. Тем не менее это обобщенный метод, на что указывают угловые скобки и переменная типа. Обратите внимание на то, что переменная типа вводится после модификаторов (в данном случае public static) и перед возвращаемым типом.
Обобщенные методы можно определять как в обычных, так и в обобщенных классах. Когда вызывается обобщенный метод, ему можно передать конкретные типы данных, заключая их в угловые скобки перед именем метода, как показано ниже:
String middle = ArrayAlg.<String>getMiddle("param1", "param2", "abacaba");
В данном случае (как и вообще) при вызове метода можно пропустить параметр типа String. У компилятора имеется достаточно информации, чтобы вывести из такого обобщения именно тот метод, который требуется вызвать. Он сравнивает тип параметра метода и приходит выводу, что вместо обобщенного типа T следует подставить тип String, что равнозначно следующему вызову:
String middle = ArrayAlg.getMiddle("param1", "param2", "abacaba");
Выводимость типов в обобщенных методах практически всегда действует исправно. Но иногда компилятор ошибается, и тогда приходятся выяснять причину ошибок компилирования. Рассмотрим следующий пример:
double middle = ArrayAlg.getMiddle(1, 2.0, 3);
Данный код не скомпилируется. Данный код можно интерпретировать двояко и в обоих случаях - правильно. По существу, компилятор выполняет автоупаковку в один объект типа Double и два объекта типа Integer, а затем пытается найти общий супертип для этих классов. И таких типов два: класс Number и интерфейс Comparable, который сам является обобщенным. В этом случае для устранения ошибки методу следует передать все параметры со значениями типа double.
На следующем шаге мы рассмотрим ограничение на переменные типа