我有一个类派对,派生类动作,喜剧和戏剧。我有一系列不同的电影叫做rentedMovies。
当我使用简单的for循环遍历数组时,
for(int i = 0; i < rentedMovies.lenght; i++){
..Do something..
}
IntelliJ IDE建议我可以将此循环更改为foreach。
for(Movie movie: rentedMovies){
..Do something..
}
但这不是暗示我的所有电影元素都将被视为Movie类的对象而不是派生类的对象吗? 这是IDE的错误建议还是我不正确?感谢。
答案 0 :(得分:2)
rendedMovies声明类似于
这一事实已经暗示了这一假设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
的子类中移动行为,这样你就不需要知道特定的类型,只需要调用公共接口的方法。
答案 1 :(得分:1)
我认为你的rentedMovies
被声明为Movies[]
,所以原来的for循环仍将它们作为电影对象。
如果你想使用子类的特定方法,那么你将不得不抛出任何一种情况。
使用(int i = 0; i < rentedMovies.lenght; i++)
的实现的好处是,如果你不需要循环已经使用的数组(然后Intellij不会给你这个警告)或相对于当前对象的索引位置,那么你有索引< / p>
答案 2 :(得分:1)
如果你有一个不同类型的数组,那么Array变量的类型应该是超类。
无论如何,如果你要在循环中搜索特定类型的电影,你必须进行明确的检查(不是很好的设计)。
所以你使用哪个循环真的没什么区别......因为每个循环都会更简单,没有任何缺点。
答案 3 :(得分:1)
如果你在一个数组中有“动作,喜剧和戏剧”,则rentedMovies必须是“电影”类。因此,如果你在for循环中迭代它们,你就像“电影”一样迭代它们,而不是像“动作,喜剧或戏剧”。
建议的IDE迭代与您使用的相同,但如果您决定将数组更改为List,可能会更直观并可用于很多类(如List)。