Lati negativi della riflessione in generale
La riflessione è più difficile da comprendere rispetto al codice lineare.
Nella mia esperienza, la riflessione è una funzionalità di "livello esperto" in Java. Direi che la maggior parte dei programmatori non usa mai la riflessione in modo attivo (cioè il consumo di librerie che usano la riflessione non conta). Ciò rende il codice che lo utilizza più difficile da comprendere per questi programmatori.
Il codice di riflessione non è accessibile all'analisi statica
Supponiamo di avere un getter getFoo
nella mia classe e che voglio rinominarlo getBar
. Se non uso alcuna riflessione, posso semplicemente cercare nella base di codice getFoo
e trovare ogni posto che utilizza il getter in modo da poterlo aggiornare, e anche se mi manca uno, il compilatore si lamenterà.
Ma se il posto che utilizza il getter è qualcosa di simile callGetter("Foo")
e lo callGetter
fa getClass().getMethod("get"+name).invoke(this)
, allora il metodo sopra non lo troverà e il compilatore non si lamenterà. Solo quando il codice viene effettivamente eseguito otterrai un NoSuchMethodException
. E immagina il dolore che provi se quell'eccezione (che viene tracciata) viene inghiottita callGetter
perché "viene utilizzata solo con stringhe codificate, non può effettivamente accadere". (Nessuno lo farebbe, qualcuno potrebbe obiettare? Tranne il fatto che l'OP ha fatto esattamente questo nella sua risposta SO. Se il campo viene rinominato, gli utenti del setter generico non se ne accorgerebbero mai, fatta eccezione per l'insetto estremamente oscuro del setter che non fa nulla in silenzio. Gli utenti del getter potrebbero, se sono fortunati, notare l'output della console dell'eccezione ignorata.)
Il codice di riflessione non viene verificato dal compilatore
Questo è fondamentalmente un grande sotto-punto di quanto sopra. Il codice di riflessione è tutto Object
. I tipi sono controllati in fase di esecuzione. Gli errori vengono rilevati dai test unitari, ma solo se si dispone di copertura. ("È solo un getter, non ho bisogno di provarlo.") Fondamentalmente, perdi il vantaggio usando Java su Python che ti ha guadagnato in primo luogo.
Il codice di riflessione non è disponibile per l'ottimizzazione
Forse non in teoria, ma in pratica, non troverai una JVM che incorpora o crea una cache inline per Method.invoke
. Chiamate di metodo normali sono disponibili per tali ottimizzazioni. Questo li rende molto più veloci.
Il codice di riflessione è solo lento in generale
La ricerca del metodo dinamico e il controllo del tipo necessari per il codice di riflessione sono più lenti delle normali chiamate di metodo. Se trasformi quel getter economico di una riga in una bestia riflesso, potresti (non l'ho misurato) guardando diversi ordini di grandezza di rallentamento.
Aspetto negativo del getter / setter generico in particolare
Questa è solo una cattiva idea, perché la tua classe ora non ha più incapsulamento. Ogni campo che ha è accessibile. Potresti anche renderli tutti pubblici.