Пояснение
Обобщения инвариант . A List<Event<ActionType>>
не будет принимать Event<RightClick>
, только Event<ActionType>
.
. Понимать дженерики и корректировать ограничения типа c дженериков.
Если дженерики будут ковариантными , тогда вы могли бы дать кому-то, кто ожидает List<Animal>
a List<Dog>
, а затем добавить Cat
s к нему. Что может вызвать повреждение кучи , поскольку dogs.get(0)
может внезапно стать Cat
.
Пример:
List<Dog> dogs = new ArrayList<>();
dogs.add(new Dog());
List<Animal> animals = dogs; // pretend this would work
animals.add(new Cat()); // would be legit
Dog dog = dogs.get(1); // should be safe, but is cat, heap corruption
A List<Animal>
явно говорит, что этот список должен принять всех животных, а также кошек. Но List<Dog>
ограничен только для собак. Два списка ведут себя по-разному, они имеют разные ограничения, поэтому вы не можете использовать один для другого. В отличие от Dog
, который является Animal
, List<Dog>
не является List<Animal>
, то есть то, что подразумевается под коинвариантностью и инвариантностью.
Решение
Правильный инструмент для "принять любые ActionType
, мне все равно" являются подстановочными знаками . Так что либо go с
List<Event<? extends ActionType>>
или просто
List<Event<?>>
, так как класс Event
уже определяет ограничение T extends ActionType
.
С этим типом вы к нему можно будет добавить все виды Event
s:
Event<RightClick> rightClick = ...
Event<LeftClick> leftClick = ...
Event<MiddleClick> middleClick = ...
list.add(rightClick);
list.add(leftClick);
list.add(middleClick);
В результате использования подстановочного знака ?
вы больше не сможете знать фактический тип во время компиляции, поэтому :
Event<?> event = list.get(0); // unknown which exact type
Все, что вам известно о ?
, это то, что оно по крайней мере extends ActionType
, так что вы сможете использовать все виды методов, которые даются ActionType
, но ничего не вводится только в RightClick
например. Для этого потребовалось бы явное приведение (защищенное проверкой instanceof
), хотя я бы поставил под сомнение ваш дизайн, если вам придется использовать указание правой кнопкой мыши c вещей там.