为了账号安全,请及时绑定邮箱和手机立即绑定

如何获取Java中的调用方类

如何获取Java中的调用方类

aluckdog 2019-12-11 14:09:22
我想获取方法的调用者类,即class foo{  bar();}在方法栏中,我需要获取类名称foo,然后找到了该方法:Class clazz = sun.reflect.Reflection.getCallerClass(1);但是,即使getCallerClass是public,当我尝试调用它时,Eclipse 也会说:访问限制:由于必需的库C:\ Program Files \ Java \ jre7 \ lib \ rt.jar的限制,无法访问类型为Reflection的方法getCallerClass()还有其他选择吗?
查看完整描述

3 回答

?
慕工程0101907

TA贡献1887条经验 获得超5个赞

您可以生成堆栈跟踪并使用StackTraceElements中的信息。


例如,实用程序类可以为您返回调用类名称:


public class KDebug {

    public static String getCallerClassName() { 

        StackTraceElement[] stElements = Thread.currentThread().getStackTrace();

        for (int i=1; i<stElements.length; i++) {

            StackTraceElement ste = stElements[i];

            if (!ste.getClassName().equals(KDebug.class.getName()) && ste.getClassName().indexOf("java.lang.Thread")!=0) {

                return ste.getClassName();

            }

        }

        return null;

     }

}

如果你调用KDebug.getCallerClassName()从bar(),你会得到"foo"。


现在假设您想知道方法调用的类bar(这会更有趣,也许您真正想要的是)。您可以使用以下方法:


public static String getCallerCallerClassName() { 

    StackTraceElement[] stElements = Thread.currentThread().getStackTrace();

    String callerClassName = null;

    for (int i=1; i<stElements.length; i++) {

        StackTraceElement ste = stElements[i];

        if (!ste.getClassName().equals(KDebug.class.getName())&& ste.getClassName().indexOf("java.lang.Thread")!=0) {

            if (callerClassName==null) {

                callerClassName = ste.getClassName();

            } else if (!callerClassName.equals(ste.getClassName())) {

                return ste.getClassName();

            }

        }

    }

    return null;

 }

那是用于调试吗?如果没有,可能有一个更好的解决方案。



查看完整回答
反对 回复 2019-12-12
?
神不在的星期二

TA贡献1963条经验 获得超6个赞

要获得呼叫者/被呼叫者的类名,请使用以下代码,它对我来说很好用。


String callerClassName = new Exception().getStackTrace()[1].getClassName();

String calleeClassName = new Exception().getStackTrace()[0].getClassName();


查看完整回答
反对 回复 2019-12-12
?
繁花如伊

TA贡献2012条经验 获得超12个赞

堆栈跟踪


这高度取决于您要查找的内容...但是,这应该直接在此对象中获得调用此方法的类和方法。


索引0 =线程

索引1 =这个

索引2 =直接呼叫者,可以是自己。

索引3 ... n =相互调用以获得索引2及以下的类和方法。

对于类/方法/文件名:


Thread.currentThread().getStackTrace()[2].getClassName();

Thread.currentThread().getStackTrace()[2].getMethodName();

Thread.currentThread().getStackTrace()[2].getFileName();

上课:


Class.forName(Thread.currentThread().getStackTrace()[2].getClassName())

仅供参考:Class.forName()抛出不是运行时的ClassNotFoundException。您需要尝试抓住。


同样,如果您希望忽略类本身内的调用,则必须添加一些带有逻辑的循环来检查该特定事物。


像...(我没有测试过这段代码,所以要当心)


StackTraceElement[] stes = Thread.currentThread().getStackTrace();

for(int i=2;i<stes.length;i++)

  if(!stes[i].getClassName().equals(this.getClass().getName()))

    return stes[i].getClassName();

StackWalker


StackWalker StackFrame


请注意,这不是详尽的指南,而是这种可能性的一个示例。


打印每个StackFrame的Class(通过获取Class引用)


StackWalker.getInstance(Option.RETAIN_CLASS_REFERENCE)

    .forEach(frame -> System.out.println(frame.getDeclaringClass()));

做同样的事情,但首先将流收集到一个列表中。仅用于演示目的。


StackWalker.getInstance(Option.RETAIN_CLASS_REFERENCE)

    .walk(stream -> stream.collect(Collectors.toList()))

    .forEach(frame -> System.out.println(frame.getDeclaringClass()));



查看完整回答
反对 回复 2019-12-12
  • 3 回答
  • 0 关注
  • 294 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信