【问题标题】:Polymorphism and instanceof confusion多态性和混淆实例
【发布时间】:2014-05-04 02:06:45
【问题描述】:

我很困惑一个对象是instanceof 两个不同的类。例如:

EnglishTest x = new EnglishQuiz();
if (x instanceof EnglishTest){
   System.out.print("P");
}
if (x instanceof EnglishQuiz){
   System.out.print("P");
} 

在这两种情况下,我都会打印出“P”。我的问题是为什么?

我知道x 的类型是EnglishTest,但既然我在做new EnglishQuiz,这不应该意味着我正在创建EnglishQuiz 的实例而不是EnglishTest 吗?这里发生了什么?

【问题讨论】:

  • EnglishQuizEnglishTest 的一种吗?
  • 是的 EnglishQuiz extends EnglishTest 很抱歉没有添加。
  • 这有点像生物学。人类是哺乳动物,长颈鹿也是。每个 Human 都是 Human 类的一个实例,同时也是 Mammal。每只长颈鹿都是长颈鹿的一个实例,也是哺乳动物的一个实例。但是长颈鹿不会是人类的一个实例,反之亦然。在这种情况下,哺乳动物是人类和长颈鹿的超类,它们具有一些共同的属性。

标签: java oop polymorphism instanceof


【解决方案1】:

如果此行编译:

EnglishTest x = new EnglishQuiz();

那么EnglishTestEnglishQuiz之间一定存在is-a的关系;具体来说,EnglishQuiz 必须是EnglishTest 的子类型,就像IntegerNumber 一样。

因此,x instanceof EnglishTest 为真,同样Integer instanceof Number 为真。毕竟EnglishQuiz 就是EnglishTest

查看 Java 语言规范Section 15.20.2

在运行时,如果 RelationalExpression 的值不为 null,并且可以将引用强制转换(第 15.16 节)到 ReferenceType 而不会引发 ClassCastException,则 instanceof 运算符的结果为真。否则结果为假。

因为EnglishQuiz 总是可以转换为EnglishTest(这种转换称为向上转换并且总是允许的,因为一个对象总是可以归类为其超类型),instanceof 运算符返回@987654337 @。

另一种可视化方式可能是这样的:

          Object
             |
          Number
           /  \
      Integer  Float
      /     \
     Pos.  Neg.
    /  \   /  \
   1    2 -4  -5 

如果yx 的类型相同,或者如果您可以从x 向上到达y,则x instanceof y 将返回true。

【讨论】:

  • 我理解,但我的困惑来自于我总是记得一个对象实例是用new 创建的,至少这是我的老师告诉我的。然而现在显然有两个实例,即使只有 EnglishQuiz 已被初始化。根据您所说的以及根据 is-a 关系,说 x 是 EnglishQuiz 和 EnglishTest 的实例真的安全准确吗?
  • 没有两个实例;唯一的实例是您使用 new 关键字创建的实例。 typeinstance 是有区别的;实例只是从类创建的对象,而类型是与对象一起出现并描述它在 Java 类型层次结构中的位置的一段数据。
  • @SimonMita instanceof 指的是类型。如果该实例也继承了类型,它将返回 true。所有的类都是instanceof Object。检查我的答案
  • 你说得对,xEnglishQuizEnglishTest 的一个实例。这就像说1 is-a WholeNumber is-a Integer is-a- Number is-a- Object。你只有一个1,但它是所有这些类型的一个实例。
  • 好吧,这是有道理的。谢谢。
【解决方案2】:
class Test {
     //implicitly inherits type Object
}

class Quiz extends Test {
     //explicitly inherits type Test
     //implicitly inherits type Object
}

class PopQuiz extends Quiz {
     //explicitly inheirts type Quiz
     //implicitly inheirts type Test and Object
}

Object -> Test -> Quiz -> PopQuiz

instanceof 指的是实例的类型。如果一个实例隐式或显式“扩展”了一个类,那么它就是该类型的实例,因为它继承了其扩展的类的类型(以及任何其他扩展的类,如我的层次结构示例所示)。

PopQuiz 既是测验又是测试。因此,PopQuiz 的实例继承了 Quiz 和 Test 两种类型,因此它是 Quiz AND Test 的实例。

【讨论】:

  • 哦,我想我在想一些关于 instaceof 关键字的不真实的事情。
  • @SimionMita 你可以张贴你相信的东西,并询问它是否真实
  • 好吧,根据你们提到的instanceof 检查一个类是否是一个类的实例,但正如我刚刚了解到的,它也会检查并返回 true,如果你正在检查的子类给定的类,例如我的EnglishQuiz
  • @SimionMita 你的意思是“检查一个对象是否是某个类的实例”?因为请记住,当您扩展时,您将那里的内容添加到上面,这意味着子类仍然被认为是超类,只是一个更复杂的版本。 class Poodle extends Dog { } Poodle 是一只狗,它只是一个更复杂的版本。这就是为什么这是可能的:Dog poodle = new Poodle()。这样做意味着“如果子类覆盖了方法,请使用 Poodle 中的代码。除此之外,忽略 Poodle 中不在 Dog 中的任何方法(不是从 Dog 继承的方法)
  • 是的,我知道子类不断添加到超类的内容中:)。基本上我的意思是instanceof 也适用于子类。所以Poodle 将是instaceof Dog。对吗?
猜你喜欢
  • 1970-01-01
  • 2017-11-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-09-18
  • 2015-07-01
  • 1970-01-01
相关资源
最近更新 更多