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


当前回答

简单回答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]

其他回答

下面是我根据本主题中显示的提示制作的部分代码。 希望能有所帮助。

(请随时提出任何建议来改进此代码,请告诉我)

柜台:

public class InstanceCount{
    private static Map<Integer, CounterInstanceLog> instanceMap = new HashMap<Integer, CounterInstanceLog>();
private CounterInstanceLog counterInstanceLog;


    public void count() {
        counterInstanceLog= new counterInstanceLog();
    if(counterInstanceLog.getIdHashCode() != 0){
    try {
        if (instanceMap .containsKey(counterInstanceLog.getIdHashCode())) {
         counterInstanceLog= instanceMap .get(counterInstanceLog.getIdHashCode());
    }

    counterInstanceLog.incrementCounter();

            instanceMap .put(counterInstanceLog.getIdHashCode(), counterInstanceLog);
    }

    (...)
}

对象是:

public class CounterInstanceLog{
    private int idHashCode;
    private StackTraceElement[] arrayStackTraceElements;
    private int instanceCount;
    private String callerClassName;

    private StackTraceElement getProjectClasses(int depth) {
      if(depth< 10){
        getCallerClassName(sun.reflect.Reflection.getCallerClass(depth).getName());
        if(getCallerClassName().startsWith("com.yourproject.model")){
            setStackTraceElements(Thread.currentThread().getStackTrace());
            setIdHashCode();
        return arrayStackTraceElements[depth];
        }
        //+2 because one new item are added to the stackflow
        return getProjectClasses(profundidade+2);           
      }else{
        return null;
      }
    }

    private void setIdHashCode() {
        if(getNomeClasse() != null){
            this.idHashCode = (getCallerClassName()).hashCode();
        }
    }

    public void incrementaContador() {
    this.instanceCount++;
}

    //getters and setters

    (...)



}

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

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

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

使用方法:-

 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[] stackTraceElements = Thread.currentThread().getStackTrace()

根据Javadocs的说法:

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

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

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

简单回答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]