Pop*_*ops 91 java static-initializer
假设一个项目包含几个类,每个类都有一个静态初始化块.这些块以什么顺序运行?我知道在一个类中,这些块按照它们在代码中出现的顺序运行.我已经读过它在各个类中都是一样的,但是我写的一些示例代码不同意这一点.我用过这段代码:
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");
}
}
Run Code Online (Sandbox Code Playgroud)
得到这个输出:
START
static - grandparent
static - parent
static - child
instance - grandparent
constructor - grandparent
instance - parent
constructor - parent
instance - child
constructor - child
END
显而易见的答案是父母的街区在他们的孩子面前运行,但这可能只是巧合而且如果两个班级不在同一层级中则无济于事.
编辑:
我通过将此示例代码附加到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");
}
}
Run Code Online (Sandbox Code Playgroud)
正如类名所暗示的那样,我从未在任何地方引用过新类.新程序产生的输出与旧程序相同.
Chr*_*ung 60
首次访问类时,将运行类的静态初始化程序,以创建实例或访问静态方法或字段.
因此,对于多个类,这完全取决于运行以导致这些类被加载的代码.
Pop*_*ops 32
Keith和Chris的答案都很棒,我只是为我的具体问题添加更多细节.
静态init块按其类初始化的顺序运行. 那么,那是什么顺序?根据JLS 12.4.1:
类或接口类型T将在第一次出现以下任何一个之前立即初始化:
- T是一个类,并且创建了T的实例.
- T是一个类,并且调用由T声明的静态方法.
- 分配由T声明的静态字段.
- 使用由T声明的静态字段,该字段不是常量变量(第4.12.4节).
- T是顶级类,并且执行在词典内嵌套在T中的断言语句(第14.10节).
在类Class和包java.lang.reflect中调用某些反射方法也会导致类或接口初始化.在任何其他情况下,不会初始化类或接口.
为了说明,这里是对示例中发生的事情的演练:
| 归档时间: |
|
| 查看次数: |
53831 次 |
| 最近记录: |