Методы внутри обобщенного класса могут использовать параметр типа, а
следовательно, обобщения относятся также к параметрам методов. Однако
можно объявить обобщенный метод, который сам по себе использует один или более параметров типа. Более того, можно объявить обобщенный метод, который включен в параметризованный (необобщенный) класс.
Скачать исходники для статьи можно ниже
Начнем с примера.
В следующей программе объявлен необобщенный класс по имени 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(), можно обобщить.
Вот синтаксис обобщенного метода:
<список_параметров_типа> ссылочный_тип имя_метода (список_параметров) {//...
Во всех случаях список_параметров_типа — это разделенный запятыми список параметров типа. Обратите внимание на то, что для обобщенного метода список параметров типа предшествует типу возвращаемого значения.