2015-08-23 20 views
6

In Java können Sie statischen Methoden Typparameter hinzufügen, um Methoden zu erstellen, die mit Generika umgehen. Kannst du das gleiche mit Lambdas machen?Generische Lambdas in Java erstellen

In meinem Code ich habe

final private static <K,V> Supplier<Map<K, List<V>> supplier=HashMap::new; 

Ich versuche, Typ Parameter zu tun, wie es eine Funktion, aber es lässt mich nicht.

Und wenn ich tun:

final private static Supplier<Map<?, List<?>>> supplier=HashMap::new; 

Es ist nicht das Argument akzeptieren, wenn ich versuche, es zu benutzen. Was kann ich tun?

+1

Das ist nicht eine Variable sein kann. In der Tat ist es nutzlos, eine Variable wie 'WhateverClassThatSupportsGenerics var = ...; zu deklarieren, es sei denn, es ist ein Parameter einer Methode. –

+0

Wo versuchst du die zweite Deklaration zu verwenden? (Die erste, wie Sie wahrscheinlich entdeckt haben, ist syntaktisch ungültig.) – Makoto

+1

Es ist nicht möglich, ein beschränktes generisches Objekt zu konstruieren. Ihre Codezeile schlägt aus dem gleichen Grund fehl: "neue HashMap >" ist zulässig, aber 'neue HashMap >' ist nicht. "?" bedeutet "Ich weiß nicht, welchen Typ diese HashMap verwendet", aber wenn Sie eine HashMap erstellen, wissen Sie immer, was Sie hineinlegen wollen (selbst wenn Sie sich für java.lang.Object entscheiden). – VGR

Antwort

8

Eine Abhilfe für dieses sein kann, das Verfahren Bezug in ein Verfahren zu wickeln, so dass Zielart Abzug der Typ an der Aufrufstelle löst:

import java.util.HashMap; 
import java.util.List; 
import java.util.Map; 
import java.util.function.Supplier; 

public class GenericLambda 
{ 
    // Syntactically invalid 
    //final private static <K,V> Supplier<Map<K, List<V>> supplier=HashMap::new; 

    final private static Supplier<Map<?, List<?>>> supplier=HashMap::new; 

    // A workaround 
    private static <K,V> Supplier<Map<K, List<V>>> supplier() 
    { 
     return HashMap::new; 
    } 


    public static void main(String[] args) 
    { 
     // Does not work 
     //useSupplier(supplier); 

     // Works 
     useSupplier(supplier()); 
    } 

    private static <K, V> void useSupplier(Supplier<Map<K, List<V>>> s) 
    { 
     System.out.println(s.get()); 
    } 
} 
+0

Ich denke, Sie brauchen eine Umwandlung von 'HashMap :: new', die' Map '(oder' Map ') aber nicht' Karte > '). Sehen Sie, wie 'Collections.emptyList()' implementiert ist. – NoDataFound

+1

@NoDataFound Nicht sicher, was du meinst, aber hier ist keine Besetzung erforderlich (obwohl eine brutale Besetzung auch in diesem Fall sicher sein könnte, da alle Typparameter sowieso zu "Objekt" werden, wenn sie kompiliert werden ...) – Marco13

+0

@ NoDataFound: Die von 'Collections.emptyList()' zurückgegebene Liste ist unveränderlich, und daher ist es möglich, immer das gleiche Objekt zurückzugeben und es nur zu werfen. In diesem Fall erhalten Sie jedoch immer eine neue HashMap und mit Hilfe von HashMap :: new kann der Compiler die korrekten generischen Parameter automatisch ableiten. Trotzdem wäre es möglich, das statische Feld immer zu werfen und zurückzugeben. Aber Casting ist in diesem Fall ein wenig unbequem: Sie müssen '(Supplier >>) (Supplier ) Supplier' verwenden. Und es erzeugt Warnungen über unkontrollierte Umwandlungen und Leistung sollte normalerweise keinen Unterschied machen. – siegi