getClass () e metodi statici: qual è la migliore pratica?
-
03-07-2019 - |
Domanda
Sto cercando di offrire un po 'di praticità attraverso la riflessione ai programmatori che useranno il mio codice. Per ottenere il risultato desiderato, vorrei ottenere l'oggetto class per le classi che estendono il mio codice. Anche se non possono ignorare il metodo statico da cui desidero accedere alle informazioni, al momento sarebbe utile. Potrei finire semplicemente per riformattare un po 'il design per evitare questa situazione, ma volevo porre questa domanda alla comunità.
L'unico modo per ottenere ciò di cui sono a conoscenza è prendere il thread corrente, navigare nella traccia dello stack ed estrarre il nome della classe, quindi convertirlo in un'istanza effettiva della classe.
Altri suggerimenti?
Nota a margine: l'approccio sopra è anche l'unico modo in cui sono a conoscenza di ottenere il metodo di chiamata.
Soluzione
Quando nel metodo statico, qual è la garanzia che una (qualsiasi) classe che è stata estesa dalla tua sia nello stack?
Se ci pensi un po ', sospetto che realizzerai che ciò che stai cercando non esiste.
/ EDIT 1 / Penso che ciò di cui hai bisogno sia
abstract class B {
<T extends B> B create(Class<T> clazz) {
....
}
Hmmm. Cosa succede se create
è il metodo protetto
? Quindi potresti essere abbastanza sicuro che il chiamante sia un B
, puoi persino richiederlo, lanciando UnsupportedOperation
o IllegalState
se il chiamante non è assegnabile a B
.
Puoi usare Thread.currentThread (). getStackTrace ()
Altri suggerimenti
Purtroppo non è necessariamente sicuro camminare nello stack:
Da Javadoc JDK 6 per getStackTrace:
Alcune macchine virtuali possono, sotto alcune circostanze, omettere uno o più stack fotogrammi dalla traccia dello stack. Nel caso estremo, una macchina virtuale che non ha informazioni sulla traccia dello stack riguardo a questo lancio è permesso per restituire un array di lunghezza zero da questo metodo. In generale, il l'array restituito con questo metodo lo farà contiene un elemento per ogni frame che sarebbe stampato da printStackTrace.
Potresti, forse, usare il debugger api per farlo. Credo che il materiale di debug sia in grado di utilizzare HotSpot a tutta velocità (potrei sbagliarmi), quindi non vedresti un enorme successo per farlo. Puoi iniziare guardando: http: // java .sun.com / JavaSE / 6 / docs / note tecniche / guide / jpda / trace.html
Inoltre, basandoci sulla risposta senza risposta ...
class Base
{
// instance method helper
public final int foo()
{
return (foo(this.getClass()));
}
// the real helper, with access to the class
private static int foo(final Class clazz)
{
return (0);
}
}
class Child
extends Base
{
public void bar()
{
final int x;
x = foo();
}
}
La creazione di un lancio è molto costoso, quindi non utilizzarlo se il tuo metodo viene chiamato spesso (.e.g. più di una volta al secondo) Un approccio leggermente migliore è Thread.currentThread (). GetStackTrace ().
Un altro approccio se si utilizza la JVM di Sun è Reflection.getCallerClass (n). Questo molto più veloce ma non portabile su altre JVM. Se sei preoccupato per questo, potresti avere un altro metodo che lo chiama se è disponibile e usa la traccia dello stack in caso contrario.
Tutto questo presuppone che il tuo metodo statico NON sia pubblico. Se è tutto, le scommesse sono disattivate poiché il tuo metodo può essere chiamato da qualsiasi classe, non solo da una tua.
Suggerisco di evitare il pantano della riflessione. Sembra che tu stia facendo una sorta di programmazione semplice. Usa un'implementazione semplice (non ci sono abbastanza informazioni per indovinare cosa potrebbe essere).