Ссылка на поле объекта в другом объекте, созданном его конструктором

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