2016-12-25 1 views
6

Aufgrund der umfangreichen Profilerstellung ist unser Java-Code mit Ausgaben von Methodenergebnissen von Nullable-Objekten überladen.Nullprüfmethode mit java8 Methodenreferenz möglich?

Es sieht aus wie diese

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

ist es möglich, eine statische Methode für diese zu schreiben? (z.B. so aussehen):

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

Wie würde = Util.nvl aussehen? Ich habe ein bisschen nach einem gesuchten Google experimentiert, aber habe kein Ergebnis erbracht.

funktioniert das nicht:

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

Der Compiler sagt mir: nicht-statische Methode getName() aus einem statischen Kontext kann Ihre Unterschrift nicht referenziert werden können

Antwort

8

nicht korrekt. Sie möchten, dass Ihre Methode das NamedObject als erstes Argument verwendet (also T ist ein NamedObject) und einen String zurückgibt (also jetzt T is String).

Sie benötigen zwei generische Typparameter:

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 
    } 
} 

Eine noch bessere Signatur, die mehr Flexibilität zulassen,

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

Hervorragende Antwort, vielen Dank! – Nachaz

+0

Es ist kein "nvl" -Operation, aber es ist eine "getOrDefault" -Operation. –

5

Ihre Methode des würde Generika nicht richtig definiert sind. Sie versuchen, eine Methode zu erstellen, die ein Objekt eines bestimmten Typs empfängt (T, aus Gründen des Arguments, oder NamedObject in dem angegebenen Beispiel) und wendet eine Methode an, die ein Objekt eines anderen Typs (S) zurückgibt oder String in dem gegebenen Beispiel), oder einen Standard S Wert, wenn das übergebene Objekt ist null:

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

Beachten Sie, dass Java 8er Optional können Sie erlauben, diese in einer elegantere Art und Weise zu schreiben (obwohl Eleganz etwas ist in das Auge des Betrachters):

public static <T, S> S nvl(T value, Function<T, S> method, S nullSubstition) { 
    return Optional.ofNullable(value).map(method).orElse(nullSubstition); 
} 
+1

Sie meinen 'Optional.ofNullable()' richtig? –

+1

@PatrickParker ja. Bin mir selbst voraus :-) Editiert und behoben, danke fürs merken! – Mureinik

+2

schönes Beispiel. vielleicht wäre ein guter Name für diese Funktion 'optionalMapOrElse', da es eine Abkürzung für diese Notation ist. –