NullPointerException при добавлении узловых объектов в ArrayList
Я получаю 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 ответа
Вы не создаете свой 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
,
Это:
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);
Вы пытаетесь добавить узлы в список до того, как они были созданы.
Хороший ответ на ваш вопрос уже дан.
Глядя на ваш код, у меня есть несколько предложенных модификаций.
Вы выполняете всю работу в (конструкторе) вашего тестового класса. Лучше по возможности делегировать это классу 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', считается плохой практикой, поэтому я добавил метод add для добавления узлов. Таким образом, класс сохраняет контроль над тем, что происходит с его данными, что является важным принципом проектирования ОО.
Метод 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)
Отказ от ответственности: мой код создан вручную, не скомпилирован и не проверен