#java #arraylist #constructor #nullpointerexception
#java #arraylist #конструктор #исключение nullpointerexception
Вопрос:
создатель объекта
ObjectCreator.java
import java.util.ArrayList;
import java.util.List;
class ObjectCreator {
List<CreatedObject> objects;
static ObjectCreator objectCreator;
public ObjectCreator() {
objects = new ArrayList<CreatedObject>();
CreatedObject createdObject = new CreatedObject(9); //second object
}
public static void main(String[]args) {
objectCreator = new ObjectCreator(); //first object
}
}
созданный объект
CreatedObject.java
class CreatedObject {
public CreatedObject() {
ObjectCreator.objectCreator.objects.add(this); //adds itself
//nullpointer here
}
}
Выше приведен пример моей проблемы. Я получаю исключение nullpointer в строке ObjectCreator.objectCreator.objects.add(this);
, потому что objectCreator (в классе ObjectCreator) имеет значение null. Я полагаю, это связано с тем, что конструктор для objectCreator (в классе ObjectCreator) не завершен, и поэтому объекту не было присвоено значение.
В моей реальной программе у меня есть класс, отвечающий за создание объектов на основе алгоритма. Этот алгоритм получает информацию через параметры конструктора класса. В конце конструктора я хочу иметь несколько (нестатических) списков массивов, каждый из которых заполнен ссылками на все различные объекты каждого типа, которые были созданы. Я хочу, чтобы эти объекты в своих конструкторах добавляли себя в ArrayList. т. е. object1 creates object2 creates object3 adds itself to ArrayList stored in object1
Этот подход, очевидно, оказался бесплодным.
Вопрос: что я должен сделать, чтобы достичь этих результатов (списки массивов, заполненные объектами, созданными в конструкторе моего класса ObjectCreator) чистым и эффективным способом? Это кажется довольно элементарной функцией, которая была бы необходима во многих программах, так как же это делается?
Комментарии:
1. Обновление: ссылка
objectCreator = new ObjectCreator();
фактически не назначается до завершения конструктораObjectCreator
. Если я попытаюсь использовать ссылку вCreatedObject
, я получуnullpointer
. Ответ заключается в поиске новой ссылки. Как мне создать новую полезную ссылку?
Ответ №1:
Проблема заключается в доступе к этому статическому полю. Назначение в main
не происходит до тех пор, пока конструктор не будет завершен, но вы пытаетесь прочитать его во внутреннем конструкторе класса.
Если вы собираетесь иметь внутренний (нестатический) класс, просто используйте список экземпляров заключающего класса.
Комментарии:
1. ОК. итак, вы говорите, что я на самом деле могу ссылаться на ArrayList, потому что он уже инициализирован, но я не могу сделать это, используя ссылку, которая еще не была создана
main
. По крайней мере, это то, что я понимаю. Как бы я мог ссылаться на список экземпляров окружающего класса без несуществующей ссылки, созданной в main?2. Заменить
objectCreator
наthis
.3. Извините за путаницу. Я не вижу, где замена
objectCreator
наthis
создаст другую ссылку. Возможно, я его пропускаю. Однако из вашего ответа я понимаю, что мне нужна другая ссылка на objectCreator , которая может быть передана через параметр конструктора createdObject . Это обеспечивает правильную работу программы. Существует ли какая-либо другая альтернатива ссылке, кроме передачи ее через конструктор? Мне нравятся минималистичные параметры. Если нет, это все еще вполне приемлемая альтернатива.4. Внутренние классы имеют неявную ссылку на содержащие их классы. Попробуйте решение, которое я предложил.
5. Я попробовал решение, которое вы предоставили в своем комментарии. Я получаю ошибку компиляции
No enclosing instance of the type ObjectCreator is accessible in scope
. Однако кажется, что это другая проблема, возможно, с видимостью? В любом случае, ваш ответ был превосходным и должен работать с настройкой. Если у вас есть совет по поводу ошибки, мне бы это понравилось, но вы ответили на мой первоначальный вопрос с оговоркойthis
.
Ответ №2:
Вы можете вызвать статическое поле, которое означает, что конструктор не вызывается.
ObjectCreator.objectCreator.objects.add(this);
Вы можете сделать это вместо этого в классе для инициализации статического поля:
static ObjectCreator objectCreator = new ObjectCreator();