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 吗?
一些备注:
我已经把问题降到最低了。我确实知道有更简单的方法来获取 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);
我有一个包含两个参数的 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 吗?
一些备注:
我已经把问题降到最低了。我确实知道有更简单的方法来获取 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);