我即将在我的公司(我是一名实习生)中介绍Java中的继承。 我想我已经明白了,我也知道如何使用它。但有一点不太确定。 存储在存储器中的方法在哪里。对象如何知道方法的位置?
例如:
我们有这门课。
class Animal {
private String desc1;
protected String desc2;
public void breath() {
}
public void eat() {
}
}
和这堂课:
class Dog extends Animal() {
public void bark() {
}
}
我们现在制作一个狗类的对象:
狗狗=新狗();
所以现在我的问题:
类被加载到堆中。所以狗和动物都在堆里。 (编辑:这是错误的,类没有加载到堆中,看下面的答案。)。
所以,让我们说dog.bark()
。
狗如何知道树皮方法在堆中的位置?知道狗类在哪里?
接下来我们制作dog.eat():
因此,当狗知道狗在哪里时,狗会知道动物在哪里或者狗知道动物在哪里吗?
知道我的意思是它有一个地址在堆上。
当我覆盖一个方法时怎么样?存储在哪里?
答案 0 :(得分:8)
首先,这是依赖JVM的,并且JLS或JVM规范中没有要求 应该如何解决这些问题,只有 它们应该被解决
狗如何知道树皮方法在堆中的位置?
通常你有一个名为Virtual Method Table或简称v表的东西。您可以将此视为表映射方法标识符(例如bark
)到函数指针。也就是说,如果您调用bark
,VM将查看它的v-table并调用bark
指向的方法。扩展类并覆盖方法时,只需交换方法指针指向覆盖函数。
狗怎么知道树皮方法在堆中的位置?知道狗类在哪里?
方法和类不以与实例相同的意义存储在堆上。他们为什么会这样?
也许你和我开始使用面向对象编程时的误解一样。我想如果我实例化10 Dog
,我会得到10个树皮方法。这不是真的。实例化对象时“得到”的基本上是成员变量和this
引用。然后,您可以将this
引用视为在调用非静态方法时传递的额外参数。
答案 1 :(得分:3)
不,类没有加载到堆中(至少不是你可以认为是Java中的堆),而是加载到一个名为PermGen space的内存部分。
我无法确切地告诉你Java如何存储这些信息,但我认为它类似于C ++的工作方式(vtable),因为它通常是在JVM本机代码中完成的。
答案 2 :(得分:0)
首先在java中创建的任何对象在对象头中的某处都有一个类引用。链接“静态”(不覆盖,JIT知道是否有任何方法被覆盖,但是某些子类)方法很简单,可以内联或只调用代码所在的某个特定点。
由于优化的代码是使用寄存器中保存的值调用的,而java规范要求它们在堆栈上,因此更复杂。
调用覆盖方法的方法很简单:
了解处理器执行代码的方式以及调用/内联的方法等是一个很大的主题。我想其他一些基本概念都缺失了。