繁体   English   中英

java如何知道要返回接口的哪个实现对象?

[英]How does java get to know which implementation object of interface to return?

回答时请保持谦虚,我不是Java开发人员(或一般开发人员)

在尝试使用Java进行xml解析时,我遇到了以下问题-

NodeList nodelist = document.getElementsByTagName("item");

在这里,xml dom对象让我根据我提供的标签名称收集所有对象,但是返回类型是一个称为-nodelist的接口。 由于无法实例化接口,这令我有些惊讶。

保持断点并调试代码,我意识到我实际上为实现NodeList接口的类DeepNodeListImpl获取了对象。

这是怎么发生的? Java如何知道如何在上面声明的语句中返回由我的接口“ object”持有的“某些实现”的对象。

还有一件事-在阅读Java API时,我发现IIOMetadataNode实现了NodeList,但是我之前的代码片段没有使我成为IIOMetadataNode类型的对象

很好的问题。

Java不知道要返回对象的哪个实现。

在您的问题中,您引用Document类及其getElementsByTagName方法。 文档是一个接口,这意味着它本身没有实现代码。

因此,实现Document接口的任何人都可以选择所有详细信息(包括要从getElementsByTagName方法返回的NodeList实现)。

在getElementByTagName的代码中,会有类似

NodeList nodeList = new DeepNodeListImpl();
// do something with nodeList
return nodeList;

Java“知道”使用这种类型,因为该方法的代码将明确选择实现。

方法总是可以返回它所承诺返回的子类,通常,任何值在运行时都可以是它声明为的类型的子类型。

因此,getElementsByTagName的实现者可以自由返回DeepNodeListImpl类型的DeepNodeListImpl ,只要它是NodeList的子类型即可。

这是面向对象编程的功能。 类可以扩展基类(或实现接口)。 然后可以将基类或已实现的接口用作“公分母”。 这意味着:返回某种类型的对象的方法实际上可以返回从该类型派生的任何类的对象。

这就是您的情况。 您也不需要真正使用的实际类-您可以使用接口提供的任何方法。

而且,除了接口类型之外,您不应对返回的类型做任何假设。 仅当您100%绝对确定可以转换为特殊类型时。 示例:如果您现在进行了对DeepNodeListImpl ,但是XML解析器的实现已更改,则如果该实现不再返回DeepNodeListImpl或派生类之一,则可能会在DeepNodeListImpl期间遇到异常。

这是现实生活中的类比。 假设您与一家公司签约,请您派一名园丁。

您期望得到的是一个可以修剪草坪并修剪篱笆的园丁(园丁界面)。

您得到的是一个真实的人,可能是男人,女人,老少皆宜,并且可能会做与园艺无关的事情,例如准备晚餐(实现烹饪界面),但至少可以修剪草坪并修剪树篱(实现园丁界面)。

公司负责确定获得的实施方案(公司扮演“抽象工厂”的角色)。

通常,您并不关心此实现可以执行的与园艺无关的事情。

但是,如果您知道自己的园丁可以做饭,并且想让园丁准备晚餐,那么您需要将园丁投下厨:

Gardener gardener = AbstractFactory.getGardener();
gardener.mowLawn();
// cast 
Cook cook = (Cook) gardener;
cook.prepareDinner();

请注意,这绕过了AbstractFactory提供的抽象(并因此隐藏了信息):您要求园丁,而不应该在意其他技能。 这样的结果是,如果您将来开始使用其他工厂,则可能会遇到不能做饭的园丁,并且您的演员表将在运行时导致ClassCastException(您的晚餐可能会感到可怕)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM