Как отследить, что объект внутри ArrayList становится нулевым? - PullRequest
0 голосов
/ 02 июля 2011

Структура, которая у меня есть:

Map<String, ArrayList<Bean>>

Этот Arraylist модифицируется (добавляется / удаляется) из разных мест в разных темах.

Иногда какой-то боб внутри ArrayList становится null. Как я могу отслеживать, когда он становится нулевым? Я хочу отследить, что делает бин нулевым, чтобы исправить ошибку.

Это происходит, когда сценарий тестируется с огромным набором данных.

Вот точный код, который не работает:

for (int i = 0; i < eventlogs.size(); i++) {
    MessageEventLogBean msgEventLogBean = (MessageEventLogBean) eventlogs.get(i);
    eventlogs.remove(i); 
    try {
        logWriter.write(msgEventLogBean, context);
    } catch (FusionException e) {
        logger.error("Error While writing the event log bean ", e);
    }
}

Ответы [ 3 ]

2 голосов
/ 02 июля 2011

Вместо стандартной реализации списка, используйте анонимный класс, который переопределяет метод add и добавляет специальный код, чтобы проверить, является ли добавленный объект пустым, например:

    List<T> list = new ArrayList<T>() {
        public boolean add(T e) {
            if (e == null) {
                throw new NullPointerException("Attempt to add null to list");
            }
            return super.add(e);
        }
    };

Вы должны аналогичным образом переопределитьвсе "добавить" методы, чтобы быть уверенным.Когда код добавляет ноль, он взорвется, и вы увидите исключение в журнале и сможете увидеть, кто это сделал, проверяет трассировку стека.

EDITED

Чтобы было понятно, это невозможно для объекта в списке "стать null".Вы можете добавить a null или удалить объект из Списка, но объект уже в Список будет оставаться там до тех пор, пока не будет удален.

Для ясности, только способ для null попасть в список - это поместить его туда - т.е. добавить его одним из методов add() или addAll()метод.Одновременные проблемы с модификацией могут не вызвать эту проблему (вы можете получить ConcurrentModificationException, но это все равно не добавит null).

Код, такой как

Object o = list.get(1);
o = null;

, не имеет никакого эффекта, потому что вы просто обнуляете копию ссылки на объект - list все еще ссылка на объект.

Однако, в зависимости от конструкции объектов Bean, они могут быть изменяемыми.В то время как ссылка на объект Бина останется нетронутой, некоторые поля в Бина могут стать null.Чтобы поймать это, вам нужно будет кодировать установщики для взрыва, когда передается аргумент null, либо переписывая класс, либо перегружая сеттеры через анонимный класс (аналогично моему первоначальному предложению выше).

0 голосов
/ 02 июля 2011

Возможно, это то, что вы намеревались

private final Queue<MessageEventLogBean> eventlogs = new ConcurrentLinkedQueue<>();

// this loop stops when it runs out of objects.
MessageEventLogBean msgEventLogBean;
while ((msgEventLogBean = eventlogs.poll()) != null) {
    try {
        logWriter.write(msgEventLogBean, context);
    } catch (FusionException e) {
        logger.error("Error While writing the event log bean ", e);
    }
}

или

// this loops until the thread is interrupted
private final BlockingQueue<MessageEventLogBean> eventlogs = new LinkedBlockingQueue<>();

while (true) {
    MessageEventLogBean msgEventLogBean = eventlogs.take();
    try {
        logWriter.write(msgEventLogBean, context);
    } catch (FusionException e) {
        logger.error("Error While writing the event log bean ", e);
    }
}

Оба варианта являются поточно-ориентированными.


Вы можете переопределить методы add () и set () для списка, чтобы null был недействительным и вызывал исключение.

List<MyType> list = new ArrayList<MyType>() {
    public boolean add(MyType mt) {
        if(mt == null) throw new IllegalArgumentException();
        super.add(mt);
    }
};

Рассмотрим следующий код

String a = "hi"; // a => "hi"
String b = a; // a => "hi" and b => "hi"
a = null; // a => null and b => "hi"

String a является ссылкой на строку, и когда вы присваиваете ей null, вы изменяете только значение a, а другие ссылки на тот же объект не затрагиваются.


Способ обработки каждой второй записи или почему использование remove (i) вряд ли будет тем, что вам нужно.

List<Integer> list = new ArrayList<>();
for(int i=0;i<10;i++) list.add(i);
for(int i=0;i<list.size();i++) {
    System.out.println(list.get(i));
    list.remove(i);
}

печать

0
2
4
6
8
0 голосов
/ 02 июля 2011

Это небольшая работа, но вы можете создать свою собственную реализацию интерфейса List, которая делегирует все методы ArrayList. В методе доступа, где вы обычно возвращаете ArrayList, вместо этого возвращайте вашу отладочную реализацию с ArrayList, обернутым внутри него. Затем просто установите точку останова в вашем методе set, и вы будете точно знать, какой код вызывается в ArrayList.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...