Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Generic "is null" predicate [duplicate]

I wrote this generic predicate:

private static <T> Predicate<T> isNull(){
    return Objects::isNull;
}

But I can't use it in combination with other predicates like this:

private static Predicate<String> isEmpty(){
    return string -> string.isEmpty();
}

Because this snippet will not compile (expects Predicate< String> in or operation):

isNull().or(isEmpty())

Any idea to solve it? Thanks!

like image 680
italktothewind Avatar asked Aug 22 '18 18:08

italktothewind


2 Answers

Since isNull() is generic, and the compiler cannot infer the generic parameter when combined like that, you need to explicitly specify the type parameter.

To do that, you must qualify with the class name, e.g. Test:

Test.<String>isNull().or(isEmpty())

Full example:

public class Test {
    public static void main(String[] args) {
        Predicate<String> isNullOrEmpty = Test.<String>isNull().or(isEmpty());
        System.out.println(isNullOrEmpty.test(null));   // true
        System.out.println(isNullOrEmpty.test(""));     // true
        System.out.println(isNullOrEmpty.test("Foo"));  // false
    }
    private static <T> Predicate<T> isNull(){
        return Objects::isNull;
    }
    private static Predicate<String> isEmpty(){
        return string -> string.isEmpty();
    }
}

You can also resolved it by assigning each part to a variable:

Predicate<String> isNull = isNull(); // String is inferred from assignment operator
Predicate<String> isEmpty = isEmpty();
Predicate<String> isNullOrEmpty = isNull.or(isEmpty);

Or just the first part:

Predicate<String> isNull = isNull();
Predicate<String> isNullOrEmpty = isNull.or(isEmpty());
like image 91
Andreas Avatar answered Oct 23 '22 05:10

Andreas


Well in our project we have a small work-around for this:

private static <T> Predicate<T> allOr(Predicate<T> ... predicates) {
    return Arrays.stream(predicates).reduce(Predicate::or).orElse(x -> true);
}

And using it with:

Predicate<String> both = allOr(isEmpty(), isNull());
like image 25
Eugene Avatar answered Oct 23 '22 04:10

Eugene