Generic: ArrayList of ? Extends ISomeInterface in Java
我在下面的代码中遇到了一些问题。
1
2 3 4 5 6 |
public ArrayList<? extends IEvent> getEventsByDateRange(DateTime minStartTime, DateTime minEndTime)
{ ArrayList<? extends IEvent> returnedEvents = new ArrayList<GoogleEvent>(); returnedEvents.add(new GoogleEvent()); return (returnedEvents); } |
这会为”returnedEvents.add(new GoogleEvent()); line of code”返回以下编译错误:
The method add(capture#1-of ? extends IEvent) in the type
ArrayList is not applicable for the
arguments (GoogleEvent)
类GoogleEvent的声明如下:
1
|
public class GoogleEvent implements IEvent {…}
|
我知道在 Java 中使用泛型有一些棘手的部分,因此是通配符,但我似乎无法弄清楚这一点。
谢谢。
你为什么不写:
1
2 3 4 5 6 |
public List<IEvent> getEventsByDateRange(DateTime minStartTime, DateTime minEndTime)
{ List<IEvent> returnedEvents = new ArrayList<IEvent>(); returnedEvents.add(new GoogleEvent()); return returnedEvents; } |
- ArrayList<GoogleEvent> 与 List<IEvent> 的赋值不兼容。
- 您不能将 ArrayList<GoogleEvent> 分配给 List<IEvent>。
- 你不能这样做..它不是同一个对象类型
- 对不起,我忘了替换泛型参数
- 现在你有一个问题,因为你不能创建 IEvents 的实例,它是一个接口
- @Mortalus:为什么不呢?你可以,它是一个泛型列表,而不是一个数组。我什至试过:)
解决办法:
1
|
ArrayList<IEvent> returnedEvents = new ArrayList<IEvent>();
|
您的错误原因是因为编译器正在尝试进行捕获转换。
在您的情况下,returnedEvents 捕获了一些扩展 IEvent 的未知数(即扩展/实现 IEvent 的任何内容)并且您将其分配给参数化类型 GoogleEvent)。
编译器看到,returnedEvents.add(? extends IEvent) 没有使用 returnedEvents.add(GoogleEvent) 的签名进行验证,因为捕获占位符设置在 returnedEvents 上。
- 这不编译。您不能在通用实例化中使用通配符。
- @John B,谢谢,我看到了,页面需要很长时间才能更新。我已经更新了我的帖子。
您不需要使用 ? extends IEvent,因为仅使用 IEvent,Java 将动态绑定 GoogleEvent 类。它是多态性。
这是不允许的。 returnedEvents 包含 GoogleEvent 对象的列表,不得允许接受不是 GoogleEvent 对象的对象。
虽然在您的示例中您恰好传递了一个 GoogleEvent,但您是通过调用一个接受任何实现 IEvent 的 add 版本来实现的。根本不允许调用该 add 方法,因为它可能导致列表存储 GoogleEvent.
以外的内容
Java 通配符”编辑出”方法会以这种方式破坏规则。
如果你需要返回那个通配符列表类型,一个 ArrayList<GoogleEvent> 就可以满足它。
注意这是一个完整的源文件,编译时不会出错:
1
2 3 4 5 6 7 8 9 10 11 12 13 |
import java.util.*;
interface IEvent { } class GoogleEvent implements IEvent { } public class Foo { |
- 我应该如何将 googleEvents 类的对象添加到实现 IEvents 的对象数组列表中?
- 再次在返回语句中,我得到 Type mismatch: cannot convert from List<GoogleEvent> to ArrayList<?扩展 IEvent>
- List 还是 ArrayList?他们不一样。
- @Mortalus – 查看进一步更新,一个完整的源文件,您可以尝试编译。
- 谢谢 !!!!!完美地工作..所以现在我应该能够使用 IEvent 接口访问所有糟糕的 GoogleEvents 了吗?
- 是的,Java 泛型将允许对可以从 ArrayList<? extends IEvent> 检索的对象调用 IEvent 方法。 (但如前所述,您将不被允许向集合中添加新对象。)
你不能写入一个用 ? extends … 声明的变量。仅在使用 ? super ….
时才允许写入
这可以用下面的例子来解释:
1
2 3 4 5 6 7 8 9 |
List<GoogleEvent> googleEvents = new ArrayList<GoogleEvent>();
ArrayList<? extends IEvent> returnedEvents = googleEvents; // Would be OK // Would be OK to the definition of returnedEvents, |
您的简短解决方案是将 returnedEvents 声明为 List<GoogleEvent>.
- 这将返回类型不匹配:无法从 List<GoogleEvent> 转换为 ArrayList<?扩展 IEvent>
- 使用列表<?扩展 IEvent> 作为结果类型。通常哪个更好,因为您可以将 ArrayList 更改为另一个列表,例如。 g.、LinkedList不改变操作界面。
- 添加演员表 ArrayList<? extends IEvent> returnedEvents = (ArrayList<? extends IEvent>)googleEvents;
1
2 3 4 5 6 7 |
public ArrayList<IEvent> getEventsByDateRange(DateTime minStartTime,
DateTime minEndTime) { ArrayList<IEvent> returnedEvents = new ArrayList<IEvent>(); returnedEvents.add(new GoogleEvent()); return (returnedEvents); } |
来源:https://www.codenong.com/7821064/