Comment obtenir le nom de la classe appelante en Java?

je voudrais de l'aide sur cette affaire", 151930920"

exemple:

public class A {

    private void foo() {

          //Who Invoked me

    }

}

public class B extends A { }

public class C extends A { }

public class D {

     C.foo();

}

c'est essentiellement le scénario. Ma question Est comment la méthode foo() peut-elle savoir qui l'appelle?

EDIT : fondamentalement, j'essaie de faire un calque de base de données, et en Classe A je vais créer une méthode qui générera des déclarations SQL. De telles déclarations sont générées dynamiquement en obtenant les valeurs de tout le public propriétés de la classe appelante.

11
demandé sur R. Martinho Fernandes 2009-11-08 16:33:31

9 réponses

la voie la plus facile est la suivante:

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

mais en réalité, il ne devrait pas être nécessaire pour cela, sauf à des fins de journalisation, parce que c'est une tâche assez coûteuse. C'est quoi, le problème pour lequel vous pensez que c'est la solution? Nous pouvons trouver-beaucoup-de meilleures suggestions.

Edit : vous avez commenté comme suit:

en gros, j'essaie de faire couche de base de données, et en Classe A je vais créer une méthode qui générera des instructions sql, de telles instructions sont générées dynamiquement en obtenant les valeurs de toutes les propriétés publiques de la classe d'appel.

je recommande donc fortement de chercher une bibliothèque existante ORM , tels que Hibernate , iBatis ou n'importe quel mise en œuvre JPA à votre goût.

28
répondu BalusC 2009-11-08 20:22:37

peut-être pour votre cas d'utilisation, il serait logique de passer de la catégorie de l'appelant dans la méthode, comme:

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

et appelez ça quelque chose comme ça:

public class B { new A().foo(getClass() /* or: B.class */ ); }
13
répondu Fabian Steeg 2009-11-08 13:52:06

Java 9: API Stack Walking

JEP 259 fournit une API standard efficace pour le stack walking qui permet un filtrage facile et un accès paresseux à l'information dans les traces stack. Tout d'abord, vous devez obtenir une instance de StackWalker :

import static java.lang.StackWalker.Option.RETAIN_CLASS_REFERENCE;
// other imports

StackWalker walker = StackWalker.getInstance(RETAIN_CLASS_REFERENCE);

vous pouvez appeler la getCallerClass() la méthode:

Class<?> callerClass = walker.getCallerClass();

quelle que soit la façon dont vous avez configuré l'instance StackWalker , la La méthode getCallerClass ignorera les cadres de réflexion, les cadres cachés et ceux qui sont liés à MethodHandle S. En outre, cette méthode ne devrait pas être appelée sur le premier cadre de pile.

8
répondu Ali Dehghani 2017-08-22 08:14:52

foo() est privé, afin que l'appelant sera toujours dans la classe A.

4
répondu alternative 2009-11-08 13:38:02
1
répondu quant_dev 2009-11-08 13:35:59

si vous utilisez slf4j comme système de journalisation des applications. vous pouvez utiliser:

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

je pense que c'est plus rapide que la nouvelle Exception().getStackTrace(), puisque getStackTrace() alaways faire clone stacktrace.

1
répondu Fulai Zhang 2018-01-12 05:32:12

une solution hacky est sun.reflect.Reflection.getCallerClass .

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

Il est hacky parce que vous devez vous assurer que la classe qui appelle Reflection.getCallerClass() est chargé sur le bootstrap chargeur de classe pour l'annotation @CallerSensitive (qui getCallerClass est taggés avec) pour travailler. En tant que tel, il n'est probablement pas la meilleure solution pour un projet à moins que votre projet se trouve à utiliser un Agent Java pour ajouter vos classes au Bootstrap ClassLoader rechercher.

0
répondu AMDG 2017-08-18 23:12:59

j'ai essayé ceci et cela fonctionne bien. C'est parce que chaque objet Java a accès à la méthode getClass() qui renvoie l'appelant de la classe et le nom de la méthode.

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

exemple d'usage:

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

exemple de journal de sortie utilisant java.util.journalisation.Logger;

Feb 01, 2017 11:14:50 PM rmg.données.modèle.DBTable (init) INFO: done

-1
répondu resti 2017-02-01 15:25:09

peut être la réponse est ici :

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
}
}
-2
répondu Piyush 2013-11-25 20:23:33