2015-06-06 14 views
24

Con il rilascio di Java 7 è stato fornito il MethodHandle, che consente a un utente di richiamare un metodo come se utilizzasse il suo bytecode sottostante. In particolare, la classe MethodHandles.Lookup fornisce metodi factory per creare il metodo maniglie per accedere ai membri della classe:Perché utilizzare reflection per accedere ai membri della classe quando MethodHandle è più veloce?

I metodi di fabbrica su un oggetto di ricerca corrispondono a tutti i principali casi di utilizzo per metodi, costruttori, e campi. Ogni handle di metodo creato da un metodo factory è l'equivalente funzionale di un particolare comportamento bytecode.

Funzionalmente, questo è più o meno equivalente all'utilizzo della riflessione per accedere a questi stessi membri della classe, tuttavia method handles are faster than reflection.

Quindi, c'è qualche motivo per utilizzare ancora le funzionalità di riflessione come Field#get(..)/Method.invoke(..) o questi metodi sono effettivamente obsoleti con l'introduzione degli handle di metodo più veloci?

Nota che, mentre le maniglie di metodo sono stati introdotti in Java 7, la mia domanda si riferisce principalmente a Java 8, in cui sono stati ottimizzati per presunto raggiungere prestazioni pari a circa chiamate di campo/metodo diretto, superando la capacità di riflessione.

+0

Per ulteriori dettagli sui manici del metodo, vedere [MethodHandle - Di cosa si tratta?] (Http: // stackoverflow.it/q/8823793/1247781) – Vulcan

+0

Non sembra molto più veloce, soprattutto se si disattiva il controllo dell'accesso in reflection ('setAccessible (true)') – ZhongYu

+0

@ bayou.io Sembra ragionevole, ma avete qualche test di benchmark come prova? La semplice modifica del benchmark nella domanda collegata per chiamare 'setAccessible (true)' e l'output di quei risultati sarebbe una prova sufficiente per me. – Vulcan

risposta

22

Le maniglie di riflessione e metodo hanno scopi diversi e esistono a diversi livelli di astrazione. Dovresti usare quello giusto per il problema che stai risolvendo.

riflessione è un meccanismo introspezione generico, che comprende molte caratteristiche che il meccanismo metodo maniglia manca, ad esempio l'enumerazione i membri di una classe (Class.getMethods()), ispezionare le caratteristiche di un elemento come suoi flag di accessibilità, ispezionando generico firme dei membri, ecc.

Inoltre, gli oggetti riflettenti possono essere condivisi liberamente senza concedere l'accesso allo sharee, poiché i controlli di accesso vengono effettuati ad ogni invocazione; le maniglie del metodo conferiscono a sharee la capacità di invocare. Quindi hanno anche diverse implicazioni sulla sicurezza.

Gli handle di metodo sono un meccanismo di basso livello per la ricerca, l'adattamento e il richiamo di metodi. Sebbene l'invocazione tramite il metodo handle sia più veloce che tramite reflection (anche se fino ad ora, la chiamata diretta del codice è ancora più veloce di quella del metodo), gli handle del metodo sono anche molto più difficili da utilizzare, poiché non eseguono automaticamente gli adattamenti che gli utenti Java si aspetterebbero (come convertire un argomento String in Object), causando errori di linkage.

La libreria di riflessione è destinata agli utenti Java tradizionali; il livello di handle del metodo è rivolto più a scrittori di runtime del linguaggio e del compilatore. Scegli lo strumento progettato per il lavoro.

+0

Sebbene questa risposta sia utile, la mia domanda riguarda solo l'uso di 'Field # get/set' e' Method # invoke' per accedere/invocare i membri della classe, e se c'è qualche ragione per usare ancora questi metodi di riflessioni quando il metodo gestisce fornire modi presumibilmente più veloci per ottenere lo stesso accesso/invocazione. – Vulcan

+10

Le prestazioni non sono l'unica misura di idoneità per un'attività. I manici del metodo sono più veloci, ma sono meno flessibili e più difficili da usare. Forse le maniglie del metodo sono lo strumento giusto per il tuo problema (non l'hai davvero spiegato), forse non lo sono. Ma la tua domanda era: "Perché usare la riflessione quando abbiamo maniglie del metodo". E ci sono molte ragioni per le quali potresti preferire la riflessione, oltre alle prestazioni di invocazione. –

5

tl; dr No. Si dovrebbe usare (e preferiscono) MethodHandles alla riflessione core API quando si può.

MethodHandles.Lookup access dice (in parte),

differenza con la riflessione core API, dove l'accesso è controllato ogni volta un metodo di riflessione viene richiamato, il controllo di accesso metodo maniglia viene eseguita when the method handle is created.

+0

@BrianGoetz Ti sei perso * la mia domanda riguarda principalmente le loro prestazioni in Java 8, in cui sono state ottimizzate per raggiungere le prestazioni approssimativamente uguali alle chiamate dirette campo/metodo *? –

+2

"prestazioni ** in Java 8 **", a differenza delle prestazioni in Java 7, non "principalmente ... prestazioni". – zeroflagL

Problemi correlati