2015-08-23 15 views
6

In java, è possibile aggiungere i parametri Tipo ai metodi statici, per creare metodi che gestiscono i generici. Puoi fare lo stesso con lambda?Creazione di lambda generici in Java

Nel mio codice che ho

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

che sto cercando di fare parametri di tipo come se fosse una funzione, ma non me lo permette.

E se lo faccio:

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

Non accetta l'argomento dove cerco di usarlo. Cosa posso fare?

+1

che non può essere una variabile. In realtà, è inutile dichiarare una variabile come "WhateverClassThatSupportsGenerics var = ...;" a meno che non si tratti di un parametro di un metodo. –

+0

Dove provate ad usare la seconda dichiarazione? (Il primo, come probabilmente hai scoperto, non è sintatticamente valido). – Makoto

+1

Non è possibile costruire un oggetto generico limitato. La tua linea di codice fallisce per lo stesso motivo: "nuova HashMap >" è legale, ma "new HashMap >" non lo è. '?' significa "Non so che tipo usi HashMap", ma quando crei una HashMap, sai sempre cosa intendi inserire (anche se decidi che è java.lang.Object). – VGR

risposta

8

Una soluzione per questo può essere quella di avvolgere il metodo di riferimento in un metodo, in modo che tipo di destinazione detrazione risolve il tipo di chiamata sul sito:

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

Penso che sia necessario un cast su 'HashMap :: new' che è' Mappa '(o' Mappa ') ma non' Mappa > '). Guarda come viene implementato 'Collections.emptyList()'. – NoDataFound

+1

@NoDataFound Non sei sicuro di cosa intendi, ma qui, non è richiesto alcun cast (anche se un cast brutale potrebbe essere al sicuro anche in questo caso, dato che tutti i parametri di tipo diventano comunque in "Object" quando vengono compilati ...) – Marco13

+0

@ NoDataFound: la lista restituita da 'Collections.emptyList()' è immutabile e quindi è possibile restituire sempre lo stesso oggetto e semplicemente lanciarlo. In questo caso, tuttavia, ottieni sempre un nuovo 'HashMap' e usando' HashMap :: new' il compilatore può inferire automaticamente i parametri generici corretti. Tuttavia, sarebbe sempre possibile trasmettere e restituire il campo statico. Ma il casting in questo caso è un po 'scomodo: è necessario utilizzare '(Fornitore >>) (Fornitore ) fornitore'. E produce avvertimenti sui cast non controllati e le prestazioni di solito non fanno differenza. – siegi