2013-06-17 21 views
8

Le questioni di carattere generale sono:Come eseguire indirettamente un riferimento al metodo in Java 8?

  • Quando si utilizza la sintassi object::aMethod, può essere convertito in un tipo come ad esempio MethodHandle un'interfaccia funzionale?
  • Se no, come può un riferimento al metodo essere invocato indirettamente in Java 8 se possibile?

Per fare un esempio, immaginiamo ci piacerebbe avere un MethodRefRunner come:

class MethodRefRunner { 
    static void execute(Object target, WHATTYPE mref, Object... args) { 
    mref.apply(args); 
    } 
} 

E può essere usato come: MethodRefRunner.execute(o, o::someMethod, someParam)

In questo frammento di codice, un'opzione per WHATTYPE è java.util.function.Function ma molto restrittivo. Come menzioni this answer, prima della versione b75, c'era uno java.util.function.Block disponibile e potrebbe essere utile.

Dall'altro lato, nessuna possibilità che WHATTYPE possa essere in qualche modo convertita in java.lang.invoke.MethodHandle?

Nota agli esperti di Java: Si prega di rifinire il titolo delle domande secondo necessità.

+1

In Scala, è possibile forzare un * metodo * in un valore * funzione *, questa è l'espansione * eta * (c'è una differenza tra * metodo * e * funzione * in Scala). Per quanto riguarda il caso che descrivi, il compilatore Scala è abbastanza intelligente da accettarli entrambi. – Beryllium

+0

@Beryllium In effetti un bel contrasto e questo è anche il motivo per cui mi chiedevo il motivo per cui Java 8 non ha optato per questo. – nobeh

+2

@nobeh Java 8 si attacca alle interfacce funzionali perché l'aggiunta di tipi di funzione avrebbe comportato modifiche molto più grandi del linguaggio. Potrebbero venire più tardi. –

risposta

8

Non credo che ci sia un modo per fare ciò che vuoi. WHATTYPE dovrà essere un'interfaccia funzionale — non necessariamente Function, ma uno il cui singolo metodo astratto corrisponde a somemethod. È un tipo di interfaccia ordinario, soggetto alle solite regole che regolano i tipi di Java. java.util.function.Block era un tipo di interfaccia ordinaria come questa, e non speciale nel modo in cui tu sembri pensare. (È ancora intorno, a proposito, ora chiamato Consumer.)

+0

Grazie per la risposta. Ora, la domanda è: esiste un modo per convertire un riferimento al metodo (o un'espressione lambda) in un 'MethodHandle' in runtime in modo tale che possa essere invocato? – nobeh

+1

Scusa, penso che la risposta sia ancora no. Il motivo (AFAIK) è che qualsiasi modo per farlo dovrebbe avere un punto di partenza fisso nella forma di una particolare implementazione lambda. Ma l'intenzione non è di limitare l'implementazione - il runtime può scegliere "classi interne dinamiche, classi wrapper attorno a handle di metodo, proxy dinamici, proxy di gestione del metodo o altri meccanismi ancora sconosciuti". (Http://mail.openjdk.java.net/pipermail/lambda-dev/2011-November/004224.html). Quindi, se c'è effettivamente un modo per fare ciò che vuoi, sarà sempre dipendente dalla VM. –

+0

Ho trovato una discussione dal novembre 2012, ma non è chiaro se questo sia andato ovunque: http://mail.openjdk.java.net/pipermail/lambda-spec-experts/2012-December/000159.html – Gili

5

Un metodo di riferimento funziona proprio come un lambda, e come un lambda, non ha un "tipo" da solo. Il suo tipo dipende dal contesto in cui viene utilizzato. Quindi la tua domanda non ha molto senso. Se si utilizza il riferimento al metodo in una chiamata a questo metodo MethodRefRunner.execute(), il tipo del metodo di riferimento sarà un'istanza di WHATTYPE (qualsiasi cosa sia), perché è quello che il metodo è stato dichiarato di accettare. Se l'hai preso da qualche altra parte, beh, quel posto saprà di che tipo si tratta.

Problemi correlati