我有一个List<>包含两个参数的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;
类型为&#34; C&#34;的列表元素的值是null,所以我希望Double值变为null - 这没关系。这在if语句中起作用,它打印&#34; if-output = null&#34;如预期的那样。
我希望if语句与条件运算符相同。你知道我为什么得到NullPointerException吗?
一些评论:
我已将问题减少到最低限度。我知道有更简单的方法来获得Dto的价值。我想了解为什么上面显示的代码不起作用。
如果您搜索类型&#34; A&#34;或&#34; B&#34;没有错误,值打印两次
替换值&#34; 0&#34;应该是&#34; 0d&#34;相反,它用&#34; 0&#34;编译。但是,在将代码更改为:
Double value = optional.isPresent() ? null : 0;
在我将替换值更改为&#34; 0d&#34;之前,它不会编译。也许这有助于解决问题。
答案 0 :(得分:12)
这是一个有点滑稽的。你的三元运营商在这里:
optional.isPresent() ? ((TestDto) optional.get()).getValue() : 0;
正在使用原始零。 Java决定首先将null Double
解包为原始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);