Что такое Generics в Java и как они работают?

«Что такое Generics в Java и как они работают?» — вопрос из категории Java Core, который задают на 10% собеседований Java Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

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

Основная цель:

  • Type-safety: Компилятор проверяет корректность типов.
  • Reusability: Один обобщенный код для разных типов.
  • Устранение кастов: Избегание ClassCastException.

Пример обобщенного класса:

public class Container<T> {
    private T value;

    public void setValue(T value) { this.value = value; }
    public T getValue() { return value; }
}
// Использование
Container<String> stringContainer = new Container<>();
stringContainer.setValue("Hello");
String s = stringContainer.getValue(); // Без приведения типа

Как работают (Type Erasure): Во время компиляции информация о generic-типах стирается.

  • Параметр типа T заменяется на его верхнюю границу (по умолчанию Object).
  • Генерируются необходимые приведения типов (casts).
  • При компиляции Container<String> становится Container<Object>.

Ограничения (Bounds):

// T должен быть подтипом Number
public class NumericContainer<T extends Number> { ... }
// ? - wildcard (подстановочный знак)
public void processList(List<? extends Number> list) { ... } // Producer (чтение)
public void addToList(List<? super Integer> list) { ... } // Consumer (запись)

Практическое правило PECS:

  • Producer Extends (? extends T) — если структура является источником данных (читаем).
  • Consumer Super (? super T) — если структура является приемником данных (записываем).