2016-08-17 43 views
3

我有以下代碼:類A的構造函數調用由類B實現的抽象方法,該類從B類返回變量。此變量在A調用抽象方法時將爲null即使我在聲明中實例化了它。有什麼辦法可以這樣實例化嗎?在子類中未實例化的類變量Java

public abstract class A { 
public A() { 
    isStringNull(); 
} 

protected abstract String getMyString(); 

private void isStringNull() { 
    if (getMyString() == null) { 
     System.out.println("String is null :("); 
    } else { 
     System.out.println(getMyString()); 
    } 
} 
} 

public class B extends A { 
private String amINull = "Of course not"; 

@Override 
protected String getMyString() { 
    return amINull; 
} 
} 

public static void main(String[] args) { 
new B(); 
} 

有人可以請解釋爲什麼字符串將爲空嗎?

+0

因爲構造函數方法正在執行amINull賦值之前 – ControlAltDel

+1

這就是爲什麼你不應該從構造函數中調用可重寫的方法。 – bradimus

回答

0

發生這種情況是因爲您首先檢查的是字符串null,然後您正在分配其值。當您擴展某個類時,該類代碼將首先執行!

你的編譯器做這種方式: new B() - >isStringNull() - >private String amINull = "Of course not";

檢查這個修改後的代碼,看看會發生什麼,並期待在執行步驟

public abstract class A { 
public A() { 
    System.out.println("Class A() called"); 
    isStringNull(); 
} 

protected abstract String getMyString(); 

private void isStringNull() { 
    if (getMyString() == null) { 
     System.out.println("String is null :("); 
    } else { 
     System.out.println(getMyString()); 
    } 
} 
} 

public class B extends A { 
System.out.println("Class B() called"); 
private String amINull = "Of course not"; 

@Override 
protected String getMyString() { 
    return amINull; 
} 
} 

public static void main(String[] args) { 
new B(); 
} 
1

有一個詳細的解釋初始化的順序如下:

Java order of Initialization and Instantiation

基本上,如果調用超類的構造函數(顯式或隱式地通過繼承並具有無參數的構造函數),則其所有初始化都會在返回到子類之前完成。因此,在這種情況下,順序是:

  • 執行類A的變量初始化
  • 執行類的構造體
  • 返回到B類構造函數
  • 執行B級變量初始化
  • 執行類B構造函數體