为什么非静态类变量在运行时初始化而在Java中没有编译时

Vij*_*wal 0 java jvm

这是问题的扩展:Java中初始化的顺序

所以在代码块中:

public class Point {

int y = getX();
int x = 42;

int getX() { 
    return x; 
}

public static void main (String s[]) {
    Point p = new Point();
    System.out.println(p.x + "," + p.y);
}
Run Code Online (Sandbox Code Playgroud)

}

它输出 42,0

虽然通过描述Java编译器和运行时的行为来回答上述问题,但仍然困扰我为什么编译器不将x(42)的初始值烘焙到字节码中?我知道静态变量的值嵌入到字节码中,因为它们是类级变量,并且它们不占用对象内存中的任何空间,但是为类级非静态变量嵌入任何初始值也没有意义也进入字节码?这样,上面的代码将更符合预期的行为,并且我猜测对象的实例化会更快(因为分配给x的内存将立即包含42因此节省了解析类中初始化行的时间每次创建Point类的对象时)

我怀疑这可能与类字节码大小,对象初始化效率和编译时效率之间的权衡有关.

我希望对Java编译器/运行时有深入了解的人可以对此有所了解.了解框架如何在内部工作总能帮助我们编写更好的代码:-)

Lou*_*man 6

这不是效率问题; 这是一个有明智语义的问题.

Java设计者希望初始化的行为是相同的,无论x是定义为42或将是getFortyTwo(),因为如果该行为不同,那么这会导致各种方式无意中射击自己的脚.所以他们在JLS中指定了哪个顺序字段初始化发生,并且该顺序与是常量还是方法调用或马铃薯无关x.(仅供参考,那就是你在声明中的字段的顺序-如果你颠倒的顺序x,并y在您的类,y将被设置为42)

坦率地说,我敢打赌,编译器烘烤分配y = 0到构造,因为JLS的语义需要的是y = 0在此基础上的代码.