继承技术如何运作?

时间:2011-03-03 11:41:40

标签: java class object heap storage

我即将在我的公司(我是一名实习生)中介绍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(): 因此,当狗知道狗在哪里时,狗会知道动物在哪里或者狗知道动物在哪里吗? 知道我的意思是它有一个地址在堆上。 当我覆盖一个方法时怎么样?存储在哪里?

这是帮助。

3 个答案:

答案 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规范要求它们在堆栈上,因此更复杂。

调用覆盖方法的方法很简单:

  • 动态检查实例并像静态示例一样调度调用,这是一个比较/分支调用,比
  • 快得多
  • Inline caches
  • 或已经提到的v-table调用。 v表是最慢的

了解处理器执行代码的方式以及调用/内联的方法等是一个很大的主题。我想其他一些基本概念都缺失了。