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

mge*_*cht 4 java nullpointerexception conditional-operator optional

我有一个包含两个参数的Dto的List <>:type和value.现在我想找到类型为"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; }
}
Run Code Online (Sandbox Code Playgroud)

...

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);
Run Code Online (Sandbox Code Playgroud)

该异常显示在以下行中:

Double value = optional.isPresent() ? ((TestDto) optional.get()).getValue() : 0;
Run Code Online (Sandbox Code Playgroud)

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

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

一些评论:

  • 我已将问题减少到最低限度.我知道有更简单的方法来获得Dto的价值.我只想理解为什么上面显示的代码不起作用.

  • 如果搜索"A"或"B"类型,则没有错误,并且该值将打印两次

  • 替换值"0"应该是"0d"而是编译为"0".但是,将代码更改为:

Double value = optional.isPresent() ? null : 0;
Run Code Online (Sandbox Code Playgroud)

直到我将替换值更改为"0d"才会编译.也许这有助于解决问题.

Mic*_*ael 12

这是一个有点滑稽的.你的三元运营商在这里:

optional.isPresent() ? ((TestDto) optional.get()).getValue() : 0;
Run Code Online (Sandbox Code Playgroud)

正在使用原始零.Java决定首先将null解包Double为原始double,这样两个结果都是相同的类型,这会导致a NullPointerException.

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

optional.isPresent() ? ((TestDto) optional.get()) : Double.valueOf(0);
Run Code Online (Sandbox Code Playgroud)

顺便说一句,所有可怕的强制转换使你的代码在某些地方显得如此丑陋,这是因为你没有使用泛型版本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);
Run Code Online (Sandbox Code Playgroud)

  • 顺便说一句,为了使它更好,人们也可以这样做:`Double value = optional.map(TestDto :: getValue).orElseGet(0D);` (5认同)
  • @davida.小心!这不是一个确切的替代品.如果`getValue`返回null,那么当你确实想要null时,你最终会得到0. (2认同)