将节点对象添加到ArrayList时出现NullPointerException

时间:2012-05-27 05:36:24

标签: java arraylist nullpointerexception variable-initialization

我尝试运行此代码时收到NullPointerException。我已将Nodes 2,3和4作为子节点分配给Node1。我试图创建一个方法,它将遍历Node1中的所有子节点并返回列表。我不确定我做错了什么。

public class TestingArrays2 {

    List<Node> myList1;
    List<Node> myList2;
    List<Node> myList3;
    List<Node> myList4;

    private Node Node1;
    private Node Node2;
    private Node Node3;
    private Node Node4;

    public TestingArrays2() {
        myList1 = new ArrayList<Node>();
        myList2 = new ArrayList<Node>();
        myList3 = new ArrayList<Node>();
        myList4 = new ArrayList<Node>();

        myList1.add(Node2);
        myList1.add(Node3);
        myList1.add(Node4);

        Node1 = new Node("One", myList1);
        Node2 = new Node("Two", myList2);
        Node3 = new Node("Three", myList3);
        Node4 = new Node("Four", myList4);

        List<Node> allNodesArray = nodeArray(Node1);

        for (int i = 0; i < allNodesArray.size(); i++){
            System.out.println(allNodesArray.get(i).label);
        }
    }

    public static void main(String arg[]) {
        TestingArrays2 testArray = new TestingArrays2();
    }

    public List<Node> nodeArray(Node n){
        List<Node> tempList = new ArrayList<Node>();

        for (int i = 0; i < n.children.size(); i++){
            tempList.add(n.children.get(i));
        }

    return tempList;
    }
}

3 个答案:

答案 0 :(得分:2)

您没有创建Nodes。见这些行......

private Node Node1;
private Node Node2;
private Node Node3;
private Node Node4;

这些只是声明一个变量,因为它能够包含Node类型的对象。但是,它们最初以null值开头 - 即它们是空的。

然后你正在调用这些行...

myList1.add(Node2);
myList1.add(Node3);
myList1.add(Node4);

哪会将null值插入List,因为您正在尝试添加尚未创建的对象。

因此,您需要更改代码以便这些行......

Node1 = new Node("One", myList1);
Node2 = new Node("Two", myList2);
Node3 = new Node("Three", myList3);
Node4 = new Node("Four", myList4);
在您尝试myList1.add()他们到列表之前,

出现。这将首先创建Node个对象,然后可以将其添加到List

正如@BalusC在评论中提到的那样,代码中的for循环失败了,因为它试图在.label对象上调用null。如上所述更正订单将更正此问题,因为List中的所有对象现在都是Nodes

答案 1 :(得分:1)

此:

myList1.add(Node2);
myList1.add(Node3);
myList1.add(Node4);

Node1 = new Node("One", myList1);
Node2 = new Node("Two", myList2);
Node3 = new Node("Three", myList3);
Node4 = new Node("Four", myList4);

您尝试在创建节点之前将其添加到列表中。

答案 2 :(得分:0)

已经给出了一个很好的答案。

查看您的代码我有几个建议的修改。

您正在测试类的(构造函数)中完成所有工作。在可能的情况下将它委托给Node类是更好的设计。也尽量不要在构造函数中“工作”,只需初始化。

同时查看我应用的代码约定,例如使用名词的名词和带小写字母的起始变量名。

public class ArrayTest2 {

    public static void main(String arg[]) {

        Node node1 = new Node("One");

        node1.add(new Node("Two"));
        node1.add(new Node("Three"));
        node1.add(new Node("Four"));

        // this calls the toString method of node1
        System.out.println(node1);
    }

}

public class Node {

    private final String name;
    private final List<Node> children;

    public Node(String name) {
        this.name = name;
        this.children = new ArrayList<Node>();
    }

    public String getName() {
        return name;
    }

    public void add(Node children) {
        children.add(child);
    }

    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        sb.append(name);
        if(children.size() > 0) {
            sb.append("(");
            String separator = "";
            for (Node child : children){
                sb.append(separator).append(String.valueOf(child));
                separator = ",";
            }
            sb.append(")");
        }
        return sb.toString();
    }
}

请注意,children字段是私有的,并且没有getter。提供对“儿童”等内部数据结构的直接访问被认为是不好的做法,因此我提供了一种添加节点的“添加”方法。通过这种方式,类可以控制其数据发生的变化,这是一个重要的面向对象设计原则。

toString方法构建Node的字符串表示。它附加节点名称,然后,如果有子节点,将每个子节点的字符串表示附加到括号括起来的逗号分隔列表中,所以这应该打印如下:

One(Two,Three,Four)

更复杂的结构,例如:

Node node1 = new Node("One");
Node node2 = new Node("Two");
Node node3 = new Node("Three");
Node node4 = new Node("Four");
Node node5 = new Node("Five");
Node node6 = new Node("Six");
node1.add(node2);
node1.add(node3);
node2.add(node4);
node4.add(node5);
node4.add(node6);

应该给:

One(Two(Four(Five,Six)),Three)

免责声明:我的代码是手工制作,未经编译和未经测试的