我正在尝试使用这样的静态块:
我有一个名为Base.java
public class Base {
static public int myVar;
}
派生类Derived.java
:
public class Derived extends Base {
static
{
Base.myVar = 10;
}
}
我的main
功能是这样的:
public static void main(String[] args) {
System.out.println(Derived.myVar);
System.out.println(Base.myVar);
}
这会将输出打印为0 0
,就像我预期的那样10 0
。有人可以解释这种行为吗?另外,如果我希望我的派生类设置静态变量的值,我该如何实现呢?
答案 0 :(得分: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);
}
}
从java规范中,当初始化类(并执行静态块)时:
12.4.1初始化发生时类或接口类型T将在第一次出现之前立即初始化:
•T是一个类,创建了一个T实例 •T是一个类,调用T声明的静态方法 •分配由T声明的静态字段 •使用由T声明的静态字段,该字段不是常量变量(§4.12.4) •T是顶级类(第7.6节),并且执行在词典内嵌套在T(第8.1.3节)内的断言语句(第14.10节)。
答案 1 :(得分:6)
在初始化类之前,不会运行静态初始化程序块。参见Java Language Specification第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);
}
}
此程序仅打印:
1729
因为Sub类从未初始化;对Sub.taxi的引用 是对Super类中实际声明的字段的引用 不会触发Sub类的初始化。
答案 2 :(得分:1)
myVar
只有一个副本,父类和子类都会共享相同的副本。
直到并且除非儿童课程被启动。
答案 3 :(得分:0)
这是Java规范的链接 - 第8.7节讨论了静态初始化器。它提供了有关它们应如何运行以及它们被调用的顺序的详细信息。 http://docs.oracle.com/javase/specs/jls/se7/html/jls-8.html#jls-8.7
答案 4 :(得分:0)
当我们做的时候
class Base {
public static int myVar = 0;
static {
System.out.println("Base");
}
}
class Derived extends Base {
static {
System.out.println("Derived");
Base.myVar = 9;
}
}
public class StaticBlock {
public static void main(String[] args) {
System.out.println(Base.myVar);
System.out.println(Derived.myVar);
}
}
输出将是
Base
0
0
这意味着派生类的静态块没有执行.. !!