Java 在接口上使用通配符

Java 在接口上使用通配符,java,generics,interface,bounded-wildcard,Java,Generics,Interface,Bounded Wildcard,考虑以下类别: interface Notifiable { } class NotifiableImpl1 implements Notifiable { } class NotifiableImpl2 implements Notifiable { } class NotifiableImpl3 implements Notifiable { } 以下代码正常工作: Set<Notifiable> set = new HashSet<>(); set.

考虑以下类别:

interface Notifiable {

}

class NotifiableImpl1 implements Notifiable {

}

class NotifiableImpl2 implements Notifiable {

}

class NotifiableImpl3 implements Notifiable {

}
以下代码正常工作:

Set<Notifiable> set = new HashSet<>();
set.add(new NotifiableImpl1());
set.add(new NotifiableImpl2());
set.add(new NotifiableImpl3());
也许更有趣的是,为什么下面的工作

Set<Notifiable> set = new HashSet<>();
set.add(new NotifiableImpl1());
set.add(new NotifiableImpl2());
set.add(new NotifiableImpl3());

Set<? extends Notifiable> set3 = set;
Set Set=newhashset();
set.add(新的NotifiableImpl1());
set.add(新的NotifiableImpl2());
set.add(新的NotifiableImpl3());

Set第一个代码完全有效。由于您可以使用超类型的引用来保存子类对象,如下所示:

Notifiable notifiable = new NotifiableImpl1();
同样,您可以将
NotifiableImpl
对象添加到
集合中。该集合可以容纳任何子类型的对象


根据,第二个代码无效。基本上是一个
SetI我想你能找到答案。我喜欢这样的语句
1st当您仅从结构中获取值时使用扩展通配符当您仅将值放入结构中时使用超级通配符,当您获取和放入时不使用通配符。
@nachokk此问题不是关于超级vs扩展。虽然答案可能是相似的,但这并不意味着问题是相似的。没错,这不是同一个问题,而是与答案相同的解释。从前面提到的线索中可以看出,“你实际上无法向集合中添加任何内容,你可以做
Set<Notifiable> set = new HashSet<>();
set.add(new NotifiableImpl1());
set.add(new NotifiableImpl2());
set.add(new NotifiableImpl3());

Set<? extends Notifiable> set3 = set;
Notifiable notifiable = new NotifiableImpl1();
Set<Notifiable> set = new HashSet<>();
Set<? extends Notifiable> set3 = set;