如何在Java中获取调用类的名称?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1696551/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to get the name of the calling class in Java?
提问by Mark Buhagiar
I would like some help on this matter,
我想在这个问题上得到一些帮助,
Example:
例子:
public class A {
private void foo() {
//Who invoked me?
}
}
public class B extends A {}
public class C extends A {}
public class D {
C.foo();
}
This is basically the scenario. My question is how can method foo()
know who is calling it?
基本上就是这个场景。我的问题是方法如何foo()
知道谁在调用它?
EDIT: Basically I am trying to do a database Layer, and in class A
I will create a method that will generate SQL statements. Such statements are dynamically generated by getting the values of all the public
properties of the calling class
.
编辑:基本上我正在尝试做一个数据库层,并且class A
我将创建一个将生成 SQL 语句的方法。此类语句是通过获取public
调用的所有属性的值动态生成的class
。
回答by BalusC
Easiest way is the following:
最简单的方法如下:
String className = new Exception().getStackTrace()[1].getClassName();
But in real there should be no need for this, unless for some logging purposes, because this is a fairly expensive task. What is it, the problem for which you think that this is the solution? We may come up with -much- better suggestions.
但实际上应该没有必要这样做,除非出于某些日志目的,因为这是一项相当昂贵的任务。它是什么,您认为这是解决方案的问题?我们可能会提出 - 更好的建议。
Edit: you commented as follows:
编辑:您评论如下:
basically i'am trying to do a database Layer, and in Class A i will create a method that will generate sql statements, such statements are dynamically generated by getting the values of all the public properties of the calling class.
基本上我正在尝试做一个数据库层,在 A 类中,我将创建一个生成 sql 语句的方法,这些语句是通过获取调用类的所有公共属性的值动态生成的。
I then highly recommend to look for an existing ORM library, such as Hibernate, iBatisor any JPA implementationto your taste.
回答by quant_dev
回答by alternative
foo() is private, so the caller will always be in class A.
foo() 是私有的,所以调用者总是在 A 类中。
回答by Fabian Steeg
Perhaps for your use case it would make sense to pass the class of the caller into the method, like:
也许对于您的用例,将调用者的类传递给方法是有意义的,例如:
public class A { public void foo(Class<?> c) { ... } }
And call it something like this:
并称之为:
public class B { new A().foo(getClass() /* or: B.class */ ); }
回答by Piyush
Maybe an answer is
也许答案是
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
}
}
回答by resti
I tried this and it works well. It is because each Java Object
has access to getClass()
method which returns the class
caller and the method name.
我试过这个,效果很好。这是因为每个 JavaObject
都可以访问getClass()
返回class
调用者和方法名称的方法。
public Logger logger() {
return Logger.getLogger(getClass().toString());
}
example usage:
用法示例:
public DBTable(String tableName) {
this.tableName = tableName;
loadTableField();
this.logger().info("done");
}
sample output log using java.util.logging.Logger
示例输出日志使用 java.util.logging.Logger
Feb 01, 2017 11:14:50 PM rmg.data.model.DBTable (init) INFO: done
2017 年 2 月 1 日晚上 11:14:50 rmg.data.model.DBTable(初始化)信息:完成
回答by AMDG
A hacky solution is sun.reflect.Reflection.getCallerClass
.
一个hacky的解决方案是sun.reflect.Reflection.getCallerClass
。
public void foo() {
Class<?> caller = sun.reflect.Reflection.getCallerClass();
// ...
}
It is hacky because you have to ensure that the class that calls Reflection.getCallerClass()
is loaded on the bootstrap ClassLoaderfor the annotation @CallerSensitive
(which getCallerClass
is tagged with) to work. As such, it probably isn't the best solution for a project unless your project happens to use a Java Agentto add your classes to the bootstrap ClassLoader search.
这是 hacky,因为您必须确保调用的类Reflection.getCallerClass()
加载到引导类加载器上才能使注释@CallerSensitive
(getCallerClass
标记为)工作。因此,它可能不是项目的最佳解决方案,除非您的项目碰巧使用Java 代理将您的类添加到引导类加载器搜索中。
回答by Ali Dehghani
Java 9: Stack Walking API
Java 9:堆栈遍历 API
JEP 259provides an efficient standard API for stack walking that allows easy filtering of, and lazy access to, the information in stack traces. First off, you should obtain an instance of StackWalker
:
JEP 259为堆栈遍历提供了一个高效的标准 API,允许轻松过滤和延迟访问堆栈跟踪中的信息。首先,您应该获得一个实例StackWalker
:
import static java.lang.StackWalker.Option.RETAIN_CLASS_REFERENCE;
// other imports
StackWalker walker = StackWalker.getInstance(RETAIN_CLASS_REFERENCE);
After that you can call the getCallerClass()
method:
之后,您可以调用该getCallerClass()
方法:
Class<?> callerClass = walker.getCallerClass();
Regardless of how you configured the StackWalker
instance, the getCallerClass
method will ignore the reflection frames, hidden frames and those are related to MethodHandle
s. Also, this method shouldn't be called on the first stack frame.
无论您如何配置StackWalker
实例,该getCallerClass
方法都会忽略反射帧、隐藏帧以及与MethodHandle
s相关的那些。此外,不应在第一个堆栈帧上调用此方法。
回答by Fulai Zhang
if you using slf4j as your application logging system. you can using:
如果您使用 slf4j 作为您的应用程序日志系统。你可以使用:
Class<?> source = org.slf4j.helpers.Util.getCallingClass();
I think it's faster than new Exception().getStackTrace(), since getStackTrace() alaways doing clone stacktrace.
我认为它比 new Exception().getStackTrace() 快,因为 getStackTrace() 总是在做克隆堆栈跟踪。
回答by forhas
I would use StackWalker
我会使用StackWalker
private static Class<?> getCallingClass(int skip) {
StackWalker walker = StackWalker.getInstance(StackWalker.Option.RETAIN_CLASS_REFERENCE);
Optional<? extends Class<?>> caller = walker.walk(frames ->
frames.skip(skip).findFirst().map(StackWalker.StackFrame::getDeclaringClass)
);
return caller.get();
}
If you need the class of the calling method use skip=1
.
如果您需要调用方法的类,请使用skip=1
.