英文:
generic misunderstanding when tying to add to list
问题
以下是您要求的代码部分的中文翻译:
这是一个通配符问题。
我的目的是创建一个包含具有泛型类型的类的列表,并提供扩展示例:
这是结构:
public class Event<T extends ActionType> {
}
public abstract class ActionType {
}
// **许多**扩展ActionType类的类
这是一个包含扩展自**ActionType**的类的列表
private List<Event<ActionType>> list = new ArrayList<>();
Event<RightClick> event = new Event<>(xPosition, yPosition, delay, new RightClick(robot), clicks, robot);
list.add(event);
我知道这样做无法确保我可以添加扩展的项:
private List<Event<ActionType>> list = new ArrayList<>();
但我可以采取什么措施将项目添加到同一列表中。
为了解决我的问题,我使用了通配符选择器**?**
List<Event<? extends ActionType>>
英文:
this a wildcard question.
my purpose is to make a list that contains a class that has a generic type with extended examples:
so this is the structure:
public class Event<T extends ActionType>{
}
public abstract class ActionType{
}
//**many** classes that extends ActionType class
that's a list that hold classes that extends from ActionType
private List<Event<ActionType>> list = ArrayList<>();
Event<RightClick> event = new Event<>(xPosition, yPosition, delay, new RightClick(robot), clicks, robot);
list.add(event);
I know that's I cant do this to make sure that I can add the extended items:
private List<Event<ActionType>> list = ArrayList<>();
but what I can do to add the items to the same list.
to fix my problem I used the wildcard selector ?
List<Event<? extends ActionType>>
答案1
得分: 1
Explanation
泛型是不变的。List<Event<ActionType>> 不会接受 Event<RightClick>,只会接受 Event<ActionType>。
理解泛型并调整你的泛型类型限制。
如果泛型是协变的,那么你可以把一个期望 List<Animal> 的人一个 List<Dog>,然后再向其中添加 Cat,这将导致堆破坏,因为 dogs.get(0) 可能突然变成了一个 Cat。
一个例子:
List<Dog> dogs = new ArrayList<>();
dogs.add(new Dog());
List<Animal> animals = dogs; // 假装这能够工作
animals.add(new Cat()); // 将是合法的
Dog dog = dogs.get(1); // 应该是安全的,但却是猫,堆破坏
List<Animal> 明确表示这个列表必须接受所有动物,包括猫。但是 List<Dog> 只限制在狗。这两个列表的行为不同,它们有不同的限制,因此你不能将一个用于另一个。与Dog是Animal不同,List<Dog> 不是一个 List<Animal>,这就是共变和不变的含义。
Solution
正确的工具用于*“接受任何 ActionType,我不关心是什么”*是通配符。所以要么使用
List<Event<? extends ActionType>>
要么只使用
List<Event<?>>
因为 Event 类已经指定了 T extends ActionType 的限制。
使用这种类型,你将能够向其中添加各种类型的 Event:
Event<RightClick> rightClick = ...
Event<LeftClick> leftClick = ...
Event<MiddleClick> middleClick = ...
list.add(rightClick);
list.add(leftClick);
list.add(middleClick);
由于 ? 通配符,你将无法在编译时知道实际的类型,所以:
Event<?> event = list.get(0); // 未知的确切类型
你所知道的关于 ? 就是它至少是 extends ActionType,所以你将能够使用由 ActionType 提供的所有方法,但不能使用仅在 RightClick 中引入的方法。这将需要一个显式的转换(由 instanceof 检查保护),尽管如果你必须在那里使用特定于右键单击的内容,我会对你的设计产生疑问。
英文:
Explanation
Generics are invariant. A List<Event<ActionType>> will not accept Event<RightClick>, only Event<ActionType>.
Understand generics and adjust your generic type restrictions.
If generics would be covariant, then you could give someone who expects a List<Animal> a List<Dog> and then add Cats to it. Which would cause heap corruption as dogs.get(0) could suddenly be a Cat.
An example:
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> explicitly says that this list must accept all animals, also cats. But a List<Dog> is restricted to dogs only. The two lists behave differently, they have different restrictions, hence you can not use one for another. Unlike a Dog who is an Animal, a List<Dog> is not an List<Animal>, that is what is meant by co- and invariance.
Solution
The correct tool to "accept any ActionType, I do not care" are wildcards. So either go with
List<Event<? extends ActionType>>
or just
List<Event<?>>
since the Event class already specifies the T extends ActionType restriction.
With that type you will be able to add all sorts of Events to it:
Event<RightClick> rightClick = ...
Event<LeftClick> leftClick = ...
Event<MiddleClick> middleClick = ...
list.add(rightClick);
list.add(leftClick);
list.add(middleClick);
As a consequence of the ? wildcard you will not be able to know the actual type at compile-time anymore, so:
Event<?> event = list.get(0); // unknown which exact type
All you know of ? is that it is at least extends ActionType, so you will be able to use all sorts of methods that are given by ActionType, but nothing introduced only in RightClick for example. That would require an explicit cast (guarded by an instanceof check), although I would question your design if you have to use right-click specific things there.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论