static <Т, V extends Т> boolean arraysEqual(Т[] х, V[] у) { Параметры типа указываются перед возвращаемым типом. Обратите далее внимание на то, что верхней границей для типа параметра V является тип параметра Т. Таким образом, тип параметра V должен быть таким же, как и у параметра Т, или же быть его подклассом. Такая связь гарантирует, что при вызове метода arraysEqual могут быть указаны только совместимые друг с другом параметры. И наконец, обратите внимание на то обстоятельство, что метод arraysEqual объявлен как static, т.е. его можно вызывать независимо от любого объекта. Но обобщенные методы не обязательно должны быть статическими. В этом смысле на них не накладывается никаких ограничений. А теперь проанализируем, каким образом метод arraysEqual вызывается в методе main . Для этого используется обычный синтаксис, а параметры типа не указываются. И это становится возможным потому, что типы аргументов данного метода распознаются автоматически, а типы параметров Т и V настраиваются соответствующим образом. Рассмотрим в качестве примера первый вызов метода arraysEqual :
if(arraysEqual(nums, nums)) В данном случае типом первого аргумента является Integer, который и заменяет тип параметра Т. Таким же является и тип второго аргумента, а следовательно, тип параметра V также заменяется на Integer. Следовательно, выражение для вызова метода arraysEqual составлено правильно, и оба массива можно сравнить друг с другом. Обратите далее внимание на следующие закомментированные строки:
// if(arraysEqual(nums, dvals)) // System.out.println("nums equals dvals"); Если удалить в них символы комментариев и попытаться скомпилировать программу, то компилятор выдаст сообщение об ошибке. Дело в том, что верхней границей для типа параметра V является тип параметра Т. Этот тип указывается после ключевого ело- ва extends, т.е. тип параметра V может быть таким же, как и у параметра т, или быть его подклассом. В данном случае типом первого аргумента рассматриваемого здесь метода является Integer, заменяющий тип параметра т, тогда как типом второго аргумента — Double, не являющийся подклассом Integer. Таким образом, вызов метода arraysEqual оказывается недопустимым, что и приводит к ошибке при компиляции. Синтаксис объявления метода arraysEqual может быть обобщен. Ниже приведена общая форма объявления обобщенного метода.
<параметры
// Применение обобщенного конструктора,
class Summation {
private int sum;
// Обобщенный конструктор.
}
class GenConsDemo { public static void main(String args[]) { Summation ob = new Summation(4.0); System.out.println("Summation of 4.0 is " + ob.getSum); }
} В классе Summation вычисляется и инкапсулируется сумма всех чисел от 0 до N, причем значение N передается конструктору. Для конструктора Summation указан параметр типа, ограниченный сверху классом Number, и поэтому объект типа Summation может быть создан с использованием любого числового типа, в том числе Integer, Float и Double. Независимо от используемого числового типа, соответствующее значение преобразуется в тип Integer при вызове intValue , а затем вычисляется требуемая сумма. Таким образом, класс Summation совсем не обязательно объявлять обобщенным — достаточно сделать обобщенным только его конструктор. ## Обобщенные интерфейсы Наряду с обобщенными классами и методами существуют также обобщенные интерфейсы. Такие интерфейсы определяются подобно обобщенным классам. Их применение демонстрируется в приведенном ниже примере программы. В ней создается интерфейс Containment, который может быть реализован классами, хранящими одно или несколько значений. Кроме того, в этой программе объявляется метод contains , в котором определяется, содержится ли указанное значение в текущем объекте.
// Пример обобщенного интерфейса.
// В этом интерфейсе подразумевается, что реализующий // его класс содержит одно или несколько значений, interface Containment { // обобщенный интерфейс // Метод contains проверяет, содержится ли // некоторый элемент в объекте класса, // реализующего интерфейс Containment, boolean contains(Т о); }