方法很多, 直接上代码:
public class Zoo {
public static void main(String[] args) {
// 调用构造函数
Rabbit r1 = new Rabbit();
// 相当于一个临时的构造函数
Rabbit r2 = new Rabbit() {{
weight = 10;
maxHealth = 20;
health = 10;
speed = 2;
year = 10;
}};
}
}
类的static初始化和实例初始化:
class Rabbit extends Animal{
static final double basicSpeed = 3.0;
static int RabbitNum;
// 1. 类第一次被使用时执行
static {
System.out.println("Rabbit static initializaion.");
RabbitNum = 0;
}
// 3. 每个兔子都有field a,在Rabbit的构造函数总调用
int a;
{
System.out.print("Miao~");
}
// 2. Rabbit先调用super()
Rabbit(){
super(5, 10, 10, 0, basicSpeed);
// 4. 打印语句
System.out.println("Rabbit!");
}
}
来个复杂一点的例子,假设上面的Rabbit类加了一个 String name = "", 我们发现一个Rabbit对象的构造过程分为下面的过程:
- static { ... } // 静态初始化,当类被加载进入jvm时执行,仅执行一次
- 进入Rabbit的构造方法
- 递归调用super()
- 属于其他类的field 初始化, 如 String name = “”
- 执行实例初始化语句块, 如 int a; { .... }
- 构造方法中剩下的语句
我们再对上面的例子进行修改, 给Rabbit类添加一个 { ...}语句块,并将它与上文的 int a ; { .. }, String name = "" , 打乱顺序重新安排在Rabbit的各处,
Debug发现,它们的执行顺序是从上到下,也就是先出现的语句先被执行。
综上, 我们做出总结:一个类对象的构造过程调用的函数和执行的语句(块)的顺讯如下:
- 父类的静态初始化块 (先进入子类的构造函数, 递归调用super)
- 子类的静态初始化块
- 父类的初始化块 (由上到下执行)
- 父类的构造函数(完成)
- 子类的初始化块
- 子类的构造函数(完成)