为什么list.contains(null)会抛出空指针异常?

问题描述 投票:0回答:3

我有

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

java exception collections nullpointerexception
3个回答
10
投票

为什么

list.contains(null)
抛出空指针异常?

因为这是规范所说的可能发生的情况。

List.of(...)
案例的具体推理如下:

  1. List.of
    方法被指定为生成不可修改的列表

  2. 不可修改的列表被指定以不允许

    null
    元素:

    “它们不允许空元素。尝试使用

    null
    元素创建它们会导致
    NullPointerException
    。”

  3. List.contains

    javadoc
    指出:

    “抛出:

    NullPointerException
    - 如果指定元素是
    null
    并且此列表不允许
    null
    元素。

换句话说,您所看到的是指定的行为......而不是不正确或反复无常的实现的结果。

对于您正在搜索

countryList
的情况...它将取决于实际的
List
实现类。但是
List
contains
规范中有一个明确的预期:如果您尝试搜索 null,某些
类型的列表可能会抛出 NPE。

(这是否是一个“糟糕的设计选择”,这是一个观点问题。但这没有实际意义。List

设计选择是很久以前做出的,现在改变它们会造成太大的破坏性,无法考虑。此外,我怀疑您能否让当前的 Java 设计团队相信集合类型中的 
null
 值是个好主意。)


3
投票
来自

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
 生成的元素
    


0
投票
如果您想要一个可为空的列表,则只需使用

Arrays.asList

 即可。那么
contains(null)
就不会抛出
NullPointerException

© www.soinside.com 2019 - 2024. All rights reserved.