2016-08-17 48 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构造函数体