为什么 super class 中的 static blocks/static 变量在 main 之前初始化?
Why are static blocks/static variables in super class initialized before main?
public class sup {
static {
System.out.print("In Sup ");
}
}
public class sub extends sup {
static {
System.out.print("In Sub");
}
}
final public class test extends sub {
static int a = 10;
static {
System.out.print(" In test" + a);
}
{
System.out.print(" In test" + a);
}
public static void main(String[] args) {
}
}
输出:
In Sup In Sub In test10
但这里我不是在创建对象。 JVM 应该调用静态的 main 方法并仅初始化 main class。所以它应该给出输出 In test10
。
谁能解释一下为什么我得到不同的输出?
静态块执行beforemain
方法。由于test extends sub
和sub extends sup
,sup
的静态块将被执行,然后是sub
的静态块,最后是test
的静态块。
详见JLS - 12.4.1. When Initialization Occurs:
class Super {
static { System.out.print("Super "); }
}
class One {
static { System.out.print("One "); }
}
class Two extends Super {
static { System.out.print("Two "); }
}
class Test {
public static void main(String[] args) {
One o = null;
Two t = new Two();
System.out.println((Object)o == (Object)t);
}
}
这个例子演示了执行顺序,输出将是
Super Two false
static
初始化程序块在 class 加载程序加载 class 时被调用。简而言之,这里的执行顺序如下:
- 尝试加载
test
,看到它取决于sub
- 尝试加载
sub
,看到它取决于sup
- 尝试加载
sup
sup
已加载,其 static
块打印 "In Sup"
sub
的加载已恢复,其 static
块打印 "In Sub"
test
的加载恢复,a
初始化为10
.
test
的 static
块被执行并打印 " In test10"
test
的 main
函数被执行,但什么都不做,因为它是空的。
当 class 为 运行 时,无论您是否创建 class 的实例,JVM 都会加载 class。
这在 Java 语言规范的 Section 12.1.1 中有明确规定。
java Test reboot Bob Dot Enzo
The initial attempt to execute the method main of class Test discovers that the class Test is not loaded - that is, that the Java Virtual Machine does not currently contain a binary representation for this class. The Java Virtual Machine then uses a class loader to attempt to find such a binary representation
这里我不是在创建对象。。这与对象的创建无关。即使在创建对象之前,也必须加载/初始化 class 及其相关依赖项。 类 可以在您访问其中存在的 static methods
时加载(main
是 static
)。因为你的 test
class 依赖于 sub
而 sub
依赖于 sup
,JVM 加载它们的顺序是 sup --> sub --> test 所以class 'test' 的依赖关系已解决。除非这样做,否则您的 'test' 不能使用其超 classes 的字段/方法。
static block/variable/methods 不可继承,因为它们属于 class 而不是对象。
你得到这个输出的原因是,JVM 需要加载 main class 的完整层次结构来执行 main 方法(parent class 然后是 child)。
如果您从测试 class 中删除继承,您将只得到 'In test10'。
public class sup {
static {
System.out.print("In Sup ");
}
}
public class sub extends sup {
static {
System.out.print("In Sub");
}
}
final public class test extends sub {
static int a = 10;
static {
System.out.print(" In test" + a);
}
{
System.out.print(" In test" + a);
}
public static void main(String[] args) {
}
}
输出:
In Sup In Sub In test10
但这里我不是在创建对象。 JVM 应该调用静态的 main 方法并仅初始化 main class。所以它应该给出输出 In test10
。
谁能解释一下为什么我得到不同的输出?
静态块执行beforemain
方法。由于test extends sub
和sub extends sup
,sup
的静态块将被执行,然后是sub
的静态块,最后是test
的静态块。
详见JLS - 12.4.1. When Initialization Occurs:
class Super {
static { System.out.print("Super "); }
}
class One {
static { System.out.print("One "); }
}
class Two extends Super {
static { System.out.print("Two "); }
}
class Test {
public static void main(String[] args) {
One o = null;
Two t = new Two();
System.out.println((Object)o == (Object)t);
}
}
这个例子演示了执行顺序,输出将是
Super Two false
static
初始化程序块在 class 加载程序加载 class 时被调用。简而言之,这里的执行顺序如下:
- 尝试加载
test
,看到它取决于sub
- 尝试加载
sub
,看到它取决于sup
- 尝试加载
sup
sup
已加载,其static
块打印"In Sup"
sub
的加载已恢复,其static
块打印"In Sub"
test
的加载恢复,a
初始化为10
.test
的static
块被执行并打印" In test10"
test
的main
函数被执行,但什么都不做,因为它是空的。
当 class 为 运行 时,无论您是否创建 class 的实例,JVM 都会加载 class。
这在 Java 语言规范的 Section 12.1.1 中有明确规定。
java Test reboot Bob Dot Enzo
The initial attempt to execute the method main of class Test discovers that the class Test is not loaded - that is, that the Java Virtual Machine does not currently contain a binary representation for this class. The Java Virtual Machine then uses a class loader to attempt to find such a binary representation
这里我不是在创建对象。。这与对象的创建无关。即使在创建对象之前,也必须加载/初始化 class 及其相关依赖项。 类 可以在您访问其中存在的 static methods
时加载(main
是 static
)。因为你的 test
class 依赖于 sub
而 sub
依赖于 sup
,JVM 加载它们的顺序是 sup --> sub --> test 所以class 'test' 的依赖关系已解决。除非这样做,否则您的 'test' 不能使用其超 classes 的字段/方法。
static block/variable/methods 不可继承,因为它们属于 class 而不是对象。
你得到这个输出的原因是,JVM 需要加载 main class 的完整层次结构来执行 main 方法(parent class 然后是 child)。
如果您从测试 class 中删除继承,您将只得到 'In test10'。