JavaGuide icon indicating copy to clipboard operation
JavaGuide copied to clipboard

关于静态方法为什么不能调用非静态代码的原因?

Open kebukeYi opened this issue 4 years ago • 5 comments

   静态方法是属于类的而动态方法属于实例对象,因此在类加载的时候就会为其分配内存,可以通过类名直接去访问,非静态成员(变量和方法)属于类的对象,所以只有该对象初始化之后才存在,然后通过类的对象去访问。所以说如果我们在静态方法中调用非静态成员变量会超前,可能会调用了一个还未初始化的变量,因此编译器会报错。

kebukeYi avatar Oct 29 '20 08:10 kebukeYi

@kebukeyi 你cite的这段就是原因

ZacBi avatar Oct 30 '20 07:10 ZacBi

   静态方法是属于类的而动态方法属于实例对象,因此在类加载的时候就会为其分配内存,可以通过类名直接去访问,非静态成员(变量和方法)属于类的对象,所以只有该对象初始化之后才存在,然后通过类的对象去访问。所以说如果我们在静态方法中调用非静态成员变量会超前,可能会调用了一个还未初始化的变量,因此编译器会报错。

👍可以指出具体需要完善的位置。 可以提交一个PR完善一下不?

Snailclimb avatar Oct 31 '20 00:10 Snailclimb

@kebukeyi 更详细的来说你得看类加载对象创建了, ref: 深入理解JVM

ZacBi avatar Oct 31 '20 10:10 ZacBi

说一下我的看法:我们可以直接用类名调用静态方法,这个静态方法肯定必须要在我们调用之前就要被初始化好,那么也就是说在类被加载的时候就会被初始化好了。具体阶段应该在类加载的初始化阶段,这时会执行clint方法对静态变量进行赋值和static{}代码块的初始化。这时候是不知道有非静态代码的。所以会报错 创建实例对象的时候就可以发现对于static{}中的代码先执行,然后再是{}代码块里面的被执行,再是构造方法被执行。而当构造方法被执行时,一个对象实例再算创建。这时候才能调用非静态的代码,所以静态方法是不能调用非静态代码的

zouyishan avatar Dec 27 '20 13:12 zouyishan

  @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, 其过程应该如下:

  1. 当前线程在虚拟机栈中建立A的栈帧
  2. A调用B, 虚拟机栈中建立B的栈帧
  3. B作为实例方法, 其栈帧的局部变量表中索引为0处应该存放对应实例对象在内存布局中的地址. 但实例还未被创建, 所以报错.

  但是Java编译器会在编译时就检查到这类错误, 直接报错.

ZacBi avatar Dec 29 '20 04:12 ZacBi