为什么在创建对象引用时可以使用接口作为类型?

时间:2014-07-14 17:11:53

标签: java

我正在关注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();

6 个答案:

答案 0 :(得分:3)

只有您的代码必须拥有EvenIterator才有意义。

否则应该首选更通用的接口,允许您更改底层实现而无需进一步更改代码。

作为(有点人为的)具体示例,使用 ArrayList来强制执行常量时间索引访问可能是有意义的;在这种情况下,您可能希望避免使用更广义的List,以确保不会破坏应用的时间。

答案 1 :(得分:0)

接口用于以简洁的类型抽象实现的本质,并且甚至可以用作实现类型的引用。这使得客户端类与实际实现类无关,从而使设计成为more robust

答案 2 :(得分:0)

示例对变量类型的DataStructureIterator的选择是一种风格的。它是有效的,因为EvenIteratorDataStructureIterator的子类型,因此每个EvenIterator也是DataStructureIterator

根据经验,通常最好尽可能一般地输入变量和方法参数,并尽可能具体地输入方法返回值。这为您的代码提供了更大的灵活性。根据代码的性质以及您打算如何使用它,您可以做出一般性或具体的“可能性”判断。

答案 3 :(得分:0)

您可以使用该界面的原因是因为EvenIterator DataStructureIterator。在创建引用时应始终使用接口,因为通常不需要知道具体的实现。接口定义了实现类必须符合的契约。使用接口有助于最小化耦合。

使用一个简单的例子,A​​nimal(接口)可以运行(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;,以及我想引用的部分内容:

  

如果存在适当的接口类型,则应使用接口类型声明参数,返回值,变量和字段。

     

...

     

如果您养成使用接口作为类型的习惯,您的程序将更加灵活。如果您决定要切换实现,那么您所要做的就是更改构造函数中的类名(或使用不同的静态工厂)。