我有一个Dto的List <>,其中包含两个参数:类型和值。现在,我想找到类型为“ 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”的列表元素的值为空,因此我希望Double值变为空-可以。这在if语句内部起作用,按预期方式输出“ if-output = null”。
我希望if语句与条件运算符相同。您知道为什么我会收到NullPointerException吗?
一些评论:
我已将问题减少到最低限度。我确实知道,有更简单的方法来获取Dto的价值。我只想了解为什么上面显示的代码不起作用。
如果搜索类型“ A”或“ B”,则没有错误,并且值被打印两次
替换值“ 0”应改为“ 0d”,但编译时应为“ 0”。但是,将代码更改为:
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);