首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Java to List NullPointerException

Java to List NullPointerException
EN

Stack Overflow用户
提问于 2014-07-03 18:18:58
回答 1查看 1K关注 0票数 1

我在StackOverflow上读过许多关于这类问题的其他答案,然而,我的答案与我所读过的任何答案都不一样。

我在向ArrayList添加对象时遇到了麻烦。我一直在获取NullPointerException,正如您所看到的,我的列表是初始化的,并且我为它提供了适当类型的对象。第一次失败了。在尝试添加到ArrayList之前,您可以看到我的println,而println正确地显示了所有信息,没有什么是空的,这些都是对象的属性。它尝试将该对象添加到ArrayList中,并抛出一个NullPointerException。

请帮我整理一下,这样我就能从这个问题上走下去了。谢谢你们!

代码语言:javascript
复制
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非常好。

代码语言:javascript
复制
: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

下面是由基类抽象类实现的接口

代码语言:javascript
复制
public interface ParserInterface {
    ArrayList<Object> units = new ArrayList<Object>();
    JSONObject json = null;

    void initParse();
    void process(JSONObject o);

    java.util.ArrayList getUnits();
}

下面是BaseParser抽象类

代码语言:javascript
复制
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;
    }

}

运行这段代码的代码是:

代码语言:javascript
复制
JSONObject fleets = report.getFleets();
FleetParser fleetParser = new FleetParser(fleets);
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2014-07-03 19:36:21

初始化字段的顺序有问题。您需要知道初始化块(包括字段的初始化)被调用。

  • 超类的构造函数之后(在显式或隐式super(...)调用之后,它总是处于构造函数的开头)
  • 构造函数之前的实际代码(在super(...)之后)。

换句话说,这个代码

代码语言:javascript
复制
class SomeClass extends BaseClass{
    String field = "some value";

    SomeClass(String data){ //constructor
        super(data);

        System.out.println(field);
    }
}

将被汇编成

代码语言:javascript
复制
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

这段代码可能会更好地显示出来:

代码语言:javascript
复制
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

如果不在派生类中重新声明fieldmethod将使用基类中的field。所以为了

代码语言:javascript
复制
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

代码语言:javascript
复制
protected ArrayList units

看看您的代码:在您的BaseParser构造函数中,您正在调用调用抽象方法processinitParse(),该方法使用来自FleetParser的代码(基于您的堆栈跟踪),该代码如下所示

代码语言:javascript
复制
@Override
public void process(JSONObject o)
{
    //... some code
    units.add(fleet);
}

units是在FleetParser中重新声明的列表,并且由于控制流当前在super(..)中,所以units无法初始化。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/24560753

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档