英文:
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 Cat
s 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 Event
s 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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论