JavaGuide
JavaGuide copied to clipboard
关于静态方法为什么不能调用非静态代码的原因?
静态方法是属于类的而动态方法属于实例对象,因此在类加载的时候就会为其分配内存,可以通过类名直接去访问,非静态成员(变量和方法)属于类的对象,所以只有该对象初始化之后才存在,然后通过类的对象去访问。所以说如果我们在静态方法中调用非静态成员变量会超前,可能会调用了一个还未初始化的变量,因此编译器会报错。
@kebukeyi 你cite的这段就是原因
静态方法是属于类的而动态方法属于实例对象,因此在类加载的时候就会为其分配内存,可以通过类名直接去访问,非静态成员(变量和方法)属于类的对象,所以只有该对象初始化之后才存在,然后通过类的对象去访问。所以说如果我们在静态方法中调用非静态成员变量会超前,可能会调用了一个还未初始化的变量,因此编译器会报错。
👍可以指出具体需要完善的位置。 可以提交一个PR完善一下不?
@kebukeyi 更详细的来说你得看类加载
和对象创建
了, ref: 深入理解JVM
说一下我的看法:我们可以直接用类名调用静态方法,这个静态方法肯定必须要在我们调用之前就要被初始化好,那么也就是说在类被加载的时候就会被初始化好了。具体阶段应该在类加载的初始化阶段,这时会执行clint方法对静态变量进行赋值和static{}代码块的初始化。这时候是不知道有非静态代码的。所以会报错 创建实例对象的时候就可以发现对于static{}中的代码先执行,然后再是{}代码块里面的被执行,再是构造方法被执行。而当构造方法被执行时,一个对象实例再算创建。这时候才能调用非静态的代码,所以静态方法是不能调用非静态代码的
@zouyishan 讲的差不多是这个意思, 但是有点偏差, 我补充一下.
首先, JVM中方法是不存在initialization
这个过程的, 确切的描述应该是调用和执行. 此外, 类加载的时候, 才存在类初始化这个阶段.
zouyishan的解释可以理解为这么一句话:
You can't call something that doesn't exist. Since you haven't created an object, the non-static method doesn't exist yet. A static method (by definition) always exists.
更深一点的探究应该涉及到方法调用的过程. 如果运行时能够发生静态方法A
调用实例方法B
, 其过程应该如下:
- 当前线程在虚拟机栈中建立
A
的栈帧 -
A
调用B
, 虚拟机栈中建立B
的栈帧 -
B
作为实例方法, 其栈帧的局部变量表中索引为0
处应该存放对应实例对象在内存布局中的地址. 但实例还未被创建, 所以报错.
但是Java编译器会在编译时就检查到这类错误, 直接报错.