在java中,代码块一般可分为普通代码块、构造代码块、静态代码块、同步代码块,这里我们主要将普通代码块和初始化代码块(构造+静态代码块):
一、普通代码块:
普通代码块仅出现于方法中,起到分隔不同功能代码的作用,其运行顺序依据代码块出现的先后。
public static void main(String[] args) {
System.out.println("hello world");
}
二、初始化代码块:
初始化代码块分为静态初始化代码块和非静态初始化代码块两类。
初始化代码块出现于类的主体中,在类的声明中,可以包含多个初始化块,当创建类的实例时,就会依次执行这些代码块。如果使用 static 修饰初始化块,就称为静态初始化块。
非静态初始化代码块多为构造方法,它隐性运行于创建类的对象时,顺序依据代码块的先后排列,且这些代码块间可以存在其他方法。也就是说在实例化这个对象时,会从类的头到尾检索一遍来运行初始化代码块。
以下代码将详细的说明静态代码块、初始化代码块和构造方法三者的执行顺序:
public class TestClass5 {
//系统在初始化类时,不仅会初始化该类中的静态初始化代码块,还回上溯到引用的包中的类的静态初始化代码块
static {
//只在类加载时(包括子类)执行一遍
//静态初始化块只能给静态变量赋值,不能初始化普通的成员变量
System.out.print("类加载:");
System.out.print("父类-静态方法 ");
}
public TestClass5(){
//每次创建(包括子类)对象都会执行
System.out.print("父类-无参构造方法 ");
}
public TestClass5(String str){
//带参的构造方法在创建对象时,不会自动执行
System.out.print("父类-有参构造方法 ");
}
{
//每次创建(包括子类)对象都会执行
System.out.print("父类-初始化代码块 ");
}
}
class ChildTestClass5 extends TestClass5{
static {
//只在类加载时(包括子类)执行一遍
//静态初始化块只能给静态变量赋值,不能初始化普通的成员变量
System.out.println("子类-静态方法 ");
}
public ChildTestClass5(){
//每次创建(包括子类)对象都会执行
System.out.print("子类-无参构造方法 ");
}
{
//每次创建(包括子类)对象都会执行
System.out.print("子类-初始化代码块 ");
}
public static void main(String[] args) {
//创建父类对象时不会去执行子类的构造方法
System.out.print("执行new TestClass5():");
new TestClass5();
System.out.println();
//创建父类对象时,如果带有参数,则不会去执行无参的构造方法,只执行参数个数及类型对应的构造方法
System.out.print("执行new TestClass5(\"10\"):");
new TestClass5("10");
System.out.println();
//创建子类对象时,会先执行父类的构造方法,然后才会去执行子类的构造方法
System.out.print("执行new ChildTestClass5():");
new ChildTestClass5();
System.out.println();
}
}
执行后打印结果为:
类加载:父类-静态方法 子类-静态方法
执行new TestClass5():父类-初始化代码块 父类-无参构造方法
执行new TestClass5("10"):父类-初始化代码块 父类-有参构造方法
执行new ChildTestClass5():父类-初始化代码块 父类-无参构造方法 子类-初始化代码块 子类-无参构造方法