我需要找到一个方法的调用者。是否可以使用堆栈跟踪或反射?
当前回答
我以前做过。您可以只创建一个新的异常,并在不抛出异常的情况下获取其堆栈跟踪,然后检查堆栈跟踪。正如另一个答案所说,这是非常昂贵的——不要在一个紧密的循环中进行。
我以前在一个性能不太重要的应用程序上为一个日志实用程序做过这样的操作(实际上,性能几乎不太重要——只要你将结果显示给一个动作,比如快速单击按钮)。
这是在你可以得到堆栈跟踪之前,异常只是有. printstacktrace(),所以我必须重定向系统。输出到我自己创建的流,然后(new Exception()).printStackTrace();重定向系统。返回并解析流。有趣的东西。
其他回答
听起来好像您试图避免将this的引用传递到方法中。传递这个比通过当前堆栈跟踪查找调用者要好得多。重构为更面向对象的设计更好。你不需要认识打电话的人。必要时传递回调对象。
简单回答ReflectionUtils.getCallingClass(0)
长答案(代码,Groovy)
package my
import org.codehaus.groovy.reflection.ReflectionUtils
import java.lang.reflect.Field
import java.lang.reflect.Method
trait Reflector {
static String[] fieldNames() {
List<String> names = []
Arrays.asList(naturalFields()).forEach { Field fl -> names.add(fl.name) }
return names.toArray() as String[]
}
static Field[] naturalFields() {
return finalClass().getDeclaredFields().findAll { Field fl -> !fl.synthetic }.collect()
}
static Method[] naturalMethods() {
return finalClass().getDeclaredMethods().findAll { Method md -> !md.synthetic }.collect()
}
static Class finalClass() {
return ReflectionUtils.getCallingClass(0)
}
}
class Demo implements Reflector {
int archived = 0
int demo = 100
static void playToo() {
println finalClass()
}
}
println Demo.finalClass() // class my.Demo
println Demo.naturalFields() // [private int my.Demo.archived, private int my.Demo.demo]
println Demo.fieldNames() // [archived, demo]
Oneliner:
Thread.currentThread().getStackTrace()[2].getMethodName()
注意,您可能需要将2替换为1。
我以前做过。您可以只创建一个新的异常,并在不抛出异常的情况下获取其堆栈跟踪,然后检查堆栈跟踪。正如另一个答案所说,这是非常昂贵的——不要在一个紧密的循环中进行。
我以前在一个性能不太重要的应用程序上为一个日志实用程序做过这样的操作(实际上,性能几乎不太重要——只要你将结果显示给一个动作,比如快速单击按钮)。
这是在你可以得到堆栈跟踪之前,异常只是有. printstacktrace(),所以我必须重定向系统。输出到我自己创建的流,然后(new Exception()).printStackTrace();重定向系统。返回并解析流。有趣的东西。
private void parseExceptionContents(
final Exception exception,
final OutputStream out)
{
final StackTraceElement[] stackTrace = exception.getStackTrace();
int index = 0;
for (StackTraceElement element : stackTrace)
{
final String exceptionMsg =
"Exception thrown from " + element.getMethodName()
+ " in class " + element.getClassName() + " [on line number "
+ element.getLineNumber() + " of file " + element.getFileName() + "]";
try
{
out.write((headerLine + newLine).getBytes());
out.write((headerTitlePortion + index++ + newLine).getBytes() );
out.write((headerLine + newLine).getBytes());
out.write((exceptionMsg + newLine + newLine).getBytes());
out.write(
("Exception.toString: " + element.toString() + newLine).getBytes());
}
catch (IOException ioEx)
{
System.err.println(
"IOException encountered while trying to write "
+ "StackTraceElement data to provided OutputStream.\n"
+ ioEx.getMessage() );
}
}
}
推荐文章
- 在流中使用Java 8 foreach循环移动到下一项
- 访问限制:'Application'类型不是API(必需库rt.jar的限制)
- 用Java计算两个日期之间的天数
- 如何配置slf4j-simple
- 在Jar文件中运行类
- 带参数的可运行?
- 我如何得到一个字符串的前n个字符而不检查大小或出界?
- 我可以在Java中设置enum起始值吗?
- Java中的回调函数
- c#和Java中的泛型有什么不同?和模板在c++ ?
- 在Java中,流相对于循环的优势是什么?
- Jersey在未找到InjectionManagerFactory时停止工作
- 在Java流是peek真的只是调试?
- Recyclerview不调用onCreateViewHolder
- 将JSON字符串转换为HashMap