← Назад к вопросам

Как реализован параметрический полиморфизм в Java?

1.3 Junior🔥 231 комментариев
#ООП

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

# Параметрический полиморфизм в Java

Определение

Параметрический полиморфизм (Generics) — это механизм в Java, который позволяет классам, интерфейсам и методам работать с различными типами данных, сохраняя при этом типобезопасность на этапе компиляции. Это решает проблему, когда один класс должен работать с разными типами, но при этом нужна строгая проверка типов.

Основные компоненты

1. Типовые параметры (Type Parameters)

Типовые параметры обозначаются углубраквыми скобками и обычно одной буквой:

public class Box<T> {
    private T content;
    
    public void set(T item) {
        content = item;
    }
    
    public T get() {
        return content;
    }
}

Здесь T — типовой параметр, который будет заменён конкретным типом при использовании класса.

2. Использование параметризованных типов

Box<String> stringBox = new Box<>();
stringBox.set("Hello");
String value = stringBox.get(); // Автоматически String, без кастирования

Box<Integer> intBox = new Box<>();
intBox.set(42);
Integer num = intBox.get();

Type Erasure (Стирание типов)

Это ключевая особенность параметрического полиморфизма в Java. Во время компиляции все типовые параметры удаляются (заменяются на их верхнюю границу или Object):

// Исходный код
Box<String> stringBox = new Box<>();
stringBox.set("Hello");

// Что видит Java Virtual Machine (после компиляции)
Box stringBox = new Box();
stringBox.set((Object) "Hello");

Почему это сделано так? Для обратной совместимости со старыми версиями Java, которые не поддерживали Generics.

Ограничения типовых параметров (Bounded Type Parameters)

Можно ограничить, какие типы могут передаваться как типовой параметр:

// Верхняя граница (extends)
public class NumberBox<T extends Number> {
    private T value;
    
    public double toDouble() {
        return value.doubleValue();
    }
}

NumberBox<Integer> intBox = new NumberBox<>(); // OK
NumberBox<String> stringBox = new NumberBox<>(); // Ошибка компиляции

Подстановочные типы (Wildcards)

Позволяют работать с неизвестными типами:

// ? — любой тип
public void processBox(Box<?> box) {
    Object obj = box.get(); // OK, но тип неизвестен
}

// ? extends Number — верхняя граница
public void processNumbers(Box<? extends Number> box) {
    Number num = box.get();
}

// ? super Integer — нижняя граница
public void setInt(Box<? super Integer> box) {
    box.set(42); // OK
}

Параметризованные методы

Еже не весь класс, а конкретный метод может быть параметризованным:

public static <T> void swap(List<T> list, int i, int j) {
    T temp = list.get(i);
    list.set(i, list.get(j));
    list.set(j, temp);
}

swap(stringList, 0, 1); // T будет String
swap(intList, 0, 1);    // T будет Integer

Проблемы и ограничения

  1. Нельзя создавать массивы параметризованных типов: new Box<String>[10] — ошибка
  2. Нельзя использовать примитивные типы: Box<int> — нельзя, нужно Box<Integer>
  3. Нельзя создавать экземпляры типовых параметров: new T() — ошибка
  4. Проверка instanceof не работает с типовыми параметрами: obj instanceof Box<String> — ошибка

Практическое применение

Параметрический полиморфизм широко используется в Java Collections Framework:

List<String> names = new ArrayList<>();
names.add("Alice");
for (String name : names) {
    System.out.println(name); // Тип известен, нет кастирования
}

Map<String, Integer> ages = new HashMap<>();
ages.put("Bob", 30);
Integer age = ages.get("Bob"); // Возвращает Integer, не Object

Заключение

Параметрический полиморфизм — это мощный инструмент для создания переиспользуемого, типобезопасного кода. Несмотря на стирание типов и некоторые ограничения, Generics делают Java код более безопасным и читаемым, избегая многочисленных кастирований и ошибок типов.