具有继承的静态块的行为

Ash*_*sha 31 java inheritance static static-block

我试图使用这样的静态块:

我有一个基类叫 Base.java

public class Base {

    static public int myVar;

}
Run Code Online (Sandbox Code Playgroud)

派生类Derived.java:

public class Derived extends Base {

    static
    {
        Base.myVar = 10;
    }
}
Run Code Online (Sandbox Code Playgroud)

我的main功能是这样的:

public static void main(String[] args)  {
    System.out.println(Derived.myVar);
    System.out.println(Base.myVar);
}
Run Code Online (Sandbox Code Playgroud)

这打印输出0 0就像我预期的那样10 0.有人可以解释这种行为吗?另外,如果我希望我的派生类设置静态变量的值,我该如何实现呢?

Nik*_*zov 22

我认为.您不会调用任何Derived属性(myVar属于Base,不属于Derived).并且java没有运行静态块Derived.如果向其添加一些静态字段Derived并对其进行访问,则java将执行所有静态块.

class Base {

    static public int myVar;

}


class Derived extends Base {

    static public int myVar2;

    static
    {
        Base.myVar = 10;
    }
}


public class Main {
    public static void main( String[] args ) throws Exception {
        System.out.println(Derived.myVar2);
        System.out.println(Base.myVar);
    }
}
Run Code Online (Sandbox Code Playgroud)

从java规范,当初始化类(并执行静态块)时:

12.4.1初始化发生时类或接口类型T将在第一次出现以下任何一个之前立即初始化:

•T是一个类,并创建了一个T实例.
•T是一个类,并且调用由T声明的静态方法.
•分配由T声明的静态字段.
•使用由T声明的静态字段,该字段不是常量变量(第4.12.4节).
•T是顶级类(第7.6节),并且执行在词典内嵌套在T(第8.1.3节)内的断言语句(第14.10节).

  • @Jigar但你没有访问`j`. (3认同)

esa*_*saj 6

在初始化类之前,不会运行静态初始化程序块.请参阅Java语言规范段落8.7(静态初始化程序)和12.4.1(初始化时):

在类初始化时执行类中声明的静态初始化程序(第12.4.2节).与类变量的任何字段初始值设定项(第8.3.2节)一起,静态初始值设定项可用于初始化类的类变量.

以下是JLS 12.4.1中的类似示例:

class Super {
  static int taxi = 1729;
}
class Sub extends Super {
  static { System.out.print("Sub "); }
}
class Test {
  public static void main(String[] args) {
    System.out.println(Sub.taxi);
  }
}
Run Code Online (Sandbox Code Playgroud)

此程序仅打印:

1729
Run Code Online (Sandbox Code Playgroud)

因为Sub类从未初始化; 对Sub.taxi的引用是对在Super类中实际声明的字段的引用,并且不触发Sub类的初始化.

  • @NikitaBeloglazov:在您的示例中,static-block起作用,因为在引用Derived时初始化顶级类Base.有关详细信息,请参阅JLS"12.4.1初始化发生时",初始化过程非常复杂:`对静态字段的引用(第8.3.1.1节)仅导致实际声明它的类或接口的初始化,即使它可能通过子类的名称,子接口或实现接口的类来引用 (2认同)
  • 是的,你是对的.但是你的例子可能会令人困惑,因为它看起来只有在创建类的实例时才初始化类. (2认同)