如何在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 } }