实现接口的Java对象如何存储在内存中?

时间:2016-09-17 12:40:32

标签: java inheritance memory

Java没有多重继承类,但它支持多个类的接口实现。

据我所知,当Java类继承另一个类时,其内存表示如下所示:

class Base {
    int x;
}

class Deriving {
    int y;
}
内存中的

Base

vtable|Base.x
内存中的

Deriving

vtable|Base.x|Deriving.y

此处的所有内容都很清晰,因为Deriving必须包含所有字段Base,所有Deriving的字段都会在Base&#39后立即存储那些。

但是当类实现接口时会发生什么? 例如,我们有以下接口,它们定义了相同的变量,以及一个类:

public interface Y {
    int x = 0; // both Y and Z have this field
    int y = 0;
    void methodY();
}

public interface Z {
    int x = 0; // both Y and Z have this field
    int z = 0;
    void methodZ();
}

public class A implements Y, Z {
    int a;
    int x;
    int y;
    int z;
    public A(int x, int a) {
        this.x = x;
        this.a = a;
    }

    public void methodY() {
        System.out.println("methodY: x = " + x + ", a = " + a);
    }

    public void methodZ() {
        System.out.println("methodZ: x = " + x + ", a = " + a);
    }
}

当我们有:

时会发生什么
A a = new A(5, 6);
Y y = a;
Z z = a;

yz指向的内容以及a的内容如何? vtable看起来如何?它们包含什么?

我唯一可以猜到的是它在内存中看起来像这样:

A.vtable|A.a|Y.vtable|Y.x|Y.y
^ a          ^ y

表示a指向开头,y指向对象的中间。但我仍然无法弄清楚接口如何共享一个字段。

2 个答案:

答案 0 :(得分:0)

  1. 接口没有字段。这应该使内存布局更容易。
  2. 内存布局将每个vtable放在内存中的不同位置。请记住,vtables本身没有方法实现,但是引用了方法在内存中的位置。这允许所有方法相对于vtable的开头位于正确的位置。

答案 1 :(得分:0)

接口没有即时变量,您只能在接口中声明方法签名和静态最终常量。

public class A implements Y, Z {
    int a;
    int x;
    int y;
    int z;
    public A(int x, int a) {
        this.x = x;
        this.a = a;
    }

变量x和y将被视为A类的局部变量。

接口和类将驻留在堆内存中的PermGen中。