我正在关注Oracle的Java在线教程,并对特定的代码行感到困惑。
我正在查看的示例的完整代码位于:http://docs.oracle.com/javase/tutorial/java/javaOO/innerclasses.html
困扰我的特定行是在DataStructure类' printEven()方法:
DataStructureIterator iterator = this.new EvenIterator();
我不明白为什么接口DataStructureIterator被用作迭代器的类型,而我尝试过的实际类型EvenIterator工作得很好,对我来说更有意义:
EvenIterator iterator = this.new EvenIterator();
答案 0 :(得分:3)
只有您的代码必须拥有EvenIterator
才有意义。
否则应该首选更通用的接口,允许您更改底层实现而无需进一步更改代码。
作为(有点人为的)具体示例,使用仅 ArrayList
来强制执行常量时间索引访问可能是有意义的;在这种情况下,您可能希望避免使用更广义的List
,以确保不会破坏应用的时间。
答案 1 :(得分:0)
接口用于以简洁的类型抽象实现的本质,并且甚至可以用作实现类型的引用。这使得客户端类与实际实现类无关,从而使设计成为more robust。
答案 2 :(得分:0)
示例对变量类型的DataStructureIterator
的选择是一种风格的。它是有效的,因为EvenIterator
是DataStructureIterator
的子类型,因此每个EvenIterator
也是DataStructureIterator
。
根据经验,通常最好尽可能一般地输入变量和方法参数,并尽可能具体地输入方法返回值。这为您的代码提供了更大的灵活性。根据代码的性质以及您打算如何使用它,您可以做出一般性或具体的“可能性”判断。
答案 3 :(得分:0)
您可以使用该界面的原因是因为EvenIterator 是 DataStructureIterator。在创建引用时应始终使用接口,因为通常不需要知道具体的实现。接口定义了实现类必须符合的契约。使用接口有助于最小化耦合。
使用一个简单的例子,Animal(接口)可以运行(void run()方法)。然后,您希望拥有Dog和Cat类,并且它们都可以运行,因此您可以实现该接口。现在,你想保留一个可以运行的动物列表,所以你应该使用动物参考而不是狗或猫,因为你需要知道的是动物可以跑,而不是你正在使用哪种动物。
答案 4 :(得分:0)
他们的示例代码有点草率。它本来会更好:
Iterator<Integer> iterator = this.new EvenIterator();
这清楚地表明使用Iterator
的代码只关心它需要Iterator
(在这种情况下为Integer
)。经验丰富的Java程序员经常在示例中看到类似的代码,并希望找到代码所需的一些特定原因,在本例中为DataStructureIterator
。通常,最一般适用的类型更清晰,并且做出更少的假设。例如,我习惯性地写道:
List<V> list = new ArrayList<V>();
(我读作'我需要一个列表,它恰好是ArrayList
,但这与逻辑的其余部分无关。)
答案 5 :(得分:0)
约书亚布洛赫在他的Effective Java书中将整个项目专门用于这个主题 - &#34;通过他们的界面引用对象&#34;,以及我想引用的部分内容:
如果存在适当的接口类型,则应使用接口类型声明参数,返回值,变量和字段。
...
如果您养成使用接口作为类型的习惯,您的程序将更加灵活。如果您决定要切换实现,那么您所要做的就是更改构造函数中的类名(或使用不同的静态工厂)。