我尝试运行此代码时收到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;
}
}
答案 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)
免责声明:我的代码是手工制作,未经编译和未经测试的