运行此代码:
class A {
public int x;
public A() {
function();
}
public void function() {
this.x = 20;
}
public void printhey() { System.out.println("Hey"); }
}
class B extends A {
public B() {
super();
printhey();
}
public void function() {
this.x = 50;
}
}
public class tmp {
public static void main(String[] args) {
System.out.println((new B()).x);
}
}
打印出来:
Hey
50
谁设置了VTBL?在A
的构造函数中,function
已设置为B.但在B
的构造函数中,printhey
设置为A。
答案 0 :(得分:6)
“VTBL”是存储结构中处理的语言工件。也就是说,在C ++中,你可以准确地推断出一个类在RAM中的映射方式。
Java不涉及存储结构,它处理数据结构。您可以轻松地将存储结构用作数据结构,但反过来并不是那么简单。如果您在1991年初碰巧收到了BYTE杂志的副本,您甚至可以找到我赞美将C ++数据结构映射到Commodore Amiga OS ROM内核(Exec)所使用的存储结构的优点的文章。事实上,在那时,“数据结构”一词被用作一种全能,因为我们仍然担心事情会如何恰好适合记忆。
数据结构通常由算法使用。存储结构与内部实现和序列化表单更紧密相关。实际的程序执行需要两者兼而有之,但Java数据结构底层的存储结构应该是不透明的。这是Java“Write Once,Run Anywhere”的重要组成部分。如果您不必担心事物的大小和字节方向,则不必使用“swabbers”和内存偏移计算器来加载应用程序。
某些编程语言不喜欢前向和循环引用。没有它们,Java很难做到。但是,对代码的硬引用和对字节码绑定的方法签名的引用之间存在差异,并且(可能)最终将JIT编译为机器代码。甚至在一些更先进的JVMS中重新优化和重新编译。这一切归结为实际上,你有多次通过类,其中一个建立字典,另一个插入链接。如果合适,还包括自动内联。
答案 1 :(得分:2)
Java中没有VTBL的概念; ergo,没有VTBL。
创建的对象是一个新的B(),并且B(当时)有一个函数(在B中定义,因为它覆盖了A)和printhey(从A继承)。所以X被分配给50-A的构造函数,通过B的构造函数调用,通过调用'function'(来自B)来执行set操作。然后我们调用'printhey'(在B中的super()之后的行)调用继承的fn。然后,我们返回获取X的实例,因此您看到50。
答案 2 :(得分:0)
简单的答案是'JVM,当然'。加载B时,JVM完全了解类层次结构,并已解决所有引用。它不像C ++。当然,我将你解释为使用术语VTBL比喻。在任何严重的JRE中都没有像VTBL那样的实际数据结构。