-2

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

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; 
    } 
} 
+0

在什么行请注意null异常错误?! – shareef

回答

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循环中失败,因为它试图在null对象上调用.label循环。如上所述修正订单将更正此问题,因为您的List中的所有对象现在都将是Nodes

+0

解决方案是正确的,但解释并不完全正确。您可以完美地将空值添加到列表中。当OP试图访问它时,NPE发生在for循环中。 – BalusC

+0

正确,谢谢,我调整了我的答案,以更好地反映这一点。 – wattostudios

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); 

您正在尝试已经创建它们的节点添加到列表中。

+0

我认为这也可能是解决方案 – shareef

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(); 
    } 
} 

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

toString方法构建一个节点的字符串表示形式。其追加的节点名称,然后,如果有孩子,追加由括号包围的逗号分隔列表中的每个子节点的字符串表示,所以这应该打印出类似这样的:例如

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) 

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