Как инициализировать ThreadLocal<List <Object >>
Ниже приведен мой код, в котором я объявляю ThreadLocal
переменная:
public static final ThreadLocal<List<Object>> ARGS = new ThreadLocal<>();
Я использую эту переменную в следующем фрагменте:
private static void getParams(Token... tokens) {
if(ARGS == null) {
new LinkedList<>();
}
if(tokens.length > 2) {
for(Token token : Arrays.copyOfRange(tokens, 2, tokens.length)) {
ARGS.get().add(ArgHelper.resolveArg(token));
}
}
}
Нижняя строка:
ARGS.get().add(ArgHelper.resolveArg(token));
дает мне NullPointerException
ты получаешь ценность от ArgHelper.resolveArg(token)
,
3 ответа
Java 8
private static final ThreadLocal<List<Object>> list =
ThreadLocal.withInitial(ArrayList::new);
Заметить, что:
if(ARGS == null) {
new LinkedList<>();
}
ничего не делает ARGS
создается как final
ненулевое значение, поэтому этот блок никогда не будет введен. Даже если бы это сделал, позвонив new LinkedList<>();
в одиночку просто строит LinkedList
экземпляр, который немедленно выпадает из области видимости и является сборщиком мусора. Ничто не может ссылаться на это.
Чтобы правильно инициализировать ThreadLocal
Посмотрите документацию, в которой приведен пример, показывающий, как установить начальное значение (путем переопределения метко названного initialValue()
метод).
Вы можете сделать что-то подобное:
public static final ThreadLocal<List<Object>> ARGS = new ThreadLocal<List<Object>>() {
@Override protected List<Object> initialValue() {
return new LinkedList<>();
}
};
Тем не менее, некоторые указатели:
- Вы должны предпочесть
ArrayList
надLinkedList
почти во всех случаях. - Делать
ARGS
private
если это абсолютно необходимо. Обычно лучше минимизировать видимостьThreadLocal
экземпляры, например, ограничивая его классом, содержащим класс, и предоставляя более приятный API пользователям этого класса. - Рассмотрим более значимый тип, чем
List<Object>
- вы заставляете всех пользователей проверять и выводить содержимое списка, если оно может содержать какие-либоObject
,
Это не то, как вы используете ThreadLocal
,
Вместо испорченного кода вы, вероятно, захотите, чтобы следующее инициализировало пустой локальный поток.
if(ARGS.get() == null) {
ARGS.set(new LinkedList<>());
}
Конечно, я бы посоветовал не использовать ThreadLocal
вообще, особенно если у вас нет опыта его использования.