我在StackOverflow上读过许多关于这类问题的其他答案,然而,我的答案与我所读过的任何答案都不一样。
我在向ArrayList添加对象时遇到了麻烦。我一直在获取NullPointerException,正如您所看到的,我的列表是初始化的,并且我为它提供了适当类型的对象。第一次失败了。在尝试添加到ArrayList之前,您可以看到我的println,而println正确地显示了所有信息,没有什么是空的,这些都是对象的属性。它尝试将该对象添加到ArrayList中,并抛出一个NullPointerException。
请帮我整理一下,这样我就能从这个问题上走下去了。谢谢你们!
protected ArrayList units = new ArrayList<Fleet>();
public FleetParser(JSONObject json)
{
super(json);
}
@Override
public void process(JSONObject o)
{
Fleet fleet = new Fleet();
fleet.inflateFromJSON(o);
if(fleet.getUid() != null) {
System.out.println(fleet.getUid() + " " + fleet.getPuid() + " " + fleet.getShips() + " " + fleet.getName());
units.add(fleet);
}
}编辑:这是Intellij中控制台中的Stacktrace。您会注意到它执行第一个println非常好。
:compileJavaNote: /home/cody/IdeaProjects/NeptuneCommand/src/main/java/com/codyhalovich/neptunecommand/Parsers/FleetParser.java uses unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.
:processResources UP-TO-DATE
:classes
:runSimple
Exception in thread "main" java.lang.NullPointerException
78 17 45 New Bellatrix I
at com.codyhalovich.neptunecommand.Parsers.FleetParser.process(FleetParser.java:25)
at com.codyhalovich.neptunecommand.Parsers.BaseParser.initParse(BaseParser.java:24)
at com.codyhalovich.neptunecommand.Parsers.BaseParser.<init>(BaseParser.java:16)
at com.codyhalovich.neptunecommand.Parsers.FleetParser.<init>(FleetParser.java:14)
at com.codyhalovich.neptunecommand.Parsers.ReportParser.<init>(ReportParser.java:26)
at com.codyhalovich.neptunecommand.NeptuneCommand.main(NeptuneCommand.java:25)
:runSimple FAILED下面是由基类抽象类实现的接口
public interface ParserInterface {
ArrayList<Object> units = new ArrayList<Object>();
JSONObject json = null;
void initParse();
void process(JSONObject o);
java.util.ArrayList getUnits();
}下面是BaseParser抽象类
public abstract class BaseParser implements ParserInterface {
private JSONObject json;
protected ArrayList units = new ArrayList<Object>();
public BaseParser(JSONObject json)
{
this.json = json;
this.initParse();
}
public void initParse()
{
for(Object key: json.keySet())
{
if(key != null) {
this.process((JSONObject) json.get(key));
}
}
}
public abstract void process(JSONObject json);
public ArrayList getUnits()
{
return this.units;
}
}运行这段代码的代码是:
JSONObject fleets = report.getFleets();
FleetParser fleetParser = new FleetParser(fleets);发布于 2014-07-03 19:36:21
初始化字段的顺序有问题。您需要知道初始化块(包括字段的初始化)被调用。
super(...)调用之后,它总是处于构造函数的开头)super(...)之后)。换句话说,这个代码
class SomeClass extends BaseClass{
String field = "some value";
SomeClass(String data){ //constructor
super(data);
System.out.println(field);
}
}将被汇编成
class SomeClass extends BaseClass{
String field = null; // initialization is moved --+
// |
SomeClass(String data){ // |
super(data); // |
field = "some value"; // here <----------------+
System.out.println(field);
}
}因此,在调用super(data)时,field尚未初始化,因此其值为null。
这段代码可能会更好地显示出来:
abstract class Base {
protected String field = "foo";
public abstract void method();
public Base() {
method();
}
}
class Derived extends Base {
protected String field = "bar";
public Derived() {
super();
}
public void method() {
System.out.println("value of field is "+field);
}
}
class TestX{
public static void main(String[] args) {
new Derived();
}
}输出:value of field is null
之所以发生这种情况,是因为当method引用来自TestX类的field时,正如前面提到的,它的值将在super()之后设置,所以现在是null。
如果不在派生类中重新声明field,method将使用基类中的field。所以为了
class Derived extends Base {
// protected String field = "bar";
public Derived() {
super();
}
public void method() {
System.out.println("value of field is "+field);
}
}结果将是value of field is foo,因为field的初始化是在从构造函数调用实际代码之前完成的(正如前面提到的,字段初始化发生在super类的构造函数之后,但在当前构造函数的实际代码之前)。
您的情况类似于这个示例,但是您没有使用String field
protected ArrayList units看看您的代码:在您的BaseParser构造函数中,您正在调用调用抽象方法process的initParse(),该方法使用来自FleetParser的代码(基于您的堆栈跟踪),该代码如下所示
@Override
public void process(JSONObject o)
{
//... some code
units.add(fleet);
}units是在FleetParser中重新声明的列表,并且由于控制流当前在super(..)中,所以units无法初始化。
https://stackoverflow.com/questions/24560753
复制相似问题