2017-03-26 3 views
2

Als Teil beliebiger Referenzmethoden:Java 8 Methodenreferenzen

Warum ist das erlaubt?

Predicate<String> p1 = String::isEmpty; 

Und warum ist das nicht erlaubt?

BiConsumer<HashMap<String,Integer>, Integer> b1 = HashMap<String,Integer>::put; 
+0

Meinst du _now_ oder _not_? –

+0

Verstanden, weil im obigen Fall die Argumente für Put nicht abgeleitet werden können.Dies funktioniert BiConsumer , Integer> b1 = HashSet :: add; –

Antwort

1

In Ihrem ersten Beispiel, sie ist ein Predicate zu schaffen, die als eine Eingabe einen String nimmt. Dies entspricht String.isEmpty(), die keine Argumente annimmt. Das Prädikat wirkt nur auf die String-Instanz.

Wie für das zweite Beispiel, lassen Sie uns die put Methode untersuchen:

public V put(K key, V value) 

Da Sie eine HashMap<String, Integer> verwenden, diese

public Integer put(String key, Integer value) 

würde Wie Sie sehen können, das Verfahren selbst ist erwartet zwei Argumente. Da Sie dies als eine Methodenreferenz übergeben möchten, benötigt es zusätzlich zu den zwei Argumenten die HashMap<String, Integer>.

BiConsumer<HashMap<String, Integer>, Integer> b1 = HashMap<String, Integer>::put; 

Hierher, haben Sie markiert korrekt das erste generische Typargument als HashMap<String, Integer>, aber Sie fehlen das String Argument, das die put Methode benötigt. Leider gibt es keine TriConsumer, aber Sie können Ihre eigene Schnittstelle für sie leicht definieren:

@FunctionalInterface 
public interface TriConsumer<T, U, V> { 
    void accept(T t, U u, V v); 
} 

Die @FunctionalInterface Anmerkung ist nicht erforderlich, aber es steht die Absicht, den Leser, dass diese Schnittstelle als Zuweisungsziel verwendet werden kann, für einen Lambda-Ausdruck oder eine Methodenreferenz.

Jetzt können Sie den Verweis auf put zuweisen:

TriConsumer<HashMap<String, Integer>, String, Integer> consumer = HashMap<String, Integer>::put; 

HashMap<String, Integer> map = new HashMap<>(); 
consumer.accept(map, "Key", 123); 
System.out.println(map.get("Key")); // prints 123 
+1

Danke für die Erklärung so schön! –

+0

@ VijayNarayanan Ich bin froh, dass ich helfen konnte! Schauen Sie sich auch die Antwort von Bohemian an, sein Beispiel zeigt, wie Sie eine Referenz auf eine Methode eines * bestimmten * Objekts zuweisen können. – cubrr

1

Das grundlegende Problem ist, dass put() ist kein Methode getippt - eine, wo der Typ Methode Umfang hat und geschlossen werden kann, ist es eine generische Instanz Methode - eine, die ihren Typ vom Typ der Instanz nimmt.

Außerdem stimmen Sie nicht mit dem Typ der Methodenreferenz und ihren generischen Parametern überein. Ich habe angenommen, du meinst BiFunction, nicht BiConsumer.

die bei Let schauen, was tut Arbeit:

HashMap<String, Integer> instance = new HashMap<>(); 
BiFunction<String, Integer, Integer> b1 = instance::put; 

Wenn Sie wirklich BiConsumer gemeint, das funktioniert auch:

BiConsumer<String, Integer> b1 = instance::put; 

Wie ich gesagt habe, weil die Methode von seiner Art nimmt die Instanz, also benötigen Sie eine typisierte Instanz.

+0

Vielen Dank für Ihre Erklärung! –