I have the following scenario: two validation Helpers
the StringValidationHelper ...
public class StringValidationHelper {
public static Validation<String> notNull =
SimpleValidation.from(s -> s != null, "must not be null.");
public static Validation<String> moreThan(int size) {
return SimpleValidation.from(
s -> s.length() >= size,
String.format ("must have more than %s chars.", size));
}
... // More methods (lessThan, etc)}
... and NumberValidationHelper.
public class NumberValidationHelper {
public static Validation<Number> notNull =
SimpleValidation.from(n -> n != null, "must not be null");
public static <N extends Number & Comparable<N>> Validation<N> lowerThan(N max){
return SimpleValidation.from(
n -> n.compareTo(max) == -1,
String.format("must be lower than %s.", max));
}
... // More methods like (greaterThan, etc)}
The method from is a static factory method that receives a Predicate and a message to eventual validation fails.
public class SimpleValidation<K> implements Validation<K>{
private Predicate<K> predicate;
private String onErrorMessage;
private SimpleValidation(Predicate<K> predicate, String onErrorMessage) {
this.predicate = predicate;
this.onErrorMessage = onErrorMessage;
}
public static <K> SimpleValidation<K> from(Predicate<K> predicate, String onErrorMessage){
return new SimpleValidation<>(predicate, onErrorMessage);
}
... // Omitted for simplicity
}
Thanks to the Validation interface, you can enjoy a wonderfully smooth interface
#FunctionalInterface
public interface Validation<K> {
... // Omitted for simplicity
default Validation<K> and(Validation<K> other) {
return param -> {
ValidationResult firstResult = this.test (param);
return ! firstResult.isValid()? firstResult: other.test(param);
};
}
... // Omitted for simplicity
}
So I can start, for example, a validation using the closure notNull.
Example: with NumberValidationHelper
public class MyValidate {
void validate(int toValidate) {
notNull.and(lowerThan(100)).test(toValidate).isValid();
}
}
This validation framework I developed based on this article.
Well, notNull enclaves a type-independent behavior, so I'd like to remove the duplication of these two helpers.
I'm not finding an obvious shape without losing the fluid interface.
Because the variable is static, you can not use generics and extend the behavior, for instance.
public abstract class GenericHelper<K> {
public static Validation<K> notNull = SimpleValidation.from(o -> o != null, "must not be null.");
}
Also it does not bother me to type Validation with Object as below:
public abstract class GenericHelper {
public static Validation<Object> notNull = SimpleValidation.from(o -> o != null, "must not be null.");
}
... because in the call chaining, it will give compilation error since the result of notNull will be a Validation< Object > and and will be expecting a Validation< Integer >
notNull.and(lowerThan(100)).test(toValidate).isValid(); //Does not compile
Is there any way to use the Java 8 function features that keep this interface flowing generically, running away from the solutions I've tried above?
thankful
You should relax the generic signature of and, allowing a Validation<T> with a more specific T as parameter, to produce a Validation<T> as result:
default <T extends K> Validation<T> and(Validation<T> other) {
return param -> {
ValidationResult firstResult = this.test(param);
return ! firstResult.isValid()? firstResult: other.test(param);
};
}
Staying with your examples, you still cannot write
void validate(int toValidate) {
notNull.and(moreThan(100)).test(toValidate).isValid();
}
as moreThan returns a Validation<String> which can not test an int, but spotting such errors is what Generics is all about (I suppose, you have another moreThan method in your actual code base which you didn’t include in your question). But the following will now work with your example:
void validate(int toValidate) {
notNull.and(lowerThan(100)).test(toValidate).isValid();
}
Sometimes, you need to test a validation of a more specific type before a more generic validation which still doesn’t work with the method shown above. One solution would be to go the same route as the JDK developers and augment Function.andThen(after) with a Function.compose(before), allowing to swap the roles
default <T extends K> Validation<T> compose(Validation<T> other) {
return param -> {
ValidationResult firstResult = other.test(param);
return ! firstResult.isValid()? firstResult: this.test(param);
};
}
Or you create a static method, which allows both arguments to have a broader type than the resulting Validation:
static <T> Validation<T> and(Validation<? super T> first, Validation<? super T> second) {
return param -> {
ValidationResult firstResult = first.test(param);
return ! firstResult.isValid()? firstResult: second.test(param);
};
}
Note that the static method can be combined with the convenient instance method, so that the caller only needs to resort to the static method when hitting the limitations of the generic signature:
#FunctionalInterface
public interface Validation<K> {
ValidationResult test(K item);
default <T extends K> Validation<T> and(Validation<T> other) {
return and(this, other);
}
static <T> Validation<T> and(Validation<? super T> first,Validation<? super T> second){
return param -> {
ValidationResult firstResult = first.test(param);
return ! firstResult.isValid()? firstResult: second.test(param);
};
}
}
So you can still write
notNull.and(lowerThan(100)).test(toValidate).isValid();
but when hitting the limitation, e.g.
Validation<Object> anotherCriteria;
…
lowerThan(100).and(anotherCriteria).test(toValidate).isValid();
does not work, you can resort to
Validation.and(lowerThan(100), anotherCriteria).test(toValidate).isValid();
Related
I'd like to use something like this to check some conditions, but the problem is that I need to know which condition failed and log the exception, this way does achieve it but relies on knowing the position at which it was checked inside the code which isn't ideal, is there any other nicer way of doing this? (without making calling the function much longer)
matchOrThrow(
() -> 1 == 2,
() -> 1 == 1,
() -> a > b,
() -> c == null
);
public static void matchOrThrow(BooleanSupplier... conditions) {
int i = 1;
for (BooleanSupplier condition : conditions) {
if (Boolean.FALSE.equals(condition.getAsBoolean())) {
throw new CustomException("Condition check n_" + i + " failed");
}
i++;
}
}
You might be interested at looking at the Decorator design patter.
Namely, you can create a decorating implementation of the Functional interface of your choice. It seems like you Predicate is more suitable for than a BooleanSupplier, therefore the example below illustrates a throwing Predicate, which expects a predicate, producer of the target exception, message and logger as arguments and its implementation of test() delegates to the wrapped predicate to evaluate the condition.
The instances of the trowing Predicate can be used anywhere, where Predicate is expected.
public class ThrowingLoggPredicate<T> implements Predicate<T> {
private Predicate<T> predicate;
private Function<String, RuntimeException> exceptionFactory;
private String messageShort;
private String format;
private Logger logger;
public ThrowingLoggPredicate(Predicate<T> predicate,
Function<String, RuntimeException> exceptionFactory,
String messageShort, String format,
Logger logger) {
this.predicate = predicate;
this.exceptionFactory = exceptionFactory;
this.messageShort = messageShort;
this.format = format;
this.logger = logger;
}
public boolean test(T t) {
if (!predicate.test(t)) {
RuntimeException e = exceptionFactory.apply(messageShort);
String messageVerbose = String.format(format, t);
logger.log(Level.ERROR, messageVerbose, e);
throw e;
}
return true;
}
public static <T> boolean allMatch(Collection<Predicate<T>> predicates, T t) {
return predicates.stream().allMatch(p -> p.test(t));
}
}
I want to create a construct that would work with pageable feign api calls and dry them from the first page of declared size available to the last one.
To take in account:
the feign method calls can differ in arg. count tho last two is always page and it's size
data structure returned is similar to the extent of paging information, but core data list received type differs
This is what I did:
method that is a base for draining a particular api call:
public <T> List<BaseFeignResult<T>> drainFeignPageableCall(
PagedCall<T> feignCall
) {
BaseFeignResult<T> firstPage = feignCall.call(0, 10);
List<BaseFeignResult<T>> baseFeignResults = drainFeignPageableCall(feignCall, firstPage, Lists.newArrayList(firstPage), 1);
return baseFeignResults;
}
It's overload and continuation:
<T> List<BaseFeignResult<T>> drainFeignPageableCall(
PagedCall<T> feignCall,
BaseFeignResult<T> dataPage,
List<BaseFeignResult<T>> acc,
int page
) {
if (dataPage.resp.getBody().getData().size() % 10 > 0)
return acc;
BaseFeignResult<T> res = feignCall.call(page, 10);
acc.add(res);
return drainFeignPageableCall(feignCall, res, acc, ++page);
}
And the definitions:
public static class SingleParamPageableCall<T> implements PagedCall<T> {
SingleParamPagingApi<T> fun;
String param;
public SingleParamPageableCall(SingleParamPagingApi<T> fun, String param) {
this.fun = fun;
this.param = param;
}
#Override
public BaseFeignResult<T> call(int p, int s) {
BaseFeignResult.BaseFeignResultBuilder<T> builder = BaseFeignResult.builder();
try {
builder.resp(fun.callFeignApi(param, p, s));
} catch (RuntimeException e) {
builder.excp(e);
}
return builder.build();
}
}
public interface PagedCall<T> {
BaseFeignResult<T> call(int p, int s);
}
#Builder
public static class BaseFeignResult<T> {
private final ResponseEntity<IVDPagedResponseOf<T>> resp;
private final RuntimeException excp;
}
public interface SingleParamPagingApi<T> {
ResponseEntity<IVDPagedResponseOf<T>> callFeignApi(String arg, int page, int size) throws RuntimeException;
}
This can be arbitraliry called as:
drainFeignPageableCall(new BaseService.SingleParamPageableCall<GetOrderInfoDto>(ordersFeignClient::getOrdersBySampleIds, "34596"));
and works as expected.
So as you can see, if I want to keep some sort of abstraction above various drain-able per api calls, I need to introduce definitions like SingleParamPagingApi and class implementation of SingleParamPageableCall<T>. so with every other api to be treated this way, I would need to redefine those.
My question here is: how to do this in purely descripive way, or how to reimplement this as a functional programming?
to be clear: I would like to have code impl. in which I would describe how to map parameters to the method call (that can and will vary) and return a common data structure with the data being of generic type.
Basically I am looking for the most descriptive way of re-implementing this in Java without defining heavy objects like SingleParamPagingApi<T>, but describing how to mount params called with to API params itself rather.
Thank you!
This simplest way would be to replace your SingleParamPagingApi interface with one that has a method that just takes the page no and size as parameters (PagingApi). And replace SingleParamPageableCall with a class that just takes a PagingApi argument. Then you can create the variants of PagingApi for 1 parameter, 2 parameters etc by immediately binding the method to the argument 0, argument 1 etc, thereby creating a PagingApi instance (the of methods).
public interface PagingApi1<T, A0> {
ResponseEntity<IVDPagedResponseOf<T>> callFeignApi(A0 arg0, int page, int size) throws RuntimeException;
}
public interface PagingApi2<T, A0, A1> {
ResponseEntity<IVDPagedResponseOf<T>> callFeignApi(A0 arg0, A1 arg1, int page, int size) throws RuntimeException;
}
public interface PagingApi<T> {
static <T, A0> PagingApi<T> of(PagingApi1<T, A0> api, A0 arg0) {
return (p, s) -> api.callFeignApi(arg0, p, s);
}
static <T, A0, A1> PagingApi<T> of(PagingApi2<T, A0, A1> api, A0 arg0, A1 arg1,) {
return (p, s) -> api.callFeignApi(arg0, arg1, p, s);
}
ResponseEntity<IVDPagedResponseOf<T>> callFeignApi(int page, int size) throws RuntimeException;
}
public static class PageableCall<T> implements PagedCall<T> {
PagingApi<T> fun;
public PageableCall(PagingApi<T> fun) {
this.fun = fun;
}
#Override
public BaseFeignResult<T> call(int p, int s) {
BaseFeignResult.BaseFeignResultBuilder<T> builder = BaseFeignResult.builder();
try {
builder.resp(fun.callFeignApi(p, s));
} catch (RuntimeException e) {
builder.excp(e);
}
return builder.build();
}
}
You would call it as follows:
drainFeignPageableCall(
new PageableCall<GetOrderInfoDto>(
PagingApi.of(ordersFeignClient::getOrdersBySampleIds, "34596")
)
);
As a further simplifcation, you could probably collapse PagingApi and PagedCall into a single interface.
I would also suggest replacing the recursive calls in drainFeignPageableCall with a simple for loop. You might think recursion is more "functional" but it's needlessly complex and inefficient here.
Just playing and came up with a sweet way to add functionality to enums in Java Enum toString() method with this.
Some further tinkering allowed me to nearly also add a tidy (i.e. not throwing an exception) reverse look-up but there's a problem. It's reporting:
error: valueOf(String) in X cannot implement valueOf(String) in HasValue
public enum X implements PoliteEnum, ReverseLookup {
overriding method is static
Is there a way?
The aim here is to silently add (via an interface implementation with a default method like I added politeName in the linked answer) a lookup method that does the valueOf function without throwing an exception. Is it possible? It is clearly now possible to extend enum - one of my major problems with Java until now.
Here's my failed attempt:
public interface HasName {
public String name();
}
public interface PoliteEnum extends HasName {
default String politeName() {
return name().replace("_", " ");
}
}
public interface Lookup<P, Q> {
public Q lookup(P p);
}
public interface HasValue {
HasValue valueOf(String name);
}
public interface ReverseLookup extends HasValue, Lookup<String, HasValue> {
#Override
default HasValue lookup(String from) {
try {
return valueOf(from);
} catch (IllegalArgumentException e) {
return null;
}
}
}
public enum X implements PoliteEnum/* NOT ALLOWED :( , ReverseLookup*/ {
A_For_Ism, B_For_Mutton, C_Forth_Highlanders;
}
public void test() {
// Test the politeName
for (X x : X.values()) {
System.out.println(x.politeName());
}
// ToDo: Test lookup
}
You are over-complicating your design. If you are willing to accept that you can invoke a default method on an instance only, there entire code may look like this:
interface ReverseLookupSupport<E extends Enum<E>> {
Class<E> getDeclaringClass();
default E lookup(String name) {
try {
return Enum.valueOf(getDeclaringClass(), name);
} catch(IllegalArgumentException ex) { return null; }
}
}
enum Test implements ReverseLookupSupport<Test> {
FOO, BAR
}
You can test it with:
Test foo=Test.FOO;
Test bar=foo.lookup("BAR"), baz=foo.lookup("BAZ");
System.out.println(bar+" "+baz);
An non-throwing/catching alternative would be:
interface ReverseLookupSupport<E extends Enum<E>> {
Class<E> getDeclaringClass();
default Optional<E> lookup(String name) {
return Stream.of(getDeclaringClass().getEnumConstants())
.filter(e->e.name().equals(name)).findFirst();
}
to use like:
Test foo=Test.FOO;
Test bar=foo.lookup("BAR").orElse(null), baz=foo.lookup("BAZ").orElse(null);
System.out.println(bar+" "+baz);
Here, there's basically two points. Specifically the reason it doesn't compile is 8.4.8.1:
It is a compile-time error if an instance method overrides a static method.
In other words, an enum can't implement HasValue because of the name clash.
Then there's the more general issue we have which is that static methods just cannot be 'overridden'. Since valueOf is a static method inserted by the compiler on the Enum-derived class itself, there's no way to change it. We also can't use interfaces to solve it since they do not have static methods.
In this specific case it's a place where composition can make this kind of thing less repetetive, for example:
public class ValueOfHelper<E extends Enum<E>> {
private final Map<String, E> map = new HashMap<String, E>();
public ValueOfHelper(Class<E> cls) {
for(E e : EnumSet.allOf(cls))
map.put(e.name(), e);
}
public E valueOfOrNull(String name) {
return map.get(name);
}
}
public enum Composed {
A, B, C;
private static final ValueOfHelper<Composed> HELPER = (
new ValueOfHelper<Composed>(Composed.class)
);
public static Composed valueOfOrNull(String name) {
return HELPER.valueOfOrNull(name);
}
}
(Plus, I'd recommend that over catching the exception anyway.)
I realize "you can't do it" is not really a desirable answer but I don't see a way around it due to the static aspect.
The case is the same as you can not create default toString() in interface. The enum already contains signature for static valueOf(String) method therefore you can not override it.
The enum are compile time constant and because of that it really doubtful that they will be extensible someday.
If you want to get the constant via name you can use this:
public static <E extends Enum<E>> Optional<E> valueFor(Class<E> type, String name) {
return Arrays.stream(type.getEnumConstants()).filter( x -> x.name().equals(name)).findFirst();
}
I think I have an answer - it's hacky and uses reflection but seems to fit the brief - i.e. reverse lookup without methods in the enum and without throwing exception.
public interface HasName {
public String name();
}
public interface PoliteEnum extends HasName {
default String politeName() {
return name().replace("_", " ");
}
}
public interface Lookup<P, Q> {
public Q lookup(P p);
}
public interface ReverseLookup<T extends Enum<T>> extends Lookup<String, T> {
#Override
default T lookup(String s) {
return (T) useMap(this, s);
}
}
// Probably do somethiong better than this in the final version.
static final Map<String, Enum> theMap = new HashMap<>();
static Enum useMap(Object o, String s) {
if (theMap.isEmpty()) {
try {
// Yukk!!
Enum it = (Enum)o;
Class c = it.getDeclaringClass();
// Reflect to call the static method.
Method method = c.getMethod("values");
// Yukk!!
Enum[] enums = (Enum[])method.invoke(null);
// Walk the enums.
for ( Enum e : enums) {
theMap.put(e.name(), e);
}
} catch (Exception ex) {
// Ewwww
}
}
return theMap.get(s);
}
public enum X implements PoliteEnum, ReverseLookup<X> {
A_For_Ism,
B_For_Mutton,
C_Forth_Highlanders;
}
public void test() {
for (X x : X.values()) {
System.out.println(x.politeName());
}
for (X x : X.values()) {
System.out.println(x.lookup(x.name()));
}
}
prints
A For Ism
B For Mutton
C Forth Highlanders
A_For_Ism
B_For_Mutton
C_Forth_Highlanders
Added
Inspired by #Holger - this is what I feel is most like what I was looking for:
public interface ReverseLookup<E extends Enum<E>> extends Lookup<String, E> {
// Map of all classes that have lookups.
Map<Class, Map<String, Enum>> lookups = new ConcurrentHashMap<>();
// What I need from the Enum.
Class<E> getDeclaringClass();
#Override
default E lookup(String name) throws InterruptedException, ExecutionException {
// What class.
Class<E> c = getDeclaringClass();
// Get the map.
final Map<String, Enum> lookup = lookups.computeIfAbsent(c,
k -> Stream.of(c.getEnumConstants())
// Roll each enum into the lookup.
.collect(Collectors.toMap(Enum::name, Function.identity())));
// Look it up.
return c.cast(lookup.get(name));
}
}
// Use the above interfaces to add to the enum.
public enum X implements PoliteName, ReverseLookup<X> {
A_For_Ism,
B_For_Mutton,
C_Forth_Highlanders;
}
I don't understand how I can retrieve the Enum values in an annotation processor.
My annotation is a custom Java Bean Validation annotation:
#StringEnumeration(enumClass = UserCivility.class)
private String civility;
On my annotation processor, I can access to instances of these:
javax.lang.model.element.AnnotationValue
javax.lang.model.type.TypeMirror
javax.lang.model.element.TypeElement
I know it contains the data about my enum since I can see that in debug mode. I also see ElementKind == Enum
But I want to get all the names for that Enum, can someone help me please.
Edit: I don't have access to the Class object of this Enum, because we are in an annotation processor, and not in standart Java reflection code. So I can't call Class#getEnumConstants() or EnumSet.allOf(MyEnum.class) unless you tell me how I can get the Class object from the types mentioned above.
I found a solution (this uses Guava):
class ElementKindPredicate<T extends Element> implements Predicate<T> {
private final ElementKind kind;
public ElementKindPredicate(ElementKind kind) {
Preconditions.checkArgument(kind != null);
this.kind = kind;
}
#Override
public boolean apply(T input) {
return input.getKind().equals(kind);
}
}
private static final ElementKindPredicate ENUM_VALUE_PREDICATE = new ElementKindPredicate(ElementKind.ENUM_CONSTANT);
public static List<String> getEnumValues(TypeElement enumTypeElement) {
Preconditions.checkArgument(enumTypeElement.getKind() == ElementKind.ENUM);
return FluentIterable.from(enumTypeElement.getEnclosedElements())
.filter(ENUM_VALUE_PREDICATE)
.transform(Functions.toStringFunction())
.toList();
}
The answer given by Sebastian is correct, but if you're using Java 8 or above, you can use the following (cleaner) approach than using Google Guava.
List<String> getEnumValues(TypeElement enumTypeElement) {
return enumTypeElement.getEnclosedElements().stream()
.filter(element -> element.getKind().equals(ElementKind.ENUM_CONSTANT))
.map(Object::toString)
.collect(Collectors.toList());
}
Here's a complete example. Note the use of getEnumConstants on the enum values.
public class Annotate {
public enum MyValues {
One, Two, Three
};
#Retention(RetentionPolicy.RUNTIME)
public #interface StringEnumeration {
MyValues enumClass();
}
#StringEnumeration(enumClass = MyValues.Three)
public static String testString = "foo";
public static void main(String[] args) throws Exception {
Class<Annotate> a = Annotate.class;
Field f = a.getField("testString");
StringEnumeration se = f.getAnnotation(StringEnumeration.class);
if (se != null) {
System.out.println(se.enumClass());
for( Object o : se.enumClass().getClass().getEnumConstants() ) {
System.out.println(o);
}
}
}
}
This will print out:
Three
One
Two
Three
I was reading an article linked from a slashdot story, and came across this little tidbit:
Take the latest version of Java, which
tries to make null-pointer checking
easier by offering shorthand syntax
for the endless pointer testing. Just
adding a question mark to each method
invocation automatically includes a
test for null pointers, replacing a
rat's nest of if-then statements, such
as:
public String getPostcode(Person person) {
String ans= null;
if (person != null) {
Name nm= person.getName();
if (nm!= null) {
ans= nm.getPostcode();
}
}
return ans
}
With this:
public String getFirstName(Person person) {
return person?.getName()?.getGivenName();
}
I've scoured the internet (okay, I spent at least 15 minutes googling variations on "java question mark") and got nothing. So, my question: is there any official documentation on this? I found that C# has a similar operator (the "??" operator), but I'd like to get the documentation for the language I'm working in. Or, is this just a use of the ternary operator that I've never seen before.
Thanks!
EDIT: Link to the article: http://infoworld.com/d/developer-world/12-programming-mistakes-avoid-292
The original idea comes from groovy. It was proposed for Java 7 as part of Project Coin: https://wiki.openjdk.java.net/display/Coin/2009+Proposals+TOC (Elvis and Other Null-Safe Operators), but hasn't been accepted yet.
The related Elvis operator ?: was proposed to make x ?: y shorthand for x != null ? x : y, especially useful when x is a complex expression.
This syntax does not exist in Java, nor is it slated to be included in any of the upcoming versions that I know of.
[EDIT]
Upon further thought, I figured out that it is actually possible to achieve the same only using standard Java 8 classes:
public String getFirstName(Person person) {
return Optional.ofNullable(person)
.map(Person::getName)
.map(Name::getGivenName)
.orElse(null);
}
In this case, it is even possible to choose a default value (like "<no first name>") instead of null by passing it as parameter of orElse.
[Original Answer]
One way to workaround the lack of "?" operator using Java 8 without the overhead of try-catch (which could also hide a NullPointerException originated elsewhere, as mentioned) is to create a class to "pipe" methods in a Java-8-Stream style.
public class Pipe<T> {
private T object;
private Pipe(T t) {
object = t;
}
public static<T> Pipe<T> of(T t) {
return new Pipe<>(t);
}
public <S> Pipe<S> after(Function<? super T, ? extends S> plumber) {
return new Pipe<>(object == null ? null : plumber.apply(object));
}
public T get() {
return object;
}
public T orElse(T other) {
return object == null ? other : object;
}
}
Then, the given example would become:
public String getFirstName(Person person) {
return Pipe.of(person)
.after(Person::getName)
.after(Name::getGivenName)
.get();
}
Java does not have the exact syntax but as of JDK-8, we have the Optional API with various methods at our disposal. So, the C# version with the use of null conditional operator:
return person?.getName()?.getGivenName();
can be written as follows in Java with the Optional API:
return Optional.ofNullable(person)
.map(e -> e.getName())
.map(e -> e.getGivenName())
.orElse(null);
if any of person, getName or getGivenName is null then null is returned.
There was a proposal for it in Java 7, but it was rejected:
http://tech.puredanger.com/java7/#null
See: https://blogs.oracle.com/darcy/project-coin:-the-final-five-or-so (specifically "Elvis and other null safe operators").
The result is that this feature was considered for Java 7, but was not included.
That's actually Groovy's safe-dereference operator. You can't use it in pure Java (sadly), so that post is simply wrong (or more likely slightly misleading, if it's claiming Groovy to be the "latest version of Java").
As lot of answers mentioned Java language don't have this feature.
It is possible in few scenarios with this compiler plugin, with few limitations
In the example code you mentioned can be written as
public String getFirstName(Person person) {
#NullSafe
String retVal = person.getName().getGivenName();
return retVal;
}
PS: I am author of plugin
It is possible to define util methods which solves this in an almost pretty way with Java 8 lambda.
This is a variation of H-MANs solution but it uses overloaded methods with multiple arguments to handle multiple steps instead of catching NullPointerException.
Even if I think this solution is kind of cool I think I prefer Helder Pereira's seconds one since that doesn't require any util methods.
void example() {
Entry entry = new Entry();
// This is the same as H-MANs solution
Person person = getNullsafe(entry, e -> e.getPerson());
// Get object in several steps
String givenName = getNullsafe(entry, e -> e.getPerson(), p -> p.getName(), n -> n.getGivenName());
// Call void methods
doNullsafe(entry, e -> e.getPerson(), p -> p.getName(), n -> n.nameIt());
}
/** Return result of call to f1 with o1 if it is non-null, otherwise return null. */
public static <R, T1> R getNullsafe(T1 o1, Function<T1, R> f1) {
if (o1 != null) return f1.apply(o1);
return null;
}
public static <R, T0, T1> R getNullsafe(T0 o0, Function<T0, T1> f1, Function<T1, R> f2) {
return getNullsafe(getNullsafe(o0, f1), f2);
}
public static <R, T0, T1, T2> R getNullsafe(T0 o0, Function<T0, T1> f1, Function<T1, T2> f2, Function<T2, R> f3) {
return getNullsafe(getNullsafe(o0, f1, f2), f3);
}
/** Call consumer f1 with o1 if it is non-null, otherwise do nothing. */
public static <T1> void doNullsafe(T1 o1, Consumer<T1> f1) {
if (o1 != null) f1.accept(o1);
}
public static <T0, T1> void doNullsafe(T0 o0, Function<T0, T1> f1, Consumer<T1> f2) {
doNullsafe(getNullsafe(o0, f1), f2);
}
public static <T0, T1, T2> void doNullsafe(T0 o0, Function<T0, T1> f1, Function<T1, T2> f2, Consumer<T2> f3) {
doNullsafe(getNullsafe(o0, f1, f2), f3);
}
class Entry {
Person getPerson() { return null; }
}
class Person {
Name getName() { return null; }
}
class Name {
void nameIt() {}
String getGivenName() { return null; }
}
I'm not sure this would even work; if, say, the person reference was null, what would the runtime replace it with? A new Person? That would require the Person to have some default initialization that you'd expect in this case. You may avoid null reference exceptions but you'd still get unpredictable behavior if you didn't plan for these types of setups.
The ?? operator in C# might be best termed the "coalesce" operator; you can chain several expressions and it will return the first that isn't null. Unfortunately, Java doesn't have it. I think the best you could do is use the ternary operator to perform null checks and evaluate an alternative to the entire expression if any member in the chain is null:
return person == null ? ""
: person.getName() == null ? ""
: person.getName().getGivenName();
You could also use try-catch:
try
{
return person.getName().getGivenName();
}
catch(NullReferenceException)
{
return "";
}
There you have it, null-safe invocation in Java 8:
public void someMethod() {
String userName = nullIfAbsent(new Order(), t -> t.getAccount().getUser()
.getName());
}
static <T, R> R nullIfAbsent(T t, Function<T, R> funct) {
try {
return funct.apply(t);
} catch (NullPointerException e) {
return null;
}
}
If someone is looking for an alternative for old java versions, you can try this one I wrote:
/**
* Strong typed Lambda to return NULL or DEFAULT VALUES instead of runtime errors.
* if you override the defaultValue method, if the execution result was null it will be used in place
*
*
* Sample:
*
* It won't throw a NullPointerException but null.
* <pre>
* {#code
* new RuntimeExceptionHandlerLambda<String> () {
* #Override
* public String evaluate() {
* String x = null;
* return x.trim();
* }
* }.get();
* }
* <pre>
*
*
* #author Robson_Farias
*
*/
public abstract class RuntimeExceptionHandlerLambda<T> {
private T result;
private RuntimeException exception;
public abstract T evaluate();
public RuntimeException getException() {
return exception;
}
public boolean hasException() {
return exception != null;
}
public T defaultValue() {
return result;
}
public T get() {
try {
result = evaluate();
} catch (RuntimeException runtimeException) {
exception = runtimeException;
}
return result == null ? defaultValue() : result;
}
}
You can test the code which you have provided and it will give syntax error.So, it is not supported in Java.
Groovy does support it and it was proposed for Java 7 (but never got included).
However, you can use the Optional provided in Java 8. This might help you in achieving something on similar line.
https://docs.oracle.com/javase/8/docs/api/java/util/Optional.html
http://www.oracle.com/technetwork/articles/java/java8-optional-2175753.html
Example Code for Optional
STEP-1 : Use this generic method.
public static <T> Optional<T> optionalChaining(Supplier<T> resolver) {
try {
T result = resolver.get();
return Optional.ofNullable(result);
} catch (NullPointerException e) {
return Optional.empty();
}
}
STEP-2 one example of usage of this method is below
Optional<String> rs = optionalChaining(()-> user.getName("Talha").getLastName());
if(rs.isPresent()) {
}
Done !!
Since Android does not support Lambda Functions unless your installed OS is >= 24, we need to use reflection.
// Example using doIt function with sample classes
public void Test() {
testEntry(new Entry(null));
testEntry(new Entry(new Person(new Name("Bob"))));
}
static void testEntry(Entry entry) {
doIt(doIt(doIt(entry, "getPerson"), "getName"), "getName");
}
// Helper to safely execute function
public static <T,R> R doIt(T obj, String methodName) {
try {
if (obj != null)
return (R)obj.getClass().getDeclaredMethod(methodName).invoke(obj);
} catch (Exception ignore) {
}
return null;
}
// Sample test classes
static class Entry {
Person person;
Entry(Person person) { this.person = person; }
Person getPerson() { return person; }
}
static class Person {
Name name;
Person(Name name) { this.name = name; }
Name getName() { return name; }
}
static class Name {
String name;
Name(String name) { this.name = name; }
String getName() {
System.out.print(" Name:" + name + " ");
return name;
}
}
}
If this is not a performance issue for you, you can write
public String getFirstName(Person person) {
try {
return person.getName().getGivenName();
} catch (NullPointerException ignored) {
return null;
}
}