Методы внутри обобщенного класса могут использовать параметр типа, а
следовательно, обобщения относятся также к параметрам методов. Однако
можно объявить обобщенный метод, который сам по себе использует один или более параметров типа. Более того, можно объявить обобщенный метод, который включен в параметризованный (необобщенный) класс.
Скачать исходники для статьи можно ниже
Начнем с примера.
В следующей программе объявлен необобщенный класс по имени GenMethDemo и статический обобщенный метод внутри класса по имени isIn(). Метод isIn() определяет, является ли объект членом массива. Он может
быть использован с любым типом объектов и массивов до тех пор, пока массив содержит объекты, совместимые с типом искомого объекта.
// Демонстрация простого обобщенного метода,
class GenMethDemo {
// Определение, содержится ли объект в массиве.
static <Т, V extends Т> boolean isIn(T х, V[] у) {
for(int i=0; i < у.length; i++){
if(x.equals(y[i])) return true;
}
return false;
}
public static void main(String args[]) {
// Применение isln() для Integer.
Integer nums[] = { 1, 2, 3, 4, 5 };
if(isIn(2, nums)){
System.out.println("2 содержится в nums");
}
if(!isIn(7, nums)){
System.out.println("7 не содержится в nums");
}
System.out.println();
// Применение isIn() для String.
String strs[] = { "один", "два", "три", "четыре", "пять" };
if(isIn("два", strs)){
System.out.println("два содержится в strs");
}
if(!isIn("семь", strs)) {
System.out.println("семь не содержится в strs");
}
// He скомпилируется! Типы должны быть совместимыми.
// if(isIn("два", nums))
// System.out.println("два содержится в strs ");
}
}
Результат работы этой программы показан ниже:
2 содержится в nums
7 не содержится в nums
два содержится в strs
семь не содержится в strs
Рассмотрим метод isIn() поближе. Для начала посмотрите, как объявлен метод следующей строке:
static <Т, V extends Т> boolean isIn(T х, V[] у) {
Параметр типа объявлен перед типом возвращаемого значения метода. Тип V ограничен сверху типом Т. То есть тип V либо должен быть тем же типом, что и Т, либо типом его подклассов. Это отношение указывает, что метод isIn() может быть вызван только с аргументами, совместимыми между собой.
Также обратите внимание на то, что метод isIn() статический, что позволяет вызывать его независимо от какого-либо объекта. Однако ясно, что обобщенные методы могут быть как статическими, так и нестатическими. Нет никаких ограничений на этот счет.
Теперь обратите внимание на то, как метод isIn() вызывается внутри метода main(), — с нормальным синтаксисом вызовов, без необходимости указывать аргументы типа.
Дело в том, что типы аргументов подставляются автоматически,и типы Т и V определяются соответственно.
Например, в вызове if (isIn(2, nums)) тип первого аргумента — Integer (благодаря автоупаковке), поэтому вместо параметра Т подставляется класс Integer.
Базовый тип второго аргумента — также класс Integer, что подставляет его и вместо параметра V. Во втором вызове используются типы String, и вместо параметров типа Т и V подставляются классы String.
Теперь обратите внимание на закомментированный код.
// if(isIn("два", nums))
// System.out.println("два содержится в strs ");
Если вы уберете комментарии с этих строк, а затем попытаетесь скомпилировать программу, то получите ошибку. Причина в том, что тип параметра типа V ограничен типом параметра типа Т в конструкции extends объявления параметра типа V.
Это значит, что параметр V должен иметь либо тип Т, либо тип его
подкласса. А в этом случае первый аргумент имеет тип String, но второй — тип Integer, который не является подклассом класса String. Это вызовет ошибку несоответствия типов во время компиляции. Такая способность обеспечивать безопасность типов — одно из наиболее существенных преимуществ обобщенных методов.
Синтаксис, использованный для создания метода isIn(), можно обобщить.
Вот синтаксис обобщенного метода:
<список_параметров_типа> ссылочный_тип имя_метода (список_параметров)
{//...
Во всех случаях список_параметров_типа — это разделенный запятыми список параметров типа. Обратите внимание на то, что для обобщенного метода список параметров типа предшествует типу возвращаемого значения.


