如何在Java中找出调用方法的类?

7
如何在不向方法传递任何变量的情况下找出调用我的方法的类? 假设我们有这样一个东西:
Class A{}
Class B{}
Class C{
public void method1{}
System.out.print("Class A or B called me");
}

假设类A的一个实例调用了类C的一个实例,类B也是一样。当类A调用类C的方法1时,我希望它打印出"Class A called me",当类B调用它时打印"Class B called me"。


你为什么想知道是哪个类调用了你的方法?你想解决什么问题? - Steve Kuo
@Quoi 为什么它需要是静态的?是因为它正在访问 StackTrace,我们只希望一个实例可以访问它吗? - sheidaei
@SteveKuo 我并没有具体的应用想法,这个话题是在我和一些同事进行 Java 辩论时提出来的。 - sheidaei
我知道这个问题很老,但它可能有用的一个原因是我目前遇到的事情:我有一个方法被调用了10次,但它只应该被调用一次。找出是什么在调用该方法有助于导航堆栈并定位错误。 - cjnash
2个回答

14

这个问题其实没有简单的解决方法,因为通常一个方法不应该关心它是从哪里被调用的。如果你编写的方法依赖于它被调用的位置,那么你的程序很快就会变成难以理解的混乱。

然而,下面是一个例子:

public class Prut {
    public static void main(String[] args) {
        example();
    }

    public static void example() {
        StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
        StackTraceElement element = stackTrace[2];
        System.out.println("I was called by a method named: " + element.getMethodName());
        System.out.println("That method is in class: " + element.getClassName());
    }
}

我假设这是堆栈跟踪的结构:“String declaringClass,String methodName,String fileName,int lineNumber”,因为你使用了第二个,或者应该是stackTrace [1]? - sheidaei
@sheidaei 是的,请查阅 StackTraceElement 类的 API 文档。 - Jesper
@sheidaei 不是 stackTrace[1],应该是 stackTrace[2] - 试一下。 - Jesper

6
你可以使用Thread.currentThread().getStackTrace()
它会返回一个[StackTraceElement][1]数组,代表程序的当前堆栈跟踪信息。

3
+1 这样做非常昂贵,如果性能很重要,应该尽量避免。例如,日志记录经常使用这种方法,会严重拖慢应用程序的运行速度。 - Peter Lawrey
请注意,这可能是一个相当缓慢的操作,因此在使用之前请仔细考虑。此外,如果您和您的“真实”调用者之间存在干扰的堆栈帧,例如通过反射进行调用,则无法提供帮助。 - Ian Roberts
1
如果安全管理器不允许获取线程的堆栈跟踪,它还会抛出SecurityException。 - Subhrajyoti Majumder
@Quoi 当你谈论安全管理器时,你是在谈论一个J2EE框架吗? - sheidaei
您可以通过 System.setSecurityManager(SecurityManager) 在系统中设置自定义安全策略。 - Subhrajyoti Majumder

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接