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

免責聲明:我的代碼是手工製作的,未編譯的和未經考驗的