Помимо классов и методов, обобщенными можно объявлять и нтерфейсы. Обобщенные интерфейсы объявляются таким же образом, как и обобщенные классы.
Ниже приведен характерный тому пример. В нем создается обобщенны йинтерфейс MinMax, где объявляются методы min() и max(), которые, как предполагается, должны возвращать минимальное и максимальное значения из некоторого множества объектов.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 |
// Пример применения обобщенного интерфейса // Обобщенный интерфейс MinMax для определения // минимального и максимального значений interface MinMax<T extends Comparable<T>> { T min(); T max(); } // реализовать обобщенный интерфейс MinMax class MyClass<T extends Comparable<T>> implements MinMax<T> { T[] vals; MyClass(T[] o) { vals = o; } // возвратить минимальное значение из массива vals public T min() { T v = vals[0]; for(int i = 1; i < vals.length; i++) { if(vals[i].compareTo(v) < 0) { v = vals[i]; } } return v; } // возвратить максимальное значение из массива vals public T max() { T v = vals[0]; for(int i = 1; i < vals.length; i++) { if(vals[i].compareTo(v) > 0) { v = vals[i]; } } return v; } } class GenIFDemo { public static void main(String args[]) { Integer inums[] = { 3, 16, 2, 48, 6, 10, 33, 4 }; Character chs[] = { 'c', 'b', 'r', 'p', 'w', 'Z' }; MyClass<Integer> iob = new MyClass<Integer>(inums); MyClass<Character> cob = new MyClass<Character>(chs); System.out.println("Максимальное значение в массиве inums: " + iob.max()); System.out.println("Минимальное значение в массиве inums: " + iob.min()); System.out.println("Максимальное значение в массиве chs: " + cob.max()); System.out.println("Минимальное значение в массиве chs: " + cob.min()); } } |
Ниже приведен результат выполнения данной программы.
1 2 3 4 5 6 7 |
pro-java.ru@admin:~$ javac genericinterface.java pro-java.ru@admin:~$ java GenIFDemo Максимальное значение в массиве inums: 48 Минимальное значение в массиве inums: 2 Максимальное значение в массиве chs: w Минимальное значение в массиве chs: Z pro-java.ru@admin:~$ |
Большую часть этой программы нетрудно понять, но некоторые ключевые моменты следует все же пояснить.
Прежде всего обратите внимание на следующее объявление обобщенного интерфейса MinMax:
1 |
interface MinMax<T extends Comparable<T>> { |
Как правило, обобщенный интерфейс объявляется таким же образом, как и обобщенный класс. В данном случае параметр типа T ограничивается сверху интерфейсом Comparable.
Интерфейс Comparable определен в пакете java.lang для целей сравнения объектов. Параметр его типа обозначает тип сравниваемых объектов.
Затем интерфейс MinMax реализуется в классе MyClass. Объявление класса МyClass выглядит следующим образом:
1 |
class MyClass<T extends Comparable<T>> implements MinMax<T> { |
Обратите особое внимание, каким образом параметр типа T сначала объявляется в классе MyClass, а затем передается интерфейсу MinMax.
Интерфейсу MinMax требуется тип класса, реализующего интерфейс Comparable, поэтому в объявлении класса, реализующего этот интерфейс (в данном случае — класса MyClass ), должно быть наложено такое же ограничение.
Более того, однажды наложенное ограничение уже не нужно повторять в операторе implements. В действительности это было бы даже неверно.
Например, приведенная ниже строка неверна и не может быть скомпилирована. Однажды установленный параметр типа просто передается интерфейсу без последующих видоизменений.
1 2 3 |
// Неверно! class MyClass<T extends Comparable<T>> implements MinMax<extends Comparable<T>> { |
Как правило, класс, реализующий обобщенный интерфейс, должен быть также обобщенным — по крайней мере, в тех случаях, когда он принимает параметр типа, передаваемый далее интерфейсу.
Например, следующая попытка объявить класс MyClass приведет к ошибке:
1 |
class MyClass implements MinMax<T> { // Неверно! |
В классе MyClass параметр типа не объявляется, поэтому передать его интерфейсу MinMax никак нельзя.
В данном случае идентификатор параметра типа Т просто неизвестен, и поэтому компилятор выдаст ошибку.
Безусловно, если класс реализует конкретный тип обобщенного интерфейса, то реализующий класс не обязан быть обобщенным, как показано ниже.
1 |
class MyClass implements MinMax<Integer> { // Верно |
Обобщенный интерфейс дает два преимущества. Во-первых, он может быть реализован для разных типов данных.
И во-вторых, он позволяет наложить ограреничения на типы данных, для которых он может быть реализован. В примере интерфейса MinMax вместо параметра типа Т могут быть подставлены только типы классов, реализующих интерфейс Comparable.
Ниже приведена общая синтаксическая форма обобщенного интерфейса.
1 |
interface имя_интерфейса<список_параметров_типа> { // ... |
Здесь список_параметров_типа обозначает разделяемый запятыми список параметров типа.
Когда реализуется обобщенный интерфейс, следует указать аргурменты типа, как показано ниже.
1 2 |
class имя_класса<список_параметров_типа> implements имя_интерфейса<список_аргументов_типа> { |