如何在Java中获取调用类的名称?

我想在这个问题上提供一些帮助,

例:

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

这基本上就是这种情况。 我的问题是方法foo()如何知道谁在调用它?

编辑 :基本上我试图做一个数据库层,在类AI中将创建一个将生成SQL语句的方法。 通过获取调用类的所有公共属性的值来动态生成此类语句。

最简单的方法如下:

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

但实际上应该没有必要这样做,除非出于某些记录目的,因为这是一项相当昂贵的任务。 它是什么,您认为这是解决方案的问题是什么? 我们可能会提出更好的建议。

编辑 :您评论如下:

基本上我想要做一个数据库层,在A类中,我将创建一个生成sql语句的方法,这样的语句是通过获取调用类的所有公共属性的值动态生成的。

然后,我强烈建议您根据自己的喜好寻找现有的ORM库 ,例如Hibernate , iBatis或任何JPA实现 。

也许对于您的用例,将调用者的类传递给方法是有意义的,例如:

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

并称之为:

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

Java 9:Stack Walking API

JEP 259为堆栈遍历提供了一个有效的标准API,允许轻松过滤和延迟访问堆栈跟踪中的信息。 首先,您应该获取StackWalker的实例:

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

你可以调用getCallerClass()方法:

 Class callerClass = walker.getCallerClass(); 

无论您如何配置StackWalker实例, getCallerClass方法都将忽略reflection帧,隐藏帧以及与MethodHandle相关的帧。 此外,不应在第一个堆栈帧上调用此方法。

foo()是私有的,因此调用者将始终在A类中。

从堆栈跟踪: http : //www.javaworld.com/javaworld/javatips/jw-javatip124.html

如果您使用slf4j作为您的应用程序日志记录系统。 你可以使用:

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

我认为它比新的Exception()。getStackTrace()更快,因为getStackTrace()可以执行克隆堆栈跟踪。

一个hacky解决方案是sun.reflect.Reflection.getCallerClass

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

这很麻烦,因为您必须确保调用Reflection.getCallerClass()的类在引导ClassLoader上加载注释@CallerSensitive (其标记为getCallerClass )才能工作。 因此,它可能不是项目的最佳解决方案,除非您的项目恰好使用Java代理将类添加到引导程序ClassLoader搜索中。

我试过这个并且效果很好。 这是因为每个Java对象都可以访问getClass()方法,该方法返回类调用者和方法名称。

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

示例用法:

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

使用java.util.logging.Logger的示例输出日志;

2017年2月1日下午11:14:50 rmg.data.model.DBTable(init)INFO:完成

可能答案就在这里:

 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 } }