Java Урок 64: ОБОБЩЕНИЯ, обобщенный метод

Методы внутри обобщенного класса могут использовать параметр типа, а
следовательно, обобщения относятся также к параметрам методов. Однако
можно объявить обобщенный метод, который сам по себе использует один или более параметров типа. Более того, можно объявить обобщенный метод, который включен в параметризованный (необобщенный) класс.

Скачать исходники для статьи можно ниже

Начнем с примера.
В следующей программе объявлен необобщенный класс по имени 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(), можно обобщить.
Вот синтаксис обобщенного метода:

<список_параметров_типа> ссылочный_тип имя_метода (список_параметров)
{//...

Во всех случаях список_параметров_типа — это разделенный запятыми список параметров типа. Обратите внимание на то, что для обобщенного метода список параметров типа предшествует типу возвращаемого значения.

Введите свой email адрес для того, чтобы подписаться на мой блог:


knopkisoc

Добавить комментарий