7

我的问题可能很简单,

我有一个Result包含一些内部字段、setter 和 getter 的类。

此外,我有Special1Result扩展Result并包含更多字段和Special2Result更多数据的类。

在不同的类Dispatcher中,我编写了以下方法:

processResults(List<? extends Result> results),这只是熟悉Result(我需要这个方法来查询扩展的 Result 对象中是否有特定的字段 - 我正在使用注释)。

所以我决定使用扩展的 for-each 循环:for (Result res : results) {}

那么我的问题是什么?我试图在网上找到如何为扩展对象编写这个 for 循环,例如像这样的东西for (? extends Results res: results){}

是否可以?正确的写法是怎样的?

4

4 回答 4

5

你所知道的关于 aList<? extends Result>的所有元素都是 a Result- 所以你可以在增强的 for 循环语法中添加所有内容。

如果您需要未在 中声明的成员,则Result需要在循环内进行强制转换:

for (Result result : results) {
    if (result instanceof CleverResult) {
        CleverResult clever = (CleverResult) result;
        // Use clever here
    }
}

想想如果你使用增强的 for 循环你会写什么——你仍然需要写演员,不是吗?

当然,如果您知道列表实际上应该包含一种特定类型,那么您总是可以在循环中无条件地强制转换。

于 2012-09-27T14:06:42.973 回答
3

我试图在网上找到如何为扩展对象编写这个 for 循环,例如像这样的东西

for (? extends Results res: results){}

不,这是不可能的:您不能静态键入在运行时动态提供的项目。

正确的写法是怎样的?

你已经在这样做了:

for (Results res: results) {
}

如果您想Special2Result在该循环内部进行测试,您可以这样做,但通常它表明您的设计可以改进。更好的选择是使用双重分派机制,例如访问者模式,来隐藏子类特殊处理的细节。

于 2012-09-27T14:09:11.567 回答
1

Java 有类型擦除——集合的具体类型参数在运行时不存在。

因此,如果您有一个 List,java 编译器将确保没有代码会将任何不是 Result 子类的内容放入列表中。

因此,在运行时,您的循环可以知道的所有内容都是 Result 的子类 - 因此循环它们的唯一方法是作为对 Result 的一组引用,以及由于任何子类而存在的任何多态行为在列表中。

于 2012-09-27T14:07:41.083 回答
1

由于您的具体子类仅因字段的性质而有所不同,因此我建议您从简单的多态性中受益。

您最终会得到一个Result接口/抽象类,该类定义一个execute()方法类,该方法类由您需要的多个类或子类实现,其中包含要执行的操作。

因此,您的客户端代码只能使用:

for (Result res : results){    //results being as a List<Result> type
  res.execute(); 
}
于 2012-09-27T14:10:44.233 回答