I have a List<> of an Dto containing two parameters: type and value. Now I would like to find one element of the list with type "C" and read out the value.
When executing the following java code I get a NullPointerException which I do not understand:
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);
The exception appears in the following line:
Double value = optional.isPresent() ? ((TestDto) optional.get()).getValue() : 0;
The value of the list element with type "C" is null, so I would expect the Double value to become null - which would be ok. This works inside of the if statement, it prints "if-output = null" as expected.
I would expect the if statement to be identical with the conditional operator. Do you have an idea why I get the NullPointerException?
Some remarks:
I have reduced the problem to the minimum. I do understand that there are easier ways to get the value of the Dto. I would just like to understand why the code shown above doesn't work.
If you search for type "A" or "B" there is no error and the value is printed out twice
The replacement value "0" should be "0d" instead but it compiles with "0". However when changing the code to:
Double value = optional.isPresent() ? null : 0;
it does not compile until I change the replacement value to "0d". Maybe this helps to unserstand the problem.
It's a slightly funny one. Your ternary operator here:
optional.isPresent() ? ((TestDto) optional.get()).getValue() : 0;
is using a primitive zero. Java is deciding to first unbox your null Double
to a primitive double, so that both results are of the same type, and that causes a NullPointerException
.
If you replace 0
with Double.valueOf(0)
, both results of the ternary are of the type Double
and so no unboxing needs to take place.
optional.isPresent() ? ((TestDto) optional.get()) : Double.valueOf(0);
As an aside, all of the horrible casting which makes your code look so ugly in places is a result of you not using the generic version of Optional
. If you use generic version, your code could look like this:
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);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With