我有
List<Long> countriesList
,其中包含 Long
值,这些值是国家/地区 ID。
现在我正在使用
List<UserRequests>
迭代一些 streams
列表。
userRequests.stream().
forEach(userRequest->
{
UserData=userRepository.findById(userRequest.getId()); //fine
if (CollectionUtils.isNotEmpty(countriesList) && countriesList.contains(userRequest.getCountryId()))//getting NPE here
{
//do some operation
}
});
我尝试通过评估各个语句来进行调试。 我已经确定
countriesList
有一些数据
第一部分CollectionUtils.isNotEmpty(countriesList)
正在返回true
。
userRequest
也不为空,但 userRequest.getCountryId()
为空。
当我评估countriesList.contains(userRequest.getCountryId())
时,我在这里得到Null pointer exception
。为什么不false
?
我很困惑我做错了什么。
默认 list.contains(null)
行为只是这样还是因为我在 stream()
中调用它?
为了简化,我创建了简单的列表并与
null
进行比较。
class Test {
public static void main(String[] args) {
List<Long> longList = List.of(1L, 2L, 3L);
System.out.println("Comparing long list with null::" + longList.contains(null));
}
}
这是我遇到的异常:
Exception in thread "main" java.lang.NullPointerException
at java.base/java.util.Objects.requireNonNull(Objects.java:222)
at java.base/java.util.ImmutableCollections$AbstractImmutableList.indexOf(ImmutableCollections.java:166)
at java.base/java.util.ImmutableCollections$AbstractImmutableList.contains(ImmutableCollections.java:197)
at com.test.Test.main(Test.java:26)
但是如果我这样做:
List<Long> longList = new ArrayList<>();
longList.add(1L);
System.out.println("Comparing long list with null::" + longList.contains(null));
为什么会打印
false
?为什么这里没有NullPointerException
?
为什么
抛出空指针异常?list.contains(null)
因为这是规范所说的可能发生的情况。
List.of(...)
案例的具体推理如下:
List.of
方法被指定为生成不可修改的列表。
不可修改的列表被指定以不允许
null
元素:
“它们不允许空元素。尝试使用
元素创建它们会导致null
。”NullPointerException
javadoc指出:
“抛出:
- 如果指定元素是NullPointerException
并且此列表不允许null
元素。null
换句话说,您所看到的是指定的行为......而不是不正确或反复无常的实现的结果。
对于您正在搜索
countryList
的情况...它将取决于实际的 List
实现类。但是 List
的 contains
规范中有一个明确的预期:如果您尝试搜索 null
,某些类型的列表可能会抛出 NPE。
(这是否是一个“糟糕的设计选择”,这是一个观点问题。但这没有实际意义。List
设计选择是很久以前做出的,现在改变它们会造成太大的破坏性,无法考虑。此外,我怀疑您能否让当前的 Java 设计团队相信集合类型中的
null
值是个好主意。)
java.util.List的API文档:
某些列表实现对其可能包含的元素有限制。例如,某些实现禁止 null 元素,而某些实现对其元素的类型有限制。尝试添加不合格的元素会引发未经检查的异常,通常为 NullPointerException 或 ClassCastException。尝试查询是否存在不合格元素可能会引发异常,或者可能只是返回 false;一些实现将表现出前一种行为,而另一些实现将表现出后者。更一般地,尝试对不合格元素执行操作(其完成不会导致将不合格元素插入到列表中)可能会引发异常,也可能会成功,具体取决于实现的选择。此类例外在此接口的规范中被标记为“可选”。
布尔包含(对象o)您的如果此列表包含指定元素,则返回
true
。更正式地说,当且仅当此列表包含至少一个元素 e 且满足 Objects.equals(o, e) 时,才返回 true。指定者:包含在界面集合中
参数:
o - 要测试此列表中是否存在的元素
退货:
如果此列表包含指定元素,则为 true
投掷:
ClassCastException - 如果指定元素的类型与此列表不兼容(可选)
NullPointerException - 如果指定的元素为 null 并且此列表不允许 null 元素(可选)
countriesList
似乎属于 List 类型,不接受
null
元素,例如由
List.of
或
List.copyOf
生成的元素
Arrays.asList
即可。那么
contains(null)
就不会抛出
NullPointerException
。