讲到实现和继承在内存中的区别,首先我们讲讲语法上他们的区别:
Java只允许单继承却能实现多接口。
对于单继承,试想一下,如果有两个父类ParentA和ParentB、一个子类ChildC,如果ChildC想super.两个父类的一个同样的方法F即super.F(),请问是调用了ParentA中的F还是ParentB中的F,明显就很难分清。
对于多实现,会在实现类里具体定义方法体,你可以说他是实现了ParentA的F,也可以说是实现了ParentB的F,因为实际运行的都是ChildC中具体F()实现的过程,不存在上面那种分不清的情况。
那对于JVM就内存的加载和调用来说,A是接口,B是具体实现类:
A a =new B();
在堆中创建一个B实例对象内存空间,在栈中创建一个引用变量a,a的地址指向B的内存空间。
a.print();
用A中的方法去调用B中的同名方法,这当然是正确的,因为B类实现了A接口。
B的实例方法存在一个专门的区叫方法区,B中所有的方法在创建B实例的时候B类的class方法二进制字节码就已经加载到了方法区,所有此类的方法调用的类对象均可以共享此代码空间,常量池会存放在堆里,当调用B中的方法的时候,先从方法区通过方法表快速拿到调用方法的字节码指令入栈并创建栈帧。对于a.print(),实际上在创建B对象的堆空间的时候,声明在栈里的a引用指向了B对象的内存空间首地址,所以在调用print方法的时候会去这个对象空间找对应的方法字节码,所以最终执行的是B中的print方法。
网友评论