Является ли использование extends в дженериках Java хорошей практикой?

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

Ответ

Да, это хорошая практика, когда требуется ограничить типы-параметры для повышения безопасности типов. Ключевое слово extends в дженериках задает верхнюю границу (upper bound).

Зачем это нужно:

  1. Безопасность типов: Гарантирует, что параметр типа будет определенного класса или его подкласса.
  2. Доступ к методам: Позволяет обращаться к методам класса-границы внутри обобщенного кода.

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

// T может быть только Number или его подклассом (Integer, Double, etc.)
public class NumericContainer<T extends Number> {
    private T value;

    public NumericContainer(T value) { this.value = value; }

    public double getSquare() {
        // Можем вызвать метод Number.doubleValue()
        return value.doubleValue() * value.doubleValue();
    }
}

// Использование
NumericContainer<Integer> intBox = new NumericContainer<>(5); // OK
NumericContainer<Double> doubleBox = new NumericContainer<>(3.14); // OK
// NumericContainer<String> stringBox = ... // Ошибка компиляции! String не extends Number

Пример метода с ограничением:

// Метод работает только с массивами Comparable объектов
public static <T extends Comparable<T>> T findMax(T[] array) {
    T max = array[0];
    for (T item : array) {
        if (item.compareTo(max) > 0) max = item;
    }
    return max;
}

Когда НЕ использовать extends: Если ваш класс или метод должен работать с любым типом (Object), то ограничение излишне. Используйте extends только когда ограничение добавляет ценность или является необходимым для логики.