动态(运行 时间)多态性如何在 java 中工作?换句话说,JVM 如何知道要调用哪些方法?

How does Dynamic (run-time) polymorphism work in java? In other words how does the JVM know which methods to call?

假设您有一个对象数组列表 ArrayList<Object> arr = new ArrayList<Object>();,然后您用几个不同的对象填充这个数组列表,所有这些对象都继承自 object

arr.add(new Integer(1));
arr.add("Im a String");
arr.add(new SomeOtherObject);

假设您随后循环调用 .toString() 方法的 arrayList,这实际上会按预期工作,调用 StringInteger 的重写 toString() 方法类,让我感到困惑的是,对于 JVM,arrayList 中的 IntegerString 对象被隐式转换为对象,那么 JVM 到底是怎么知道如何转换它们的呢?回到它们被放入 arrayList 之前的状态?对不起,如果这个问题有一个明显的答案,但这对我来说似乎没有多大意义

每个 object 的类型都存储在那个 object 的 header 中。当您将 reference 转换为 object 时,这不会以任何方式改变 object。

例如,当您调用 .toString 时,它会从 类 的描述中查找要调用的方法。注意:如果可以优化代码,就不必每次都这样做。

假设您有一个 Foo class 和一个名为 arrArrayList<Object>。当您说 arr.add(new Foo()) 时,Foo class 的新对象作为新元素添加到 arr。这是可能的,因为 Fooclass 并且继承自 Object。但是,对象是 Foo,即使 Foo 是从 Object 继承的。因此,当您调用它的 toString 时,它会调用您创建的 Foo 对象的 toString

假设您有一个 BirdEagle fly 的数组列表。所以,如果你调用一个 Birdfly() 方法,它实际上是一个 Eagle,它会飞得很漂亮。这实际上是继承的一大特点,非常有意义。

事实是,JVM 不知道如何将它们转换回原来的状态。我们将不得不为此完成任务。考虑一下...(在您的代码行之后)

SomeOtherObject obj = arr.get(2); //trying to access the third element

你肯定会得到 compile-time 错误。好的,现在尝试显式转换 object returned.

SomeOtherObject obj = (SomeOtherObject)arr.get(2);

它工作得很好!为什么?因为从 get() 方法得到的 object return 与被转换的类型兼容。

现在也考虑这个(我知道我做不到),只是为了检查 JVM 是否可以告诉我们哪个 object 是什么。

SomeOtherObject obj = (SomeOtherObject)arr.get(1); //1 instead of 2

是的是的我知道这个数组的第二个成员是一个字符串,我不能这样做。但是让我们看看 JVM 有什么要说的(虽然没有编译器错误)。我们得到的消息是 object 无法转换为指定的类型。 (但我们没有得到 object 的确切类型)。

你明白了吗?这里的 JVM 只知道传递给这个数组的 objects 只是 objects 与 Object 兼容。它不知道我们是否真的传递了字符串、一个 int(或者更确切地说是 Integer,因为基元不能存储在 collections 中),或者 SomeOtherObject([=44 中定义的任何 class =] 是 Object 的直接子 class).

现在回答你的问题:

  1. (我怎样才能让 String 和 Integer 恢复正常(尽管我仍然需要 type-cast 它们))原因是 String 和 wrapper classes(Integer 是一个包装器 class)已经覆盖了从 Object 继承的 toString() 方法。所以打印那些 objects 给出了实际值。

  2. (JVM 是如何知道将它们转换为哪种类型的)JVM 在 returning 之前实际上并不知道将哪个 object 转换为哪种类型.它只会 return 一个 Object 的实例(这就是 JVM 对 object 的全部了解)。我们必须明确地将其转换为适当的类型。

希望我回答了你的问题。如果不清楚,请告诉我。

有关运行时多态性的详细描述(您的标题问题)在此站点给出:http://www.javatpoint.com/runtime-polymorphism-in-java