繼承和重寫,雖然我平時用的挺多的,但是依舊沒有徹底理解,看最後面的一個點:
- 看下面的代碼:
//父類
public class Token {
static int a;
static {
a = 10;
System.out.println("這是父類的靜態代碼塊" + a);
}
public Token() {
System.out.println("父類構造方法!");
}
}
//子類
public class TokenChrild extends Token {
static int a;
public TokenChrild() {
System.out.println("子類構造方法!");
}
static {
a = 10;
System.out.println("這是子類的靜態代碼塊" + a);
}
}
//測試
public class Main {
public static void main(String[] args) {
TokenChrild t1 = new TokenChrild();
System.out.println();
TokenChrild t2 = new TokenChrild();
}
}
-
上面代碼的輸出結果:
很好理解這個點,你實例化一個類時,JVM加載這個類的代碼的順序是:父類靜態域(靜態成員變量和靜態代碼塊) -> 子類靜態域 -> 父類構造方法 -> 子類構造方法,而靜態域的生命週期與類同在,且只加載一次。上面這個結果在意料之內。 -
再看下面這段代碼:
//父類
public class Token {
static int a;
static {
a = 10;
System.out.println("這是父類的靜態代碼塊" + a);
}
public Token() {
System.out.println("父類構造方法!");
execute();
}
public void execute() {
System.out.println("父類實例方法!");
}
}
//子類
public class TokenChrild extends Token {
static int a;
int b = 1;
static {
a = 10;
System.out.println("這是子類的靜態代碼塊" + a);
}
public TokenChrild() {
super();
System.out.println("子類構造方法!");
execute();
}
public void execute() {
System.out.println("子類實例方法: " + b);
}
}
//測試類
public class Main {
public static void main(String[] args) {
TokenChrild t1 = new TokenChrild();
}
}
- 上面代碼執行結果:
在父類的構造方法中調用了子類的實例方法,從而父類的構造方法運行時,子類的實例方法也運行了,但是這個時候,子類的構造方法還沒有運行,也就是子類的屬性還沒有加載出來,所以這時候 i 的值爲0,後面子類構造方法中調用子類的實例方法,這個時候,子類的屬性都已經加載好了,所以 i 的值爲1.
我現在就姑且這麼理解,水平有限,闡述不出其原理,後面知道了再補充!