一、代碼塊的作用
在java,對於數據域的初始化除了通過構造器,以及聲明時賦值,還有就是使用代碼塊進行初始化賦值。
二、代碼塊的分類
代碼塊分爲兩種,一種是被static關鍵字修飾的靜態代碼塊,一種是非靜態代碼塊。
class Person{
...
//非靜態代碼塊
{
System.out.println("這是非靜態代碼塊");
}
//靜態代碼塊
static {
System.out.println("這是靜態代碼塊");
}
...
}
在例子中,Person中直接以{ }
括起來的沒有任何修飾的就是非靜態代碼塊。而以static關鍵字修飾的static{ }
就是靜態代碼塊。
2.1 非靜態代碼塊
public class PersonTest {
public static void main(String[] args) {
Person p=new Person("張三");
System.out.println(p);
System.out.println("==============");
Person p2=new Person("李四");
System.out.println(p2);
}
}
class Person{
private String name;
private int age;
private static String gender="未知";
public Person(String name) {
this.name = name;
}
//非靜態代碼塊
{
age=10;
System.out.println("這是非靜態代碼塊1");
}
//非靜態代碼塊
{
System.out.println("這是非靜態代碼塊2");
//調用靜態屬性
gender="男";
//執行非靜態方法
walk();
//執行靜態方法
desc();
}
public void walk(){
System.out.println("這是非靜態方法");
}
public static void desc(){
System.out.println("這是靜態方法");
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
運行結果:
通過上面的例子發現非靜態代碼塊:
作用:
- 可以在創建對象時,對對象的屬性進行初始化
特點:
- 隨着對象的創建而執行
- 每創建一次對象時就執行一次非靜態代碼塊。
- 如果類中定義了多個代碼塊,就按照類聲明中定義的次序來
- 非靜態代碼塊內部可以有輸出語句
注意點:
- 非靜態代碼塊內部可以調用靜態屬性,非靜態屬性,靜態方法,非靜態方法。
2.2 靜態代碼塊
public class PersonTest {
public static void main(String[] args) {
String desc=Person.desc;
System.out.println("===============");
System.out.println(desc);
System.out.println("===============");
Person.desc();
}
}
class Person{
private String name;
private int age;
private static String gender="未知";
static String desc="這是個人";
public Person(String name) {
this.name = name;
}
static{
System.out.println("這是靜態代碼塊1");
//調用靜態方法
desc();
//調用非靜態方法
//walk();//Non-static method 'walk()'cannot be referenced from a static context
}
static{
System.out.println("這是靜態代碼塊2");
//給靜態屬性賦值
gender="男";
desc="這是個男人";
//給非靜態屬性賦值
//age=10;//Non-static field 'age'cannot be referenced from a static context
}
public void walk(){
System.out.println("這是非靜態方法");
}
public static void desc(){
System.out.println("這是靜態方法");
}
}
運行結果:
通過運行結果分析可以發現,在第一個分割符上方,是在通過類名.靜態屬性時(Person.desc
)打印出來的,此時類就會加載到內存中,所以會執行靜態代碼塊中的代碼。而在運行結果的第二個分割符下的結果,是執行Person.desc()
這個語句所打印出來的,因爲類此時已經加載過了,一個類只會加載一次,所以這時沒有再執行靜態代碼塊。
靜態代碼塊:
作用:
- 可以對靜態屬性進行初始化
特點:
- 隨着類的加載而加載,並且只執行一次
- 如果定義了多個靜態代碼塊,按照順序依次執行
- 靜態代碼塊在非靜態代碼塊之前執行
- 內部可以執行輸出語句
注意點:
- 靜態代碼塊只能調用靜態結構,不能調用非靜態結構
三、各種屬性賦值的先後順序
例如:
public class PersonTest {
public static void main(String[] args) {
Person p=new Person("張三");
}
}
class Person{
//非靜態代碼塊
{
System.out.println(this.id);
System.out.println("這是非靜態代碼塊1");
}
//靜態代碼塊1
static{
System.out.println(Person.desc);
desc="這是個人";
System.out.println("這是靜態代碼塊1");
}
private int id=getValue();
private String name;
private int age;
private static String gender;
private static String desc=getDesc();
//靜態代碼塊
static{
System.out.println("這是靜態代碼塊2");
}
public Person() {
System.out.println("這是無參構造");
}
public Person(String name) {
//調用無參構造
this();
System.out.println("這是有一個參數的構造");
this.name = name;
}
//非靜態代碼塊
{
System.out.println("這是非靜態代碼塊2");
}
private int getValue() {
System.out.println("這是非靜態屬性(實例域)顯式初始化");
return 1;
}
private static String getDesc(){
System.out.println("這是靜態屬性顯式初始化");
return "兩個眼睛,一張嘴,兩條腿";
}
}
運行結果:
通過運行結果和代碼的分析不難發現:
- 靜態屬性被初始化爲默認值
- 靜態屬性的顯式初始化和靜態代碼塊的執行順序,是按照類中定義的順序依次執行
- 非靜態屬性被初始化爲默認值
- 非靜態屬性的顯式初始化和非靜態代碼塊的執行順序,是按照在類中聲明的次序依次執行
- 構造器(如果構造器中第一行調用了其他構造器,則執行調用的構造器。如例子中一個參數的構造器,第一行通過this()調用了無參構造,則先執行無參構造,最後在執行一個參數的構造主體。)