gpt4 book ai didi

java - Java 中的接口(interface)和泛型

转载 作者:太空狗 更新时间:2023-10-29 22:45:45 25 4
gpt4 key购买 nike

我有代码:

Set<? extends Notifiable> notifiables;

Notifiable 是一个接口(interface)。我不明白上面的代码和:

Set<Notifiable> notifiables;

如果 Notifiable 是一个类,那么我会理解其中的区别,第一个代码将允许 Notifiable 和 Notifiable 的任何子类,而第二个代码将只允许 Notifiable(而不是任何子类)

由于您不能拥有接口(interface)的实例,我可以向集合中添加什么?在我看来,只有两种选择,要么是实现 Notifiable 的任何东西(在这种情况下,它与第一个代码有何不同),要么只有不存在的“Notifiable 实例”,因此什么也没有(这是毫无意义的,应该抛出一个编译时错误)。

最佳答案

A Set<Notifiable> 可以持有实现Notifiable的类的实例.它不仅限于只持有具体类型为 Notifiable 的实例(你是对的,没有这样的东西)。但是一个Set<Notifiable>保证它可以容纳任何Notifiable , 因为它有一个 add(Notifiable)可以接受任何实现该接口(interface)的方法。

假设您有一些名为 Foo 的类和 Bar两者都实现了 Notifiable .如果你创建一个 Set<Foo> — 也就是说,允许包含 Foo 实例的集合及其子类型——你不能将它传递给采用 Set<Notifiable> 的方法,因为该方法可能会添加不是 Foo 的东西实例,例如 Bar .

public void addABar(final Set<Notifiable> notifiables) {
notifiables.add(new Bar()); // OK, since Bar is a subtype of Notifiable
}

public void wontWork() {
final Set<Foo> foos = new HashSet<>();
addABar(foos); // Compile error, can't convert Set<Foo> to Set<Notifiable>
}

但有时您想编写一个可以接受类似Set<Foo>之类的方法和 Set<Bar>除了Set<Notifiable> .这就是通配符的用武之地。 A Set<? extends Notifiable>保证其中的所有内容都是某种 Notifiable ,但它保证每一种 Notifiable可以加进去;它被允许限于一个子类型。你不能调用 add()在上面,因为该方法现在是 add(? extends Notifiable)而不是 add(Notifiable)并且您不能调用参数类型未知的方法。

当您不需要添加元素时通常会使用它,但您确实需要查看现有元素并调用 Notifiable它们的接口(interface)方法,并且您希望允许调用者传递子类型集,例如 Set<Foo> .

例如:

public void notifyAll(final Set<? extends Notifiable> notifiables) {
for (final Notifiable notifiable : notifiables) {
notifiable.notify();
}
}

public void example() {
final Set<Foo> foos = whatever();
notifyAll(foos); // OK, since a Set<Foo> is a Set<? extends Notifiable>
}

如果notifyAll()拿了Set<Notifiable> ,你将无法通过 foos

关于java - Java 中的接口(interface)和泛型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22595234/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com