Ответ
Generics (обобщения) решают задачу создания типобезопасных, переиспользуемых компонентов (классов, интерфейсов, методов), устраняя необходимость приведения типов (casting) и уменьшая дублирование кода.
Пример задачи: Реализация универсального кэша для хранения объектов любого типа с гарантией безопасности типов на этапе компиляции.
Решение с Generics:
public class GenericCache<T> {
private Map<String, T> storage = new HashMap<>();
public void put(String key, T value) {
storage.put(key, value);
}
public Optional<T> get(String key) {
return Optional.ofNullable(storage.get(key));
}
}
Использование:
// Кэш для строк. Компилятор проверяет типы.
GenericCache<String> userCache = new GenericCache<>();
userCache.put("user:1", "Alice");
String userName = userCache.get("user:1").orElse("Unknown"); // Без приведения типа
// Кэш для чисел. Тот же класс, но другой параметр типа.
GenericCache<Integer> configCache = new GenericCache<>();
configCache.put("maxConnections", 100);
Какие проблемы это решило:
- Безопасность типов: Ошибка
ClassCastExceptionобнаруживается на этапе компиляции. Нельзя положитьIntegerвGenericCache<String>. - Устранение дублирования: Не нужно создавать отдельные классы
StringCache,IntegerCache. - Улучшение читаемости: Код явно показывает, с каким типом данных работает.
- Снижение шаблонного кода: Убраны ручные приведения
(String) cache.get(key).