Java — дженерики
Было бы неплохо, если бы мы могли написать единственный метод сортировки, который мог бы сортировать элементы в массиве Integer, массиве String или массиве любого типа, который поддерживает упорядочение.
Java Универсальный Методы и универсальные классы позволяют программистам указывать с помощью одного объявления метода набор связанных методов или с помощью одного объявления класса набор связанных типов соответственно.
Универсальные шаблоны также обеспечивают безопасность типов во время компиляции, что позволяет программистам обнаруживать недопустимые типы во время компиляции.
Используя концепцию Java Generic, мы могли бы написать универсальный метод для сортировки массива объектов, а затем вызвать универсальный метод для массивов Integer, Double, String и т. д. для сортировки элементов массива.
Общие методы
Вы можете написать одно универсальное объявление метода, которое можно вызывать с аргументами разных типов. В зависимости от типов аргументов, переданных универсальному методу, компилятор соответствующим образом обрабатывает каждый вызов метода. Ниже приведены правила определения общих методов —
-
Все объявления универсальных методов имеют раздел параметра типа, разделенный угловыми скобками (<и>), который предшествует типу возвращаемого значения метода (
в следующем примере). -
Каждый раздел параметров типа содержит один или несколько параметров типа, разделенных запятыми. Параметр типа, также известный как переменная типа, представляет собой идентификатор, указывающий универсальное имя типа.
-
Параметры типа можно использовать для объявления возвращаемого типа и выступать в качестве заполнителей для типов аргументов, передаваемых универсальному методу, которые известны как аргументы фактического типа.
-
Тело универсального метода объявляется так же, как и тело любого другого метода. Обратите внимание, что параметры типа могут представлять только ссылочные типы, а не примитивные типы (например, int, double и char).
Пример
Следующий пример иллюстрирует, как мы можем напечатать массив другого типа, используя один универсальный метод —
Живая демонстрацияpublic class GenericMethodTest { // generic method printArray public static < E > void printArray( E[] inputArray ) { // Display array elements for(E element : inputArray) { System.out.printf("%s ", element); } System.out.println(); } public static void main(String args[]) { // Create arrays of Integer, Double and Character Integer[] intArray = { 1, 2, 3, 4, 5 }; Double[] doubleArray = { 1.1, 2.2, 3.3, 4.4 }; Character[] charArray = { 'H', 'E', 'L', 'L', 'O' }; System.out.println("Array integerArray contains:"); printArray(intArray); // pass an Integer array System.out.println("\nArray doubleArray contains:"); printArray(doubleArray); // pass a Double array System.out.println("\nArray characterArray contains:"); printArray(charArray); // pass a Character array } }
Это даст следующий результат —
Вывод
Array integerArray contains: 1 2 3 4 5 Array doubleArray contains: 1.1 2.2 3.3 4.4 Array characterArray contains: H E L L O
Параметры ограниченного типа
Могут быть случаи, когда вы захотите ограничить типы типов, которые разрешено передавать параметру типа. Например, метод, работающий с числами, может принимать только экземпляры класса Number или его подклассов. Для этого и нужны параметры ограниченного типа.
Чтобы объявить параметр ограниченного типа, перечислите имя параметра типа, за которым следует ключевое слово extends, за которым следует его верхняя граница.
Пример
Следующий пример иллюстрирует, как extends используется в общем смысле для обозначения либо «расширения» (как в классах), либо «реализует» (как в интерфейсах). Этот пример является универсальным методом для возврата наибольшего из трех сопоставимых объектов —
Живая демонстрацияpublic class MaximumTest { // determines the largest of three Comparable objects public static <T extends Comparable<T>> T maximum(T x, T y, T z) { T max = x; // assume x is initially the largest if(y.compareTo(max) > 0) { max = y; // y is the largest so far } if(z.compareTo(max) > 0) { max = z; // z is the largest now } return max; // returns the largest object } public static void main(String args[]) { System.out.printf("Max of %d, %d and %d is %d\n\n", 3, 4, 5, maximum( 3, 4, 5 )); System.out.printf("Max of %.1f,%.1f and %.1f is %.1f\n\n", 6.6, 8.8, 7.7, maximum( 6.6, 8.8, 7.7 )); System.out.printf("Max of %s, %s and %s is %s\n","pear", "apple", "orange", maximum("pear", "apple", "orange")); } }
Это даст следующий результат —
Вывод
Max of 3, 4 and 5 is 5 Max of 6.6,8.8 and 7.7 is 8.8 Max of pear, apple and orange is pear
Общие классы
Объявление универсального класса выглядит как объявление неуниверсального класса, за исключением того, что за именем класса следует раздел параметра типа.
Как и в случае с универсальными методами, раздел параметров типа универсального класса может иметь один или несколько параметров типа, разделенных запятыми. Эти классы называются параметризованными классами или параметризованными типами, поскольку они принимают один или несколько параметров.
Пример
Следующий пример иллюстрирует, как мы можем определить универсальный класс —
Живая демонстрацияpublic class Box<T> { private T t; public void add(T t) { this.t = t; } public T get() { return t; } public static void main(String[] args) { Box<Integer> integerBox = new Box<Integer>(); Box<String> stringBox = new Box<String>(); integerBox.add(new Integer(10)); stringBox.add(new String("Hello World")); System.out.printf("Integer Value :%d\n\n", integerBox.get()); System.out.printf("String Value :%s\n", stringBox.get()); } }
Это даст следующий результат —
Вывод
Integer Value :10 String Value :Hello World
java