Java中静态/实例初始值设定项块的运行顺序是什么?
假设一个项目包含几个类,每个类都有一个静态初始值设定项块。这些区块的运行顺序是什么?我知道在一个类中,这些块是按照它们在代码中出现的顺序运行的。我已经读到,这在不同的类中是相同的,但是我编写的一些示例代码不同意这一点。我使用了以下代码:Java中静态/实例初始值设定项块的运行顺序是什么?,java,static-initializer,Java,Static Initializer,假设一个项目包含几个类,每个类都有一个静态初始值设定项块。这些区块的运行顺序是什么?我知道在一个类中,这些块是按照它们在代码中出现的顺序运行的。我已经读到,这在不同的类中是相同的,但是我编写的一些示例代码不同意这一点。我使用了以下代码: package pkg; public class LoadTest { public static void main(String[] args) { System.out.println("START"); new
package pkg;
public class LoadTest {
public static void main(String[] args) {
System.out.println("START");
new Child();
System.out.println("END");
}
}
class Parent extends Grandparent {
// Instance init block
{
System.out.println("instance - parent");
}
// Constructor
public Parent() {
System.out.println("constructor - parent");
}
// Static init block
static {
System.out.println("static - parent");
}
}
class Grandparent {
// Static init block
static {
System.out.println("static - grandparent");
}
// Instance init block
{
System.out.println("instance - grandparent");
}
// Constructor
public Grandparent() {
System.out.println("constructor - grandparent");
}
}
class Child extends Parent {
// Constructor
public Child() {
System.out.println("constructor - child");
}
// Static init block
static {
System.out.println("static - child");
}
// Instance init block
{
System.out.println("instance - child");
}
}
得到了这个输出:
开始静态-祖父母
静态-父级
静态-子级
实例-祖父母
建造师-祖父母
实例-父级
构造函数-父级
实例-子对象
构造函数-子级
结束 显而易见的答案是,父母的积木比孩子的积木早,但这可能只是巧合,如果两个班级不在同一层次结构中,那就没什么帮助了 编辑: 我修改了示例代码,将其添加到LoadTest.java中:
class IAmAClassThatIsNeverUsed {
// Constructor
public IAmAClassThatIsNeverUsed() {
System.out.println("constructor - IAACTINU");
}
// Instance init block
{
System.out.println("instance - IAACTINU");
}
// Static init block
static {
System.out.println("static - IAACTINU");
}
}
正如类名所暗示的,我从未在任何地方引用过新类。新程序产生了与旧程序相同的输出。第一次访问类时,会运行该类的静态初始值设定项,以创建实例或访问静态方法或字段
因此,对于多个类,这完全取决于运行代码以使这些类加载。当第一次访问类时,会运行该类的静态初始值设定项,以创建实例或访问静态方法或字段
因此,对于多个类,这完全取决于运行的代码,以使这些类得到加载。请参阅的第12.4节和第12.5节,他们详细介绍了所有这些(12.4用于静态变量,12.5用于实例变量) 对于静态初始化(第12.4节): 类或接口类型T将在第一次出现以下任一情况之前立即初始化:
- T是一个类,并且创建了T的一个实例
- T是一个类,调用由T声明的静态方法
- 分配了一个由T声明的静态字段
- 使用T声明的静态字段,该字段不是常量变量(§4.12.4)
- T是一个顶级类(§7.6),执行嵌套在T(§8.1.3)中的assert语句(§14.10)
(和几个weasel word子句)参见的第12.4节和第12.5节,它们详细介绍了所有这些(12.4表示静态变量,12.5表示实例变量) 对于静态初始化(第12.4节): 类或接口类型T将在第一次出现以下任一情况之前立即初始化:
- T是一个类,并且创建了T的一个实例
- T是一个类,调用由T声明的静态方法
- 分配了一个由T声明的静态字段
- 使用T声明的静态字段,该字段不是常量变量(§4.12.4)
- T是一个顶级类(§7.6),执行嵌套在T(§8.1.3)中的assert语句(§14.10)
(还有几个狡猾的词语从句)基思和克里斯的答案都很好,我只是为我的具体问题补充了一些细节 静态init块按其类初始化的顺序运行。那么,这是什么顺序?根据JLS 12.4.1: 类或接口类型T将在第一次出现以下任一情况之前立即初始化:
- T是一个类,并且创建了T的一个实例
- T是一个类,调用由T声明的静态方法
- 分配了一个由T声明的静态字段
- 使用T声明的静态字段,该字段不是常量变量(§4.12.4)
- T是一个顶级类,执行嵌套在T中的assert语句(§14.10)李>
static{
i=1;
i=2;
}
class Super {
public static int i=10;
}
class Sub extends Super {
static {
system.out.println("Static block called");
}
}
class Test {
public static void main (String [] args) {
system.out.println(Sub.i);
}
}
class A {
public A() {
// 2
}
}
class B extends A{
static char x = 'x'; // 0
char y = 'y'; // 3
public B() {
// 4
}
public static void main(String[] args) {
new B(); // 1
}
}