第一 普通的代码块
就是我们说说的代码块,它无论定义在构造方法的哪个地方(或前或后),总是在构造方法之前运行,每定义一个实例对象,就会运行一次。如果父类中也有代码块则运行顺序如下:
1 父类普通代码块
2 父类构造方法
3 子类普通代码块
4 子类构造方法
例如:
public class CodeBlockTest {
public static void main(String[] args) throws Exception{
new Child();
System.out.println("刚刚创建了一个实例");
new Child();
System.out.println("刚刚创建了一个实例");
}
}
class Parent{
public Parent() {
System.out.println("父类构造方法");
}
{
System.out.println("父类普通代码块1");
}
{
System.out.println("父类普通代码块2");
}
}
class Child extends Parent{
public Child() {
System.out.println("子类构造方法");
}
{
System.out.println("子类普通代码块");
}
}
第二 静态代码块
静态代码块只在类加载的时候才会运行一次,之后使用该类时不会在运行。因为是先加载类才能创建实例的,所以当第一次使用类创建实例时,会先运行静态代码块。如果该类的父类中有静态代码块,则会先运行父类的静态代码块。如果之前已经加载了子类,则再加载父类时不再单独运行父类中的静态代码块。记住,静态代码块只运行一次。如下:
public class CodeBlockTest {
public static void main(String[] args) throws Exception{
System.out.println("*****加载子类*****");
Class.forName("test2.Child");
System.out.println("*****加载子类*****");
Class.forName("test2.Child");
System.out.println("*****加载父类*****");
Class.forName("test2.Parent");
System.out.println("*****加载父类*****");
Class.forName("test2.Parent");
}
}
class Parent{
private int a;
private static int b;
static{
// 这是错误的,静态代码块中不能出现非静态的属性和方法
// a = 1;
//这是错误的,静态代码块中不能出现this和super等关键字
// this.b = 10;
//这是正确的
b = 10;
System.out.println("父类静态代码块1");
}
public Parent() {
System.out.println("父类构造方法");
}
static{
System.out.println("父类静态代码块2");
}
}
class Child extends Parent{
static{
System.out.println("子类静态代码块");
}
public Child() {
System.out.println("子类构造方法");
}
}
运行结果是:
*****加载子类*****
父类静态代码块1
父类静态代码块2
子类静态代码块
*****加载子类*****
*****加载父类*****
*****加载父类*****
注意:静态代码块中不能出现非静态的属性和方法,也不能出现this和super等关键字。