0

我有一门派生类动作、喜剧和戏剧的电影类。我有一系列不同的电影,称为rentedMovies。

当我使用简单的 for 循环遍历数组时,

for(int i = 0; i < rentedMovies.lenght; i++){
  ..Do something..
}

IntelliJ IDE 建议我可以将此循环更改为 foreach。

for(Movie movie: rentedMovies){
 ..Do something..
}

但这是否意味着我所有的电影元素都将被视为 Movie 类的对象而不是派生类的对象?这是 IDE 的错误建议还是我的想法不对?谢谢。

4

4 回答 4

2

rendMovies 声明类似于

ArrayList<Movie> rentedMovies

因此,您将能够了解的有关集合中包含的对象的最具体信息是它们的类型Movie。你不得不在 Java 中这样做,因为泛型集合只能有一个特定的类型。为了能够将所有子类添加到集合中,您必须提供一个公共超类。

当您将对象添加到类时,类型信息会丢失。例如:

Comedy comedy = new Comedy();
rentedMovies.add(comedy);
Comedy comedy2 = rentedMovies.get(0); // compile error: get returns Movie
Movie movie = rentedMovie.get(0); // correct

简而言之,如果您不需要当前电影的索引,那么您的片段是等效的。请注意,for-each 语句在引擎盖下与迭代器一起使用,因此如果您正在修改循环内的集合,那么您必须注意您在做什么

如果您想从集合中检索到元素的特定信息,那么您必须自己向下转换它(并且忘记编译类型安全而无需手动检查),例如:

public Comedy asComedy() {
  return this instanceof Comedy ? (Comedy)this : null;
}

但是如果你需要这样做,那么你应该重新设计继承。也许您可以将行为完全移动到的子类中,Movie这样您就不需要知道具体的类型,而只需调用公共接口的方法。

于 2013-10-10T04:12:28.670 回答
1

你的rentedMovies我假设被声明为Movies[]无论如何,所以原始的 for 循环仍然会将它们作为 Movie 对象。

如果您想使用子类的特定方法,那么您必须在任何一种情况下进行强制转换。

使用的实现的优点(int i = 0; i < rentedMovies.lenght; i++)是,如果您不需要循环整个数组(然后 Intellij 不会给您此警告)或相对于当前对象的索引位置,则您拥有索引

于 2013-10-10T04:11:42.067 回答
1

如果你有一个不同类型的数组,那么 Array 变量的类型应该是一个超类。

无论如何,如果您要在循环中搜索特定类型的电影,您必须进行显式检查(不是很好的设计)。

所以你使用哪个循环真的没有区别......因为每个循环都会更简单并且没有任何缺点。

于 2013-10-10T04:11:50.417 回答
1

如果您将“动作、喜剧和戏剧”放在一个数组中,则租用的电影必须是“电影”类。因此,如果你通过 for 循环迭代它们,你就像“电影”一样迭代它们,而不是像“动作、喜剧或戏剧”。

建议的 IDE 迭代与您使用的相同,但如果您决定将数组更改为 List,可能会更直观一些,并且可以用于很多类(如 List)。

于 2013-10-10T04:13:34.843 回答