我们知道一个类需要在一个new操作符下完成类的初始化。
那么,这里面的各个部分到底是怎么样初始化的呢?
一、默认构造器先于任何实例的调用
class Car{
private int speed;
public Car(){speed=12;}
public void tellMeSpeed(){
System.out.println("my speed is "+speed);
}
}
public class practice {
public static void main(String[] args){
Car c=new Car();
c.tellMeSpeed();
}
}
观察上边的代码。实际上的输出是:my speed is 12
因为默认构造器在这个类已经可以使用之前就已经完成调用了。
二、块部分先于构造器
class Car{
private int speed;
public Car(){
speed=12;
System.out.println("current speed:"+speed);
}
{
speed=5;
System.out.println("block init.");
}
public void tellMeSpeed(){
System.out.println("my speed is "+speed);
}
}
public class practice {
public static void main(String[] args){
Car c=new Car();
c.tellMeSpeed();
}
}
观察上边的代码,可以看到有一个“块”在默认构造器的下面。
为了得到初始化顺序,运行这段代码:
block init.
current speed:12
my speed is 12
可以看到,块总是在默认构造器之前调用。而且为了解除由于编译器编译时的顺序问题,我把块放到了默认构造器的后面,
但是依然是块初始化最先被调用。
三、静态初始化块在非静态初始化块之前
class Car{
private int speed;
private static int id;
public Car(){
speed=12;
System.out.println("current speed:"+speed);
}
{
speed=5;
System.out.println("block init.");
}
static {
id=111;
System.out.println("static init block");
}
public void tellMeSpeed(){
System.out.println("my speed is "+speed);
}
}
public class practice {
public static void main(String[] args){
Car c=new Car();
c.tellMeSpeed();
}
}
考虑上述代码,为了观察顺序,运行:
static init block
block init.
current speed:12
my speed is 12
可以看到static初始化块是最先被调用的,但遗憾的是这个块里面只可以初始化静态成员。
为了说明 二,三 部分的区别,可以做一个这样的假设。
首先呢,类加载器(classloader)把我们的.java文件编译后生成了一个个的.class文件。
当我们不对类进行实例化时,它就认为class{...}里的代码是一个构造模板,在用到时再加载。
但是存在static变量时,它就认为这个变量是它的属性,在生成class文件时就初始化了。
所以他们分别是在使用时、生成时创建,所以一定会有创建的顺序static先于其他的了~