2015-09-09 16 views
8

C'è un modo per accedere a uno specifico Field su una classe senza utilizzare la riflessione?Accesso alla classe 'Campi senza usare la riflessione?

Considerate questa classe:

class MyType { 
    public int theNumber; 
} 

Dove vorrei per avere accesso a theNumber s' java.lang.reflect.Field.

questo funziona di sicuro:

Field f = MyType.class.getDeclaredField("theNumber"); 

Tuttavia, vorrei compilare controllo sul nome del campo, così idealmente qualcosa di simile, invece (ma naturalmente il mio esempio non può essere compilato):

Field f = MyType.class::theNumber; 

È possibile o sono in grado di risolvere le abilità del compilatore?

+0

provo a sentire il tuo sfondo, la motivazione (?) Alla domanda. Provo a risolvere un'idea simile (o inversa) http://stackoverflow.com/questions/32284675/retrieve-information-from-jpa-metamodel Ci scusiamo per "pubblicità nascosta" :) –

risposta

1

È possibile estendere il compilatore java con i processori di annotazione. Questi processori sono un modo per scansionare il codice sorgente durante la compilazione. Sono stati introdotti con Annotations ma sono in grado di analizzare l'intero codice sorgente non solo le annotazioni.

Con il codice sorgente scansionato è possibile generare classi di accesso a qualsiasi classe compilata. In questo modo puoi eliminare la riflessione.

Se si desidera ottenere errori mentre si scrive codice nell'IDE, è possibile utilizzare javax.annotation.processing.ProcessingEnvironment.getMessager(). PrintMessage() (vedere anche javax.tools.DiagnosticListener) per generare errori l'IDE può mostrare.

Così l'idea di base è:

  1. scrivere un processore di annotazione che analizza il codice sorgente che si desidera riflettere
  2. estrarre il campo che si desidera avere accesso a via javax.lang.model.element. ElementVisitor

Nel caso in cui si desidera generare il tipo salvare l'accesso al campo:

3.1. generare fonte che accederà questo codice sorgente

Nel caso in cui si vuole garantire, che una chiamata di riflessione a un campo è valida:

3.2. genera un errore tramite ProcessingEnvironment.getMessager().printMessage()

Ovviamente è necessario scrivere il codice per verificare le chiamate riflesse o generare gli accessor.

E le informazioni che si desidera ottenere deve essere estraibile dal codice sorgente poiché tutta la magia accade durante la compilazione e non in fase di esecuzione

+0

Wow, ho imparato qualcosa di nuovo lì, non conoscevo i processori di annotazione. Lo controllerò sicuramente! – Geir

2

Interessante domanda. No, non c'è modo di farlo senza usare java.lang.reflect, ma data la pseudo-proprietà class integrata sulle classi, posso capire perché lo chiedi.

+0

Pensato così. In questo momento sto usando un enum con valori che equivalgono ai nomi dei campi nella classe. Speravo di liberarmene, dal momento che ogni nome di campo è ripetuto nell'enum. – Geir

-1

No, non è ... ma si potrebbe ottenere con un'interfaccia e una chiusura

public interface Getter<T, V> { 
    V get(T object); 
} 

public static Getter<MyType, Integer> theNumberGetter = (MyType myType) -> { myType.theNumber }; 
+0

Che non accede a 'Field', accede al * valore * del campo in una determinata istanza. –

+0

Capito ... ma suppongo che voglia solo il 'Field' in modo che possa accedere ai valori più tardi –

+0

Bene, per fare ciò, semplicemente' myTypeInstance.theNumber' sembra il modo più diretto, se si conosce il nome del campo in fase di compilazione. –

0

JPA2 Metamodel (usato in typesafe query "di criteri") ha concetto simile.

MyType_.theNumber 

è attuato da "pre-processori" in più. Puoi investigare in quest'area.

Problemi correlati