Come ottenere il nome della class chiamante in Java?

Vorrei un po ‘di aiuto su questo argomento,

Esempio:

public class A { private void foo() { //Who Invoked me } } public class B extends A { } public class C extends A { } public class D { C.foo(); } 

Questo è fondamentalmente lo scenario. La mia domanda è come può il metodo foo() sapere chi lo sta chiamando?

EDIT : Fondamentalmente sto cercando di fare un livello di database, e in class AI creerò un metodo che genererà istruzioni SQL. Tali istruzioni vengono generate dynamicmente ottenendo i valori di tutte le proprietà pubbliche della class chiamante.

Il modo più semplice è il seguente:

 String className = new Exception().getStackTrace()[1].getClassName(); 

Ma in realtà non ci dovrebbe essere alcun bisogno di questo, a meno che non per alcuni scopi di registrazione, perché questo è un compito abbastanza costoso. Di cosa si tratta, il problema per il quale pensi che questa sia la soluzione? Potremmo inventare suggerimenti molto migliori.

Modifica : hai commentato come segue:

fondamentalmente sto provando a fare un database Layer, e in Classe A creerò un metodo che genererà istruzioni SQL, tali istruzioni sono generate dynamicmente ottenendo i valori di tutte le proprietà pubbliche della class chiamante.

Quindi consiglio vivamente di cercare una libreria ORM esistente, come Hibernate , iBatis o qualsiasi implementazione JPA secondo i propri gusti.

Forse per il tuo caso d’uso avrebbe senso passare la class del chiamante nel metodo, come:

 public class A { public void foo(Class c) { ... } } 

E chiamalo in questo modo:

 public class B { new A().foo(getClass() /* or: B.class */ ); } 

Java 9: ​​API Stack Walking

JEP 259 fornisce un’efficiente API standard per lo stack walking che consente un facile filtraggio e un accesso lazy alle informazioni nelle tracce dello stack. Prima di tutto, dovresti ottenere un’istanza di StackWalker :

 import static java.lang.StackWalker.Option.RETAIN_CLASS_REFERENCE; // other imports StackWalker walker = StackWalker.getInstance(RETAIN_CLASS_REFERENCE); 

Puoi chiamare il metodo getCallerClass() :

 Class callerClass = walker.getCallerClass(); 

Indipendentemente da come hai configurato l’istanza StackWalker , il metodo getCallerClass ignorerà i frame di riflessione, i frame nascosti e quelli relativi a MethodHandle . Inoltre, questo metodo non dovrebbe essere chiamato sul primo frame dello stack.

foo () è privato, quindi il chiamante sarà sempre in class A.

se si utilizza slf4j come sistema di registrazione dell’applicazione. puoi usare:

 Class source = org.slf4j.helpers.Util.getCallingClass(); 

Penso che sia più veloce del nuovo Exception (). GetStackTrace (), dal momento che getStackTrace () esegue il clone stacktrace.

Una soluzione hacky è sun.reflect.Reflection.getCallerClass .

 public void foo() { Class caller = sun.reflect.Reflection.getCallerClass(); // ... } 

È hacky perché è necessario assicurarsi che la class che chiama Reflection.getCallerClass() sia caricata sul @CallerSensitive ClassLoader per l’annotazione @CallerSensitive (con cui getCallerClass è etichettato con) per funzionare. Pertanto, probabilmente non è la soluzione migliore per un progetto a meno che il progetto non utilizzi un Java Agent per aggiungere le classi alla ricerca ClassLoader di bootstrap.

Ho provato questo e funziona bene. È perché ogni object Java ha accesso al metodo getClass () che restituisce il chiamante della class e il nome del metodo.

 public Logger logger() { return Logger.getLogger(getClass().toString()); } 

esempio di utilizzo:

 public DBTable(String tableName) { this.tableName = tableName; loadTableField(); this.logger().info("done"); } 

registro di output di esempio con java.util.logging.Logger;

1 feb 2017 11:14:50 PM rmg.data.model.DBTable (init) INFO: fatto

Può essere la risposta è qui:

 public class CallerMain { public void foo(){ System.out.println("CallerMain - foo"); System.out.println(this.getClass());//output- callerMain } public static void main(String[] args) { A a = new A(); CallerMain cm = new CallerMain(); cm.foo(); } } class A{ public void foo(){ System.out.println("A - foo"); System.out.println(this.getClass());//output- A } }