Обобщенные методы
Часть раздела Объектно-ориентированное программирование путешествия по Java на Coddy. Урок 55 из 87.
Хотя обобщённые классы позволяют целым классам работать с разными типами, иногда обобщённым нужно сделать только один метод. Обобщённый метод объявляет собственный параметр типа, независимый от обобщений на уровне класса.
Параметр типа располагается перед типом return в сигнатуре method:
public class Utility {
public static <T> void printArray(T[] array) {
for (T element : array) {
System.out.println(element);
}
}
}
String[] names = {"Alice", "Bob"};
Integer[] numbers = {1, 2, 3};
Utility.printArray(names); // Работает с String[]
Utility.printArray(numbers); // Работает с Integer[]Обратите внимание на <T>, размещённый между модификаторами и типом возвращаемого значения. Это объявляет T параметром типа для данного метода. Компилятор выводит фактический тип из переданных вами аргументов.
Generic-методы также могут возвращать generic-тип:
public static <T> T getFirst(T[] array) {
if (array.length > 0) {
return array[0];
}
return null;
}
String first = getFirst(new String[]{"a", "b"}); // Возвращает "a"При необходимости можно использовать несколько параметров типа:
public static <K, V> void printPair(K key, V value) {
System.out.println(key + ": " + value);
}
printPair("Age", 25); // String и Integer
printPair(1, "First"); // Integer и StringОбобщённые методы особенно полезны в классах утилит, где нужны гибкие, повторно используемые операции без создания обобщённого класса.
Задание
ЛегкоДавайте создадим набор утилит, демонстрирующий гибкость обобщённых методов. Вы создадите класс с повторно используемыми методами, которые работают с любым типом, показывая, что обобщённые методы могут существовать независимо от обобщённых классов.
Вы организуете код в двух файлах:
ArrayUtils.java: Создайте класс утилит, содержащий обобщённые методы для работы с массивами. В вашем классе должны быть три статических обобщённых метода:getLast— обобщённый метод, который принимает массив типаTи возвращает последний element. Если массив пуст, Returnnull.swap— обобщённый метод, который принимает массив типаTи два integer индекса, затем меняет местами elements на этих positions. Этот метод ничего не возвращает.printWithLabel— обобщённый метод с двумя параметрами типаKиV. Он принимает label типаKи значение типаV, затем Prints их в формате:[label]: [value]Main.java: Задействуйте свои обобщённые методы! Вы получите четыре входных значения: два слова (String) и два числа (integer).Сначала создайте массив
String[], содержащий оба слова. ИспользуйтеgetLast, чтобы получить последний element, и выведите:Last word: [result]Затем создайте массив
Integer[], содержащий оба числа. Вызовитеswap, чтобы поменять местами elements по индексам 0 и 1, затем выведите:After swap: [first], [second]Наконец, продемонстрируйте обобщённый метод с двумя параметрами, дважды вызвав
printWithLabel:- Один раз, используя первое слово в качестве label, а первое число — в качестве значения
- Один раз, используя первое число в качестве label, а второе слово — в качестве значения
Вы получите четыре входных значения в следующем порядке: первое слово, второе слово, первое число, второе число.
Обратите внимание, что каждый метод объявляет собственный параметр(ы) типа с помощью <T> или <K, V> перед типом Return. Компилятор выводит фактические типы из переданных вами аргументов: при вызове методов не нужно указывать их явно!
Попробуйте сами
import java.util.Scanner;
class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
// Прочитать входные данные
String firstWord = scanner.nextLine();
String secondWord = scanner.nextLine();
int firstNumber = scanner.nextInt();
int secondNumber = scanner.nextInt();
// TODO: Создать массив String[] содержащий оба слова
// TODO: Использовать ArrayUtils.getLast чтобы получить последний элемент
// Вывести: "Last word: [result]"
// TODO: Создать массив Integer[] содержащий оба числа
// TODO: Вызвать ArrayUtils.swap чтобы поменять местами элементы с индексами 0 и 1
// Вывести: "After swap: [first], [second]"
// TODO: Вызвать ArrayUtils.printWithLabel с firstWord в качестве label и firstNumber в качестве value
// TODO: Вызвать ArrayUtils.printWithLabel с firstNumber в качестве label и secondWord в качестве value
}
}
В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.
Все уроки раздела Объектно-ориентированное программирование
1Основы ООП
Внешние файлыВведение в ООПКлассы и объектыКлючевое слово thisМетодыПоля (атрибуты)Метод-конструкторПерегрузка конструкторовИтоги — Простой калькулятор4Наследование
Основы наследования (extends)Ключевое слово superПереопределение методов (@Override)Цепочка конструкторовКласс ObjectОдиночное и многоуровневое наследованиеПочему нет множественного наследования классовИтоги — Иерархия сотрудников7Специальные методы и класс Object
Метод toString()equals() и hashCode()Метод clone()compareTo() и ComparableИнтерфейс ComparatorПовторение — Кастомная сортировка2Модификаторы доступа и инкапсуляция
Обзор уровней доступаМетоды геттеры и сеттерыСокрытие данныхКлючевое слово finalИтоги — Менеджер банковского счета5Полиморфизм
Основы перегрузки методовПереопределение методов (Run-Time)Upcasting и DowncastingОператор instanceofАбстрактные классы и методыИтоги: Калькулятор фигур8Продвинутые концепции ООП
Композиция против наследованияАгрегация против композицииВнутренние, вложенные и анонимные классыEnums и методы перечисленийRecords (Java 16+)Sealed-классы (Java 17+)11Паттерны проектирования. Часть 1
Введение в паттерны проектированияПаттерн SingletonПаттерн FactoryПаттерн BuilderПаттерн ObserverПаттерн Strategy3Свойства класса и статические члены
Переменные экземпляра и статические переменныеСтатические методыСтатические блокиКонстанты (static final)Итоги: Счетчик и утилиты6Интерфейсы и абстрактные классы
Введение в интерфейсыРеализация интерфейсовРеализация нескольких интерфейсовDefault и Static методы в интерфейсахАбстрактные классы vs ИнтерфейсыФункциональные интерфейсыИтоги — Платежная система9Обобщения
Введение в обобщенияОбобщенные классыОбобщенные методыОграниченные параметры типаСимволы подстановки (Wildcards: ?, extends, super)Итоги — Обобщенный контейнер12Паттерны проектирования. Часть 2
Паттерн «Команда»Паттерн «Адаптер»Паттерн «Декоратор»Паттерн «Шаблонный метод»Паттерн «Состояние»Паттерн «Компоновщик»Паттерн «Итератор»Потренируйтесь самостоятельно: Онлайн-компилятор Java