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();
}
--》执行Tank的构造方法
--》 GameModel.getInstance().add(this);
--》 此时使用add()报错: 此时GameModel并未完成实例化操作、Tank的构造方法中拿不到一个GameModel实例、因此报空指针
解决方案:
将GameModel初始化逻辑移出构造方法、放置静态代码块、即先实例化成功--》new Tank() --> Tank此时可以拿到GameModel实例 --》 bug解决
GameModel.java
改动前:
public class GameModel {
private GameModel() {
new Tank();
}
}
改动后:
public class GameModel {
static {
new Tank();
}
private GameModel() {}
}