Main.java
package test;
public class Main {
public static void main(String[] args) {
GameModel.getInstance();
System.out.println(GameModel.getInstance().objects);
}
}
GameModel.java
package test;
import java.util.ArrayList;
import java.util.List;
public class GameModel {
List<Tank> objects = new ArrayList<Tank>();
private static GameModel INSTANCE = new GameModel();
private GameModel() {
new Tank();
}
public static GameModel getInstance() {
return INSTANCE;
}
public void add(Tank t) {
this.objects.add(t);
}
}
Tank.java
package test;
import java.awt.*;
public class Tank {
public Tank() {
GameModel.getInstance().add(this);
}
}
運行Main.main() 報錯:
/Library/Java/JavaVirtualMachines/jdk-12.jdk/Contents/Home/bin/java -javaagent:/Applications/IntelliJ IDEA CE.app/Contents/lib/idea_rt.jar=52752:/Applications/IntelliJ IDEA CE.app/Contents/bin -Dfile.encoding=UTF-8 -classpath /Library/Java/www/DesignPatterns/game_tank/out/production/game_tank test.Main
Exception in thread "main" java.lang.ExceptionInInitializerError
at test.Main.main(Main.java:6)
Caused by: java.lang.NullPointerException
at test.Tank.<init>(Tank.java:8)
at test.GameModel.init(GameModel.java:20)
at test.GameModel.<init>(GameModel.java:16)
at test.GameModel.<clinit>(GameModel.java:9)
... 1 more
Process finished with exit code 1
報錯分析:
GameModel.getInstance()
--》 return INSTANCE;
--》 private static GameModel INSTANCE = new GameModel();
--》
private GameModel() {
new Tank();
}
--》執(zhí)行Tank的構(gòu)造方法
--》 GameModel.getInstance().add(this);
--》 此時使用add()報錯: 此時GameModel并未完成實例化操作、Tank的構(gòu)造方法中拿不到一個GameModel實例、因此報空指針
解決方案:
將GameModel初始化邏輯移出構(gòu)造方法、放置靜態(tài)代碼塊、即先實例化成功--》new Tank() --> Tank此時可以拿到GameModel實例 --》 bug解決
GameModel.java
改動前:
public class GameModel {
private GameModel() {
new Tank();
}
}
改動后:
public class GameModel {
static {
new Tank();
}
private GameModel() {}
}