Приведи пример использования Generics в Java.

Ответ

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

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

public class Box<T> {
    private T content;

    public void setContent(T content) {
        this.content = content;
    }

    public T getContent() {
        return content;
    }
}

Использование:

// Создание Box для String
Box<String> stringBox = new Box<>();
stringBox.setContent("Hello");
String value = stringBox.getContent(); // Тип String гарантирован, приведение не нужно

// Создание Box для Integer
Box<Integer> intBox = new Box<>();
intBox.setContent(123);
int num = intBox.getContent(); // Авто-распаковка из Integer в int

Ключевые преимущества:

  • Типобезопасность: Компилятор проверяет соответствие типов, предотвращая ClassCastException.
  • Устранение приведения типов: Код становится чище и безопаснее.
  • Повторное использование: Один обобщенный алгоритм или структура данных может работать с разными типами.

Generics также поддерживают ограничения (<T extends Number>) и несколько параметров (<K, V>).

Ответ 18+ 🔞

Слушай, а вот эта ваша джава, она, блядь, хитрая жопа. Смотри, бывает же такое: пишешь ты класс, а он должен работать и с циферками, и со строками, и с какими-нибудь своими объектами. И тут начинается: везде касты, (String), (Integer), а потом в рантайме — бац! — ClassCastException тебе прямо в ебало. Пиздец, а не разработка.

Так вот, чтобы не бздеть каждый раз при приведении типов, умные дядьки придумали Generics, или, по-нашему, обобщения. Суть проще пареной репы, но гениальная, ёпта.

Вот смотри, раньше ты бы написал коробку так:

public class OldBox {
    private Object content; // Туда можно запихнуть ВСЁ, что угодно

    public void setContent(Object content) {
        this.content = content;
    }

    public Object getContent() {
        return content;
    }
}

А потом, доставая, орал: "А ну-ка вернись обратно, сука, в строку!" — String value = (String) oldBox.getContent();. И молился, чтобы там действительно была строка, а не, например, Integer.

Теперь же можно сделать так, чтобы коробка при создании сразу понимала, с чем она работает. Чистая магия, блядь!

Вот обобщённая коробка, красавица:

public class Box<T> { // Вот эта буква T — это типа слот для будущего типа. Хочешь — String, хочешь — Integer.
    private T content;

    public void setContent(T content) {
        this.content = content;
    }

    public T getContent() {
        return content;
    }
}

А юзается это всё вообще божественно:

// Делаем коробку исключительно для строк. Говорим ей это прямо в лицо.
Box<String> stringBox = new Box<>();
stringBox.setContent("Привет, ёпта!");
String value = stringBox.getContent(); // Никаких ебучих кастов! Компилятор уже знает, что тут String.

// А теперь — коробка для чисел.
Box<Integer> intBox = new Box<>();
intBox.setContent(123);
int num = intBox.getContent(); // И тут красота — Integer сам в int превратится (авто-распаковка).

В чём, собственно, соль и перец, блядь?

  • Типобезопасность, мать её: Компилятор теперь зорко следит, чтобы ты не сунул в stringBox число. Попробуй — получишь ошибку на этапе компиляции, а не в продакшене в три часа ночи. ClassCastException отдыхает.
  • Касты на хуй: Больше не нужно этого убогого (Тип). Код чище, сердце спокойнее.
  • Один раз написал — всюду пользуй: Написал один умный алгоритм для списка (List<T>), и он будет работать с любым типом. Не надо копипастить одно и то же для String, Integer и своего класса Cat.

А ещё можно эти обобщения, сука, ограничивать! Типа <T extends Number> — значит, сюда можно только числа (Integer, Double и т.д.). Или несколько параметров сразу сделать, например, для пары ключ-значение: <K, V>.

В общем, вещь охуенная. Сначала голова ломается, а потом — волнение ебать, как же без этого жил-то.