← Назад к вопросам

Какой любой тип данных может быть использован в Generics?

1.0 Junior🔥 221 комментариев
#Коллекции#ООП#Основы Java

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Типы данных в Java Generics

Основной принцип

В Generics можно использовать только Reference Types (ссылочные типы).

Запрещены: Primitive Types (примитивные типы)

1. Разрешённые типы

Classes (Классы):

List<String> strings = new ArrayList<>();
List<Integer> integers = new ArrayList<>();
List<MyCustomClass> customObjects = new ArrayList<>();

public class Container<T> {
    private T value;
    
    public void set(T value) {
        this.value = value;
    }
}

// Использование
Container<String> stringContainer = new Container<>();
Container<User> userContainer = new Container<>();

Interfaces (Интерфейсы):

List<Comparable> list = new ArrayList<>();
List<Serializable> serializableList = new ArrayList<>();

public interface Repository<T extends Entity> {
    T findById(Long id);
}

Array Types (Массивы объектов):

List<String[]> arrays = new ArrayList<>();
List<int[]> intArrays = new ArrayList<>(); // массив примитивов

T[] createArray(Class<T> clazz) {
    return (T[]) Array.newInstance(clazz, 10);
}

Type Variables (переменные типа):

public class Pair<T, U> {
    private T first;
    private U second;
    
    public Pair(T first, U second) {
        this.first = first;
        this.second = second;
    }
}

// Использование
Pair<String, Integer> pair = new Pair<>("John", 30);
Pair<User, Address> userAddressPair = new Pair<>(user, address);

Wildcard Types (Дикие карты):

List<?> unknownList = new ArrayList<>();
List<? extends Number> numbers = new ArrayList<>();
List<? super String> strings = new ArrayList<>();

public void printList(List<?> list) {
    for (Object obj : list) {
        System.out.println(obj);
    }
}

Nested Generics (вложенные Generics):

List<List<String>> listOfLists = new ArrayList<>();
Map<String, List<Integer>> map = new HashMap<>();
List<? extends Comparable<?>> comparables = new ArrayList<>();

2. Запрещённые типы

Primitive Types (примитивные типы):

// ОШИБКА! Не компилируется
List<int> intList;    // ❌
List<double> doubles; // ❌
List<boolean> flags;  // ❌
List<char> chars;     // ❌

// ПРАВИЛЬНО: используй Wrapper classes
List<Integer> intList;    // ✓
List<Double> doubles;     // ✓
List<Boolean> flags;      // ✓
List<Character> chars;    // ✓

Почему примитивные типы запрещены?

  1. Type erasure: Во время runtime информация о типе теряется
  2. Объекты vs примитивы: Generics работает только с объектами в heap
  3. Boxing/Unboxing: Примитивные типы требуют обёртывания
// Type erasure пример
List<Integer> intList = new ArrayList<>();
List<String> strList = new ArrayList<>();

// На runtime оба становятся просто List
// Поэтому нельзя использовать примитивы — они не объекты

3. Полная таблица типов

ТипРазрешёнПример
ClassList<String>
InterfaceList<Serializable>
EnumList<Color>
Array ObjectList<String[]>
Type VariableList<T>
WildcardList<?>
PrimitiveList<int>
voidList<void>

4. Bounded Type Parameters (ограниченные типы)

// Верхняя граница (Upper Bounded)
public <T extends Number> void processNumbers(List<T> list) {
    // T может быть Number, Integer, Double, BigDecimal и т.д.
}

public <T extends Comparable<T>> T findMax(List<T> list) {
    if (list.isEmpty()) return null;
    
    T max = list.get(0);
    for (T item : list) {
        if (item.compareTo(max) > 0) {
            max = item;
        }
    }
    return max;
}

// Использование
Integer maxInt = findMax(Arrays.asList(1, 5, 3, 9, 2)); // работает
String maxStr = findMax(Arrays.asList("a", "z", "b")); // работает
// Double maxDouble = findMax(Arrays.asList(1.5, 2.5, 3.5)); // ошибка, т.к. Double не Comparable<Double>
// Нижняя граница (Lower Bounded)
public void addNumbers(List<? super Integer> list) {
    list.add(1);
    list.add(2);
    // list может содержать Integer, Number, Object
}

5. Практические примеры

Правильный generics код:

public class GenericRepository<T extends Entity> {
    private Class<T> entityClass;
    private EntityManager entityManager;
    
    public GenericRepository(Class<T> entityClass) {
        this.entityClass = entityClass;
    }
    
    public T findById(Long id) {
        return entityManager.find(entityClass, id);
    }
    
    public List<T> findAll() {
        return entityManager.createQuery(
            "FROM " + entityClass.getSimpleName(), 
            entityClass
        ).getResultList();
    }
}

// Использование
GenericRepository<User> userRepo = new GenericRepository<>(User.class);
User user = userRepo.findById(1L);

GenericRepository<Product> productRepo = new GenericRepository<>(Product.class);
Product product = productRepo.findById(1L);

Правильная работа с Collections:

public <T> List<T> reverseList(List<T> list) {
    List<T> reversed = new ArrayList<>(list);
    Collections.reverse(reversed);
    return reversed;
}

public <T extends Comparable<T>> List<T> sortList(List<T> list) {
    List<T> sorted = new ArrayList<>(list);
    Collections.sort(sorted);
    return sorted;
}

// Использование
List<String> strings = Arrays.asList("banana", "apple", "cherry");
List<String> sorted = sortList(strings); // ✓

List<Integer> numbers = Arrays.asList(3, 1, 4, 1, 5);
List<Integer> sortedNums = sortList(numbers); // ✓

Вывод

В Generics разрешены все Reference Types (классы, интерфейсы, массивы объектов, переменные типа), но ЗАПРЕЩЕНЫ примитивные типы. Для примитивных типов используются Wrapper классы: Integer, Double, Boolean и т.д.

Какой любой тип данных может быть использован в Generics? | PrepBro