Java 中的可选条件运算符导致 NullPointerException

Optional in Java conditional operator leads to NullPointerException

我有一个包含两个参数的 Dto 列表<>:类型和值。现在我想在列表中找到类型为 "C" 的一个元素并读出值。

当执行以下 java 代码时,我得到一个我不理解的 NullPointerException:

class TestDto
{
    private String type;
    private Double value;

    TestDto(final String type, final Double value)
    {
        this.type = type;
        this.value = value;
    }

    public String getType() { return type; }
    public Double getValue() { return value; }
}

...

List<TestDto> testList = new ArrayList<>();
testList.add(new TestDto("A", 11.111d));
testList.add(new TestDto("B", 22.222d));
testList.add(new TestDto("C", null));

Predicate<TestDto> typePredicate = c-> c.getType().equals("C");
Optional optional = testList.stream().filter(typePredicate).findFirst();

if(optional.isPresent()){
    System.out.println("if-output = " + ((TestDto) optional.get()).getValue());
}

Double value = optional.isPresent() ? ((TestDto) optional.get()).getValue() : 0;

System.out.println(value);

异常出现在以下行:

Double value = optional.isPresent() ? ((TestDto) optional.get()).getValue() : 0;

类型为 "C" 的列表元素的值为 null,因此我希望 Double 值变为 null - 这没问题。这在 if 语句内部起作用,它按预期打印 "if-output = null"。

我希望 if 语句与条件运算符相同。你知道我为什么会收到 NullPointerException 吗?

一些备注:

Double value = optional.isPresent() ? null : 0;

在我将替换值更改为“0d”之前,它不会编译。也许这有助于解决问题。

有点好笑。你的三元运算符在这里:

optional.isPresent() ? ((TestDto) optional.get()).getValue() : 0;

正在使用原始零。 Java 决定首先将 null Double 拆箱为原始双精度数,以便两个结果属于同一类型,这会导致 NullPointerException.

如果将 0 替换为 Double.valueOf(0),则三元的两个结果都是 Double 类型,因此不需要进行拆箱。

optional.isPresent() ? ((TestDto) optional.get()) : Double.valueOf(0);

顺便说一句,所有让您的代码在某些地方看起来如此丑陋的可怕转换都是您没有使用 Optional 的通用版本的结果。如果您使用通用版本,您的代码可能如下所示:

Optional<TestDto> optional = testList.stream().filter(typePredicate).findFirst();
       // ^ Generics!

if(optional.isPresent()){
    System.out.println("if-output = " + optional.get().getValue());
}

Double value = optional.isPresent() ? optional.get().getValue() : Double.valueOf(0);

System.out.println(value);