Можно ли хранить объекты разных типов в HashSet?

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

Ответ

Технически да, но это нарушает принципы типобезопасности и ведет к ошибкам. HashSet может хранить любые объекты, если объявлен как HashSet<Object> или сырой тип.

Проблемы такого подхода:

  1. Потеря типобезопасности: Компилятор не сможет проверить типы, что приводит к ClassCastException во время выполнения.
  2. Непредсказуемое поведение equals() и hashCode(): Разные классы имеют разную логику этих методов. Объекты разных типов могут быть признаны "равными" или иметь одинаковый хэш, что сломает уникальность элементов в HashSet.

Пример (антипаттерн):

HashSet<Object> set = new HashSet<>();
set.add("Hello");        // String
set.add(42);             // Integer (автоупаковка)
set.add(List.of(1,2));   // List<Integer>

// Извлечение требует проверки и приведения
for (Object obj : set) {
    if (obj instanceof String) {
        System.out.println(((String) obj).toUpperCase());
    }
    // Опасность ClassCastException без instanceof
}

Вывод: Избегайте хранения разнотипных объектов в одном HashSet. Используйте дженерики с конкретным типом (HashSet<String>) или создайте общий интерфейс/суперкласс для элементов.