Svantaggi della riflessione in generale
La riflessione è più difficile da capire rispetto al codice della linea retta.
Nella mia esperienza, la riflessione è una funzionalità "a livello di esperti" in Java. Direi che la maggior parte dei programmatori non usa mai la reflection attivamente (cioè le librerie che consumano che usano la reflection non contano). Questo rende il codice più difficile da capire per questi programmatori.
Il codice di riflessione non è accessibile all'analisi statica
Supponiamo di avere un getter getFoo
nella mia classe e voglio rinominarlo in getBar
. Se non utilizzo alcuna riflessione, posso solo cercare il codice base per getFoo
e troverò ogni posto che usa il getter in modo da poterlo aggiornare, e anche se ne manchi uno, il compilatore si lamenterà.
Ma se il posto che usa il getter è qualcosa come callGetter("Foo")
e 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 è effettivamente eseguito otterrai una NoSuchMethodException
. E immagina il dolore in cui ti trovi se quell'eccezione (che è tracciata) viene inghiottita da callGetter
perché "è usata solo con stringhe hard-coded, non può realmente accadere". (Nessuno lo farebbe, qualcuno potrebbe obiettare? Tranne che l'OP ha esattamente quello nella sua risposta SO. Se il campo viene rinominato, gli utenti del setter generico non lo noterebbero mai, tranne che per l'errore estremamente oscuro del setter che non fa nulla silenziosamente Gli utenti del getter potrebbero, se sono fortunati, notare l'output della console dell'eccezione ignorata.)
Il codice di riflessione non è controllato dal compilatore
Questo è fondamentalmente un grande sotto-punto di quanto sopra. Il codice di riflessione è tutto su 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 testarlo.") Fondamentalmente, hai perso 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 incorpori o crei una cache in linea per Method.invoke
. Le chiamate al metodo normale 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 necessario per il codice di riflessione sono più lenti delle normali chiamate di metodo. Se trasformi quella getter a una linea a buon mercato in una bestia da riflessione, potresti (non l'ho misurato) osservare diversi ordini di grandezza di rallentamento.
Lato negativo del getter / setter generico
specifico
Questa è solo una cattiva idea, perché la tua classe ora non ha più incapsulamento. Ogni campo è accessibile. Potresti anche renderli tutti pubblici.