详解Java中代码块的使用
类的成员之一——代码块
-
代码块的作用:用来初始化类、对象
在类中,代码块主要使用一对” {} “表示class test{ private int age; // 以下为代码块 { age = 18; } }
-
代码块如果有修饰的话,只能使用static。
-
分类:静态代码块 vs 非静态代码块
静态代码块
内部可以有输出语句
随着类的加载而执行,且只执行一次
作用:初始化类的信息
如果一个类中定义了多个静态代码块,谁先定义谁先执行
静态代码块只能调用静态的属性、方法,不能调用非静态的public class BlockTest { @Test public void test1(){ int age = TestBlock.age; // 此时还没有创建对象 } } class TestBlock{ private String name; static int age = 19; static { System.out.println("这是静态代码块"); } }
上述代码中,定义了一个静态代码块,并且其随着类的加载而自动执行了代码块中的内容,输出了一条语句。
非静态代码
内部可以有输出语句
随着对象的创建而执行
每创建一个对象,就执行一次非静态代码块
作用:可以在创建对象时,对对象的属性进行初始化
非静态代码块可以调用静态的属性和方法public class BlockTest { @Test public void test1(){ TestBlock t1 = new TestBlock(); TestBlock t2 = new TestBlock(); } } class TestBlock{ private String name; static int age = 19; private double height; { System.out.println("这是非静态代码块"); name = "Tom"; height = 180.0; } }
在上面的代码中,定义了一个非静态代码块,并创建了两个对象,由于非静态代码块是随着对象的创建而执行,因此,非静态代码块要被执行两次,共输出两条语句
属性赋值位置及先后顺序
由于代码块中也可以对属性进行赋值,加上之前所讲的,对属性的赋值可以有以下几种方式:
- ①默认初始化
- ②显式初始化
- ③构造器中初始化
- ④有了对象以后,可以通过“对象.属性”或”对象.方法”的方式,进行赋值
- ⑤在代码块中赋值
其先后顺序为:①——② / ⑤ ——③——④
代码块在子父类中执行的先后顺序
直接用代码解释:
public class BlockTest {
public static void main(String[] args) {
new Leaf();
}
}
class Root{
static {
System.out.println("Root的静态代码块");
}
{
System.out.println("Root的非静态代码块");
}
public Root() {
System.out.println("Root的无参构造器");
}
}
class Mid extends Root{
static {
System.out.println("Mid的静态代码块");
}
{
System.out.println("Mid的非静态代码块");
}
public Mid() {
System.out.println("Mid的无参构造器");
}
public Mid(String str){
System.out.println("Mid的有参构造器");
}
}
class Leaf extends Mid{
static {
System.out.println("Leaf的静态代码块");
}
{
System.out.println("Leaf的非静态代码块");
}
public Leaf() {
super("hello");
System.out.println("Leaf的无参构造器");
}
}
代码输出结果:
解释:
程序的执行是从main函数开始的,在main函数中,执行了” new Leaf(); “这条语句,通过new,程序会调用Leaf类的构造器。
——>前文已经提到,代码块的执行要早于构造器,静态代码块随着类的加载而执行,非静态代码块随着对象的创建而执行。因此,在调用Leaf类的构造器之前,程序会先执行Leaf类的静态代码块。由于Leaf类继承于Mid类,而Mid类继承于Root类,所以程序前三条输出语句为” Root的静态代码块 “、” Mid的静态代码块 “、” Leaf的静态代码块 “。
——>在Leaf类的构造器中,由于Leaf继承于Mid类,因此会先调用Mid类的构造器。
——>同理,Mid类继承于Root类,所以会先调用Root类的构造器。而非静态代码块的执行要早于构造器,所以程序第四条输出语句为” Root的非静态代码块 “。
——>紧接着,程序就会调用Root的构造器,所以第五条输出” Root的无参构造器 “。Root类的相关操作执行完后,就会回到Mid类。
——>同理,Mid非静态代码块的执行要早于构造器,所以第六条输出” Mid的非静态代码块 “。由于,在Leaf类的构造器中,调用的是Mid类的有参构造器,所以第七条输出” Mid的有参构造器 “。
——>最后,回到Leaf类本身,程序先调用Leaf类的非静态代码块,输出” Leaf的非静态代码块 “,然后调用Leaf类的构造器,输出” Leaf的无参构造器 “。