When dealing with nested Objects in Java –
Something like:
// bad code
game.getPlayer().getState().getPositionInfo().getCurrent().getX();
, it is not clear if a nested reference would return null resulting in a NullPointerException to be thrown.
My idea was to have one generic method which calls reference path down while checking for a null reference,
and instead of throwing the Exception, just return null.
Error handling is out of scope for this solution.
My minimum code example looks like this:
import java.util.function.Function;
public class Main {
public static void main(String[] args) {
// Check 1: baseline - "normal" function mappings
SAVE.TY_Baseline(b -> b.contains("a"), "aoiudssaiud"); // works
// Check 2: nested types
Team t = new Team(new Team(null));
Team t1 = SAVE.TY_Chained(() -> t.getTeam(), z -> z.getTeam()); // does not compile
// Check 3: String -> boolean -> String
String g = "Hi !";
// does not compile
Team t2 = SAVE.TY_Chained(() -> g.contains("Hi"), b -> b ? "contained" : "not contained");
}
public static class Team {
private Team t = null;
public Team(Team t) {
this.t = t;
}
public Team getTeam() {
return t;
}
}
public static interface SAVE {
public static <A, B> B TY_Chained(Function<Void, A> first , Function<A, B> second) {
A firstResult = first.apply(null);
if (firstResult == null)
return null;
return second.apply(firstResult);
}
public static <A,B> B TY_Baseline(Function<A,B> oo, A in) {
return oo.apply(in);
}
}
}
For check 1:
Everything turns out good, the function executes and the compiler recognizes the input as String and also accepts the function.
For check 2 and 3:
When chaining the functions, the compiler does not know which parameter type function “second” has and will not accept this method call.
Getting:
java: incompatible types: incompatible parameter types in lambda expression
Using OpenJDK V22 right now.
2
You can use existing libraries like vavr.
If you willing to invent your own wheel you can at least get some inspiration from them.
You specific case is simple enough it can be solved without third party library. Just Optional
from standard JDK.
Optional.ofNullable(game)
.map(x->x.getPlayer())
.map(x->x.getState())
.map(x->x.getPositionInfo())
.map(x->x.getCurrent())
.map(x->x.getX())
.orElse(null);
0
Check 2 and 3 are failing because you’re providing first
a function with zero parameters, when it is expecting a function with one. Change TY_CHAINED
‘s signature:
public static <A, B> TY_CHAINED(Supplier<A> first, Function<A, B> second) {
A firstResult = first.get();
if (firstReslt == null) return null;
return second.apply(firstResult);
}
A Function<Void, A>
is not actually a function that takes zero arguments, but is instead a function that takes one argument that must be null
(since null
is the only valid value for the Void
type).
Otherwise, I agree with talex, Optional.map()
is best for null-chaining
1