Обобщенные методы
Часть раздела Объектно-ориентированное программирование путешествия по Java на Coddy. Урок 55 из 87.
Хотя обобщённые классы позволяют целым классам работать с разными типами, иногда обобщённым нужно сделать только один метод. Обобщённый метод объявляет собственный параметр типа, независимый от обобщённых параметров уровня класса.
Параметр типа указывается перед типом возвращаемого значения в сигнатуре метода:
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 параметром типа для данного метода. Компилятор выводит фактический тип из переданных тобой аргументов.
Обобщённые методы также могут возвращать обобщённый тип:
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и возвращает последний элемент. Если массив пуст, верниnull.swap— обобщённый метод, который принимает массив типаTи два целочисленных индекса, а затем меняет местами элементы на этих позициях. Этот метод ничего не возвращает.printWithLabel— обобщённый метод с двумя параметрами типаKиV. Он принимает метку типаKи значение типаV, а затем выводит их в формате:[label]: [value]Main.java: Используй свои обобщённые методы! Ты получишь четыре входных значения: два слова (Strings) и два числа (целые числа).Сначала создай массив
String[], содержащий оба слова. ИспользуйgetLast, чтобы получить последний элемент, и выведи:Last word: [result]Затем создай массив
Integer[], содержащий оба числа. Вызовиswap, чтобы поменять местами элементы с индексами 0 и 1, а затем выведи:After swap: [first], [second]Наконец, продемонстрируй обобщённый метод с двумя параметрами, дважды вызвав
printWithLabel:- Один раз — передав первое слово в качестве метки, а первое число в качестве значения
- Один раз — передав первое число в качестве метки, а второе слово в качестве значения
Ты получишь четыре входных значения в следующем порядке: первое слово, второе слово, первое число, второе число.
Обрати внимание: каждый метод объявляет собственные параметры типа с помощью <T> или <K, V> перед типом возвращаемого значения. Компилятор определяет фактические типы по переданным аргументам — при вызове методов указывать их явно не нужно!
Попробуйте сами
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 в качестве метки, а firstNumber — в качестве значения
// TODO: Вызовите ArrayUtils.printWithLabel, передав firstNumber в качестве метки, а secondWord — в качестве значения
}
}
В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.
Все уроки раздела Объектно-ориентированное программирование
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