Menu
Coddy logo textTech

Обобщенные методы

Часть раздела Объектно-ориентированное программирование путешествия по 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

Обобщенные методы особенно полезны в утилитарных классах, где требуются гибкие, повторно используемые операции без необходимости создания обобщенного класса.

challenge icon

Задание

Легко

Давайте создадим набор утилит, который продемонстрирует гибкость универсальных (generic) методов. Вы создадите класс с переиспользуемыми методами, которые работают с любым типом данных, показывая, как универсальные методы могут существовать независимо от универсальных классов.

Вы организуете свой код в двух файлах:

  • ArrayUtils.java: Создайте вспомогательный класс, содержащий универсальные методы для работы с массивами. Ваш класс должен иметь три статических универсальных метода:

    getLast — универсальный метод, который принимает массив типа T и возвращает последний элемент. Если массив пуст, верните null.

    swap — универсальный метод, который принимает массив типа T и два целочисленных индекса, а затем меняет местами элементы в этих позициях. Этот метод ничего не возвращает.

    printWithLabel — универсальный метод с двумя параметрами типа K и V. Он принимает метку типа K и значение типа V, а затем выводит их в формате: [label]: [value]

  • Main.java: Примените ваши универсальные методы на практике! Вы получите четыре входных значения: два слова (Strings) и два числа (integers).

    Сначала создайте массив 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 в качестве значения
    }
}
quiz iconПроверьте себя

В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.

Все уроки раздела Объектно-ориентированное программирование