2015-05-15 15 views
7

Mi chiedo se sarebbe possibile generare una classe, tramite un processore di annotazioni, che sarebbe una classe interna di una classe da compilare.È possibile generare una classe interna di una classe da compilare con un processore di annotazioni?

Ad esempio, durante la compilazione della classe A, generare la classe A$Foo. Mi chiedo se ci sia un trucco che potrebbe essere usato o meno. Ho avuto la sensazione che potrebbe essere possibile generare una fonte che verrà compilata nello stesso codice byte di una classe interna. E, in fase di compilazione/runtime, la JVM la prenderebbe per una classe interna e consentirebbe l'accesso ai campi privati ​​della classe esterna.

L'idea alla base di questa domanda, che non è una questione obliqua, anche se può sembrare più o meno tecnica, è quella di essere in grado di utilizzare il modificatore di visibilità privato per campi annotati come Dagger, ButterKnife, ecc. per rilevare più facilmente i campi non utilizzati, mentre la protezione privata dei pacchetti li nasconde.

Oppure c'è qualche soluzione, un modo per ottenere il meglio da entrambe le parole?

+1

No. Non è possibile modificare i file sorgente esistenti, basta crearne di nuovi. Ma nomino sempre classi generate secondo questo schema, ad esempio 'SomeInterface $ Impl' per indicare che questa classe generata appartiene a' SomeInterface'. –

+1

Ma so esattamente cosa intendi, gioco molto con l'elaborazione delle annotazioni e lo uso molto nelle mie librerie, e vorrei solo che fosse possibile ... Normalmente tendo a generare classi di implementazione finali private e poi a generare un public factory class che crea istanze di tali interfacce con le classi di implementazione private. È possibile chiamare questa soluzione alternativa. –

risposta

-2

La visibilità privata è davvero solo un suggerimento per il compilatore. Non c'è alcun problema per accedere a tutti questi campi al runtime (come nel mio piccolo iniettore di dipendenze: https://github.com/ko5tik/andject)

E le classi interne non statiche su Android sono in genere una cattiva idea in quanto ha avuto penalità di prestazioni.

Al momento della compilazione è possibile utilizzare lo strumento di generazione di origine come xdoclet (sebbene sia diventato obsoleto tecnicamente anni fa, ma ancora occasionalmente utilizzato) e generare tutte le origini necessarie in anticipo prima di compilarle.

+2

Nella libreria a cui ci si collega si utilizza la riflessione per eseguire l'iniezione. Nella maggior parte dei casi questo è esattamente ciò che si desidera evitare quando si utilizza l'elaborazione delle annotazioni e la generazione del codice. E il codice che si genera deve essere un codice valido e il codice valido non può accedere ai campi privati. –

+1

La visibilità privata non è "* solo un suggerimento per il compilatore *". Nel caso predefinito è possibile accedere a campi privati ​​con riflessione, ma può essere disabilitato se il codice è in esecuzione in un contesto con un altro gestore della sicurezza. In questo caso 'Field.setAccessible' lancia' SecurityException'. – Lii

2

Dato il tuo caso d'uso, no.

Una classe interna è una normale classe Java, che vive in un diverso file .class. Una volta compilato, un parametro costruttore nascosto viene aggiunto al costruttore della classe interna. I campi privati ​​nella classe esterna sono resi accessibili aggiungendo metodi accessor nascosti nella classe esterna. Tutto questo accade in fase di compilazione.

La JVM non ha nulla a che fare con questo. Se generi una classe che "assomiglia ad una classe interiore di un'altra classe", ciò non renderà accessibili i campi della classe esterna.

+0

Questa è l'idea generale che ho della limitazione. In realtà aggiungere alcune discariche di javap -c delle classi interne ed esterne potrebbe aiutare a considerare questa risposta canonica. – Snicolas

+0

Inoltre, ciò vale solo per il compilatore javac, ecj AFAIK ha un meccanismo diverso per esprimere il collegamento tra classi esterne e interne. – Snicolas