动态(运行 时间)多态性如何在 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,这实际上会按预期工作,调用 String
和 Integer
的重写 toString()
方法类,让我感到困惑的是,对于 JVM,arrayList 中的 Integer
和 String
对象被隐式转换为对象,那么 JVM 到底是怎么知道如何转换它们的呢?回到它们被放入 arrayList 之前的状态?对不起,如果这个问题有一个明显的答案,但这对我来说似乎没有多大意义
每个 object 的类型都存储在那个 object 的 header 中。当您将 reference 转换为 object 时,这不会以任何方式改变 object。
例如,当您调用 .toString
时,它会从 类 的描述中查找要调用的方法。注意:如果可以优化代码,就不必每次都这样做。
假设您有一个 Foo
class
和一个名为 arr
的 ArrayList<Object>
。当您说 arr.add(new Foo())
时,Foo
class
的新对象作为新元素添加到 arr
。这是可能的,因为 Foo
是 class
并且继承自 Object
。但是,对象是 Foo
,即使 Foo
是从 Object
继承的。因此,当您调用它的 toString
时,它会调用您创建的 Foo
对象的 toString
。
假设您有一个 Bird
和 Eagle
fly
的数组列表。所以,如果你调用一个 Bird
的 fly()
方法,它实际上是一个 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).
现在回答你的问题:
(我怎样才能让 String 和 Integer 恢复正常(尽管我仍然需要 type-cast 它们))原因是 String 和 wrapper classes(Integer 是一个包装器 class)已经覆盖了从 Object 继承的 toString() 方法。所以打印那些 objects 给出了实际值。
(JVM 是如何知道将它们转换为哪种类型的)JVM 在 returning 之前实际上并不知道将哪个 object 转换为哪种类型.它只会 return 一个 Object 的实例(这就是 JVM 对 object 的全部了解)。我们必须明确地将其转换为适当的类型。
希望我回答了你的问题。如果不清楚,请告诉我。
有关运行时多态性的详细描述(您的标题问题)在此站点给出:http://www.javatpoint.com/runtime-polymorphism-in-java
假设您有一个对象数组列表 ArrayList<Object> arr = new ArrayList<Object>();
,然后您用几个不同的对象填充这个数组列表,所有这些对象都继承自 object
。
arr.add(new Integer(1));
arr.add("Im a String");
arr.add(new SomeOtherObject);
假设您随后循环调用 .toString()
方法的 arrayList,这实际上会按预期工作,调用 String
和 Integer
的重写 toString()
方法类,让我感到困惑的是,对于 JVM,arrayList 中的 Integer
和 String
对象被隐式转换为对象,那么 JVM 到底是怎么知道如何转换它们的呢?回到它们被放入 arrayList 之前的状态?对不起,如果这个问题有一个明显的答案,但这对我来说似乎没有多大意义
每个 object 的类型都存储在那个 object 的 header 中。当您将 reference 转换为 object 时,这不会以任何方式改变 object。
例如,当您调用 .toString
时,它会从 类 的描述中查找要调用的方法。注意:如果可以优化代码,就不必每次都这样做。
假设您有一个 Foo
class
和一个名为 arr
的 ArrayList<Object>
。当您说 arr.add(new Foo())
时,Foo
class
的新对象作为新元素添加到 arr
。这是可能的,因为 Foo
是 class
并且继承自 Object
。但是,对象是 Foo
,即使 Foo
是从 Object
继承的。因此,当您调用它的 toString
时,它会调用您创建的 Foo
对象的 toString
。
假设您有一个 Bird
和 Eagle
fly
的数组列表。所以,如果你调用一个 Bird
的 fly()
方法,它实际上是一个 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).
现在回答你的问题:
(我怎样才能让 String 和 Integer 恢复正常(尽管我仍然需要 type-cast 它们))原因是 String 和 wrapper classes(Integer 是一个包装器 class)已经覆盖了从 Object 继承的 toString() 方法。所以打印那些 objects 给出了实际值。
(JVM 是如何知道将它们转换为哪种类型的)JVM 在 returning 之前实际上并不知道将哪个 object 转换为哪种类型.它只会 return 一个 Object 的实例(这就是 JVM 对 object 的全部了解)。我们必须明确地将其转换为适当的类型。
希望我回答了你的问题。如果不清楚,请告诉我。
有关运行时多态性的详细描述(您的标题问题)在此站点给出:http://www.javatpoint.com/runtime-polymorphism-in-java