Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Герберт Шилдт. Java 2, v5.0 (Tiger). Новые возм...doc
Скачиваний:
5
Добавлен:
01.03.2025
Размер:
1.21 Mб
Скачать

Создание настраиваемого метода

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

Начнем с примера. В программе из листинга 3.8 объявляется ненастраивае-мый класс, названный GenMethDemo, и внутри класса статический настраиваемый метод с именем isIn (). Метод isIn ( ) определяет, является ли объект элементом массива. Он может использоваться с объектом любого типа и любым массивом, при условии, что массив содержит объекты, тип которых сопоставим с типом проверяемого объекта.

Листинг 3.8. Демонстрация простого настраиваемого метода

class GenMethDemo {

// Определяет, является ли объект элементом массива.

static <T, V extends T> boolean isIn(T x, V[] y) {

for(int i=0; i < y.length; i++)

if(x.equals(y[i])) return true;

return false;

}

public static void main(String args[]) {

// Использует метод isin() для объектов типа Integer.

Integer nums[] = { 1, 2, 3, 4, 5 };

if(isIn(2, nums))

System.out.println("2 is in nums");

if(!isIn(7, nums))

System.out.println("7 is not in nums");

System.out.println();

// Использует метод isIn() для объектов типа String.

String strs[] = { "one", "two", "three",

"four", "five" };

if(isIn("two", strs))

System.out.println("two is in strs");

if(!isIn("seven", strs))

System.out.println("seven is not in strs");

// Opps! He откомпилирует, поскольку типы не совместимы.

// if(isln("two", nums})

// System.out.println("two is in strs”);

}

}

Далее приведен вывод результатов работы программы из листинга 3.8:

2 is in nums

7 is not in nums

two is in strs

seven is not in strs

Рассмотрим подробно метод isIn(). Во-первых, обратите внимание на его объявление, приведенное в следующей строке:

static <T, V extends T> boolean isIn(T х, V[] у) {

Параметры типа указаны перед типом значения, возвращаемого методом. Во-вторых, обратите внимание на то, что параметр типа v ограничен сверху параметром типа т. Следовательно, тип параметра v должен быть таким же, как у параметра T или классом, производным от T. Описанная взаимосвязь параметров обеспечивает вызов метода isIn( ) с аргументами, сопоставимыми друг с другом. Отметьте также то, что метод isIn( ) статический, т. е. может вызываться независимо от какого-либо объекта. Однако настраиваемые методы могут быть как статическими, так и нестатическими, на этот счет нет никаких ограничений.

Теперь рассмотрим как метод isIn () вызывается в методе main ( ) с использованием обычного синтаксиса вызова без необходимости указания аргументов типа. Это возможно благодаря тому, что типы аргументов распознаются автоматически и типы Т и V настраиваются соответственно. Например, в первом вызове:

if(isIn(2, nums))

тип первого аргумента — Integer (в результате автоупаковки), что вызывает замену типа T классом Integer, Базовый тип второго аргумента тоже Integer, что в свою очередь ведет к замене параметра V классом Integer.

Во втором вызове используется тип String, и параметры T и V заменяются классом String.

Теперь рассмотрим строки комментария приведенные далее:

// if(isIn("two", nums))

// System.out.println("two is in strs");

Если Вы удалите знаки комментария и попробуете откомпилировать программу, то получите сообщение об ошибке. Причина заключается в том, что параметр типа v ограничен типом T с помощью ключевого слова extends при объявлении параметра V. Это означает, что тип параметра V должен быть таким же, как тип параметра T или классом, производным от типа T. В нашем случае у первого аргумента тип — String, заменяющий T классом String, а у второго аргумента тип Integer который не является подклассом типа String. Подобная ситуация приводит к появлению ошибки несовместимости типов на этапе компиляции. Описанная способность обеспечения типовой безопасности — одно из важнейших преимуществ настраиваемых методов.

Далее приведена синтаксическая запись для настраиваемого метода:

<type-param-list> ret-type meth-name(param-list) { //...

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