我需要找到一个方法的调用者。是否可以使用堆栈跟踪或反射?


当前回答

使用方法:-

 StackTraceElement[] stacktrace = Thread.currentThread().getStackTrace();
 stackTraceElement e = stacktrace[2];//maybe this number needs to be corrected
 System.out.println(e.getMethodName());

方法示例代码的调用者在这里:-

public class TestString {

    public static void main(String[] args) {
        TestString testString = new TestString();
        testString.doit1();
        testString.doit2();
        testString.doit3();
        testString.doit4();
    }

    public void doit() {
        StackTraceElement[] stacktrace = Thread.currentThread().getStackTrace();
        StackTraceElement e = stacktrace[2];//maybe this number needs to be corrected
        System.out.println(e.getMethodName());
    }

    public void doit1() {
        doit();
    }

    public void doit2() {
        doit();
    }

    public void doit3() {
        doit();
    }

    public void doit4() {
        doit();
    }
}

其他回答

使用方法:-

 StackTraceElement[] stacktrace = Thread.currentThread().getStackTrace();
 stackTraceElement e = stacktrace[2];//maybe this number needs to be corrected
 System.out.println(e.getMethodName());

方法示例代码的调用者在这里:-

public class TestString {

    public static void main(String[] args) {
        TestString testString = new TestString();
        testString.doit1();
        testString.doit2();
        testString.doit3();
        testString.doit4();
    }

    public void doit() {
        StackTraceElement[] stacktrace = Thread.currentThread().getStackTrace();
        StackTraceElement e = stacktrace[2];//maybe this number needs to be corrected
        System.out.println(e.getMethodName());
    }

    public void doit1() {
        doit();
    }

    public void doit2() {
        doit();
    }

    public void doit3() {
        doit();
    }

    public void doit4() {
        doit();
    }
}

我以前做过。您可以只创建一个新的异常,并在不抛出异常的情况下获取其堆栈跟踪,然后检查堆栈跟踪。正如另一个答案所说,这是非常昂贵的——不要在一个紧密的循环中进行。

我以前在一个性能不太重要的应用程序上为一个日志实用程序做过这样的操作(实际上,性能几乎不太重要——只要你将结果显示给一个动作,比如快速单击按钮)。

这是在你可以得到堆栈跟踪之前,异常只是有. printstacktrace(),所以我必须重定向系统。输出到我自己创建的流,然后(new Exception()).printStackTrace();重定向系统。返回并解析流。有趣的东西。

StackTraceElement[] stackTraceElements = Thread.currentThread().getStackTrace()

根据Javadocs的说法:

数组的最后一个元素表示堆栈的底部,这是序列中最近的方法调用。

一个stacktracement有getts()、getFileName()、getLineNumber()和getmethod。

您必须通过试验来确定需要哪个索引 (可能是stackTraceElements[1]或[2])。

听起来好像您试图避免将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]