Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Nullcheck method using java8 method reference possible?

Due to rich profiling, our Java code is cluttered with outputs of method results of nullable objects.

It looks like this

namedObject == null ? "?" : namedObject.getName()

is it possible to write a static method for this? (e.g. looking like this):

Util.nvl( namedObject, NamedObject::getName, "?" )

What would = Util.nvl look like? I've experimented a bit an searched google but yielded no result.

This does not work:

public static <T> T nvl(T value, Function<T, ?> method, T nullSubstition) {
    return value == null ? nullSubstition : (T) method.apply(value);
}

The compiler tells me: non-static method getName() cannot be referenced from a static context

like image 665
Nachaz Avatar asked Dec 25 '16 14:12

Nachaz


People also ask

How do I avoid multiple nulls in Java 8?

Java 8 introduced an Optional class which is a nicer way to avoid NullPointerExceptions. You can use Optional to encapsulate the potential null values and pass or return it safely without worrying about the exception. Without Optional, when a method signature has return type of certain object.

Which method can be used to check null on an optional variable in Java 8?

Let's learn how to use Java 8's Optionals to make your null checks simple and less error-prone! The method orElse() is invoked with the condition "If X is null, populate X. Return X.", so that the default value can be set if the optional value is not present.

How do I check if a stream is null?

We can use lambda expression str -> str!= null inside stream filter() to filter out null values from a stream.

How do you check if a list is empty or null in Java 8?

The isEmpty() method of List interface in java is used to check if a list is empty or not. It returns true if the list contains no elements otherwise it returns false if the list contains any element.


2 Answers

Your signature can't be correct. You want your method to take the NamedObject as first argument (so T is a NamedObject), and to return a String (so now T is String).

You need two generic type parameters:

public class Utils {

    public static <O, T> T nvl(O value, Function<O, T> method, T nullSubstition) {
        return value == null ? nullSubstition : method.apply(value);
    }

    static class NamedObject {
        String getName() {
            return "foo";
        }
    }

    public static void main(String[] args) {
        NamedObject foo = null;
        String name = Utils.nvl(foo, NamedObject::getName, "bar");
        System.out.println("name = " + name); // name = bar

        foo = new NamedObject();
        name = Utils.nvl(foo, NamedObject::getName, "bar");
        System.out.println("name = " + name); // name = foo
    }
}

An even better signature, allowing more flexibility, would be

public static <O, T> T nvl(O value, Function<? super O, ? extends T> method, T nullSubstition) {
    return value == null ? nullSubstition : method.apply(value);
}
like image 122
JB Nizet Avatar answered Nov 15 '22 00:11

JB Nizet


Your method's generics aren't defined correctly. You're attempting to create a method that receives an object of a certain type (T, for argument's sake, or a NamedObject in the given example), and applies a method that returns an object of a different type (S, for argument's sake, or String in the given example), or a default S value if the passed object is null:

public static <T, S> S nvl(T value, Function<T, S> method, S nullSubstition) {
    return value == null ? nullSubstition : (S) method.apply(value);
}

Note that Java 8's Optional may allow you to write this in a more elegant way (although elegance is somewhat in the eye of the beholder):

public static <T, S> S nvl(T value, Function<T, S> method, S nullSubstition) {
    return Optional.ofNullable(value).map(method).orElse(nullSubstition);
}
like image 24
Mureinik Avatar answered Nov 14 '22 23:11

Mureinik