java的繼承關係中,構造方法呼叫問題
原文: http://www.cnblogs.com/lanxuezaipiao/p/3371224.html
考慮下下面程式碼輸出結果
public class test3 {
public static void main(String[] args) {
new Child("mike");
}
}
class People {
String name;
public People() {
System.out.print(1);
}
public People(String name) {
System.out.print(2);
this.name = name;
}
}
class Child extends People {
People father;
public Child(String name) {
System.out.print(3);
this.name = name;
father = new People(name + ":F");
}
public Child() {
System.out.print(4);
}
}
答案在最後
下面是一個延伸題
public class Dervied extends Base {
private String name = "dervied";
public Dervied() {
tellName();
printName();
}
public void tellName() {
System.out.println("Dervied tell name: " + name);
}
public void printName() {
System.out.println("Dervied print name: " + name);
}
public static void main(String[] args){
new Dervied();
}
}
class Base {
private String name = "base";
public Base() {
tellName();
printName();
}
public void tellName() {
System.out.println("Base tell name: " + name);
}
public void printName() {
System.out.println("Base print name: " + name);
}
}
第一題答案: 132
解析:考察的又是父類與子類的建構函式呼叫次序。在Java中,子類的構造過程中必須呼叫其父類的建構函式,是因為有繼承關係存在時,子類要把父類的內容繼承下來。但如果父類有多個建構函式時,該如何選擇呼叫呢?
第一個規則:子類的構造過程中,必須呼叫其父類的構造方法。一個類,如果我們不寫構造方法,那麼編譯器會幫我們加上一個預設的構造方法(就是沒有引數的構造方法),但是如果你自己寫了構造方法,那麼編譯器就不會給你添加了,所以有時候當你new一個子類物件的時候,肯定呼叫了子類的構造方法,但是如果在子類構造方法中我們並沒有顯示的呼叫基類的構造方法,如:super(); 這樣就會呼叫父類沒有引數的構造方法。
第二個規則:如果子類的構造方法中既沒有顯示的呼叫基類構造方法,而基類中又沒有無參的構造方法,則編譯出錯,所以,通常我們需要顯示的:super(引數列表),來呼叫父類有引數的建構函式,此時無參的建構函式就不會被呼叫。
總之,一句話:子類沒有顯示呼叫父類建構函式,不管子類建構函式是否帶引數都預設呼叫父類無參的建構函式,若父類沒有則編譯出錯。
第二題:
Dervied tell name: null
Dervied print name: null
Dervied tell name: dervied
Dervied print name: dervied
解析:
在第一題的基礎上,
子類的構造過程中必須呼叫其父類的建構函式,因為有繼承關係存在時,先父後子;
其次:子類可以訪問父類的非私有成員變數和非私有方法,但是父類不可以訪問子類的一切