#java #android
#java #Android
Вопрос:
У меня в моем приложении исключение нулевого указателя. Нулевой указатель возникает даже после проверки, не является ли объект null..
К моему классу обращаются разные потоки. Итак, я считаю, что объекту-члену класса присваивается значение null после оператора if. Итак, когда я на самом деле пытаюсь получить к нему доступ, возможно, значение null уже приводит к NPE (исключение нулевого указателя).
Ниже приведен мой код:
private MyCustomListener listener;
public void setListener(@Nullable final MyCustomListener listener) {
mMyCustomListener = listener;
}
public void onEvent() {
if (mMyCustomListener != null) {
.... // Some code
listener.execute(); // Null Pointer Exception at this line
}
}
Что я пробовал:
private MyCustomListener listener;
private static final Object mListenerSync = new Object();
public void setListener(@Nullable final MyCustomListener listener) {
synchronized(mListenerSync) {
mMyCustomListener = listener;
}
}
public void onEvent() {
synchronized(mListenerSync) {
if (mMyCustomListener != null) {
.... // Some small code
listener.execute(); // Null Pointer Exception
}
}
}
В принципе, у меня есть два потока. Тот, который устанавливает / отключает прослушиватель для получения onEvent()
уведомлений. Второй поток отвечает за создание onEvent()
вызовов. Я бы хотел, чтобы прослушиватель из первого потока перестал вызываться, как только я установил для прослушивателя значение null.
Итак, я хотел бы запросить вашу поддержку для подтверждения следующих пунктов.
-
Будет ли теперь мой код безопасен для протектора? Или, по крайней мере, я избегаю NPE.
-
Объект mListenerSync должен быть статическим?
Я тестирую свой код, и я не заметил никакого побочного эффекта, такого как тупиковая блокировка.. Однако я не уверен, исправит ли этот код мою проблему, учитывая, что его трудно воспроизвести.
Ответ №1:
Если вы уверены, что причиной являются другие потоки, устанавливающие прослушиватель null
, вы можете легко исправить это с помощью локальной переменной и без дополнительной синхронизации. Создайте переменную transient
, если вы действительно меняете прослушиватель, чтобы обеспечить видимость. Хотя у меня такое чувство, что это не причина ваших ошибок
private transient MyCustomListener listener;
public void onEvent() {
MyCustomListener listener = myCustomListener;
if (listener != null) {
.... // Some code
listener.execute();
}
}
Комментарии:
1. Спасибо за внимание. Я немного обновил вопрос, добавив больше информации. Мне понравился ваш подход. Это, безусловно, исправляет NPE. Тем не менее, я хотел бы избежать возможного дополнительного вызова listener.execute() после установки для listener значения null. Как вы думаете, это возможно?
2. @W0rmH0le конечно, это возможно, но это гораздо проще и проще, поэтому имеет смысл выбирать сложную версию (т.Е. мьютекс полной синхронизации, как вы сделали во второй версии, которая выглядит нормально), если вам действительно нужно избежать малейшего шанса, что планировщик потоков сделаетлокальная переменная и переменная экземпляра не синхронизированы. Если вы только хотели бы избежать этого, разве вам не хотелось бы иметь более приятный код?