【问题标题】:Getting the declaring class of an instance: possible?获取实例的声明类:可能吗?
【发布时间】:2014-04-20 15:49:42
【问题描述】:

有没有办法在运行时检索实例的声明类? 例如:

public class Caller {
    private JFrame frame = new JFrame("Test");
    private JButton button = new JButton("Test me");
    private Callee callee = new Callee();

    public Caller() {
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.getContentPane().add(button);

        button.addActionListener(callee.getListener());

        frame.pack();
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        new Caller();
    }
}

被调用者:

public class Callee {
    public ActionListener getListener() {
        return new ActionListener() {
        @Override
            public void actionPerformed(ActionEvent e) {
                /* Get the class "Caller" here and invoke its methods */
                /* Something along the lines of: */
                Object button = e.getSource();
                button.getOwnerClass(); //This would return the type Caller
            }
        };
    }
}

“getOwnerClass()”是一个虚构的方法。有没有办法得到类似的结果?

【问题讨论】:

  • 对“Callee”的引用可以存储在多个位置,“Caller”没什么特别的 => Anwser 没有。
  • 你的意思是Caller.class
  • 那会给你什么?您可以始终如一地使用这些信息做什么?您可以通过堆栈跟踪获得它。
  • @SotiriosDelimanolis 假设被调用者的 ActionListener 被多个类使用,所有这些类共享一个方法(由接口实现)。
  • 你不能对所有的 Java 做出这样的假设。所以如此具体的东西是不可能存在的。您可以访问堆栈跟踪并获取堆栈上的类型,但您永远不知道堆栈要走多远。

标签: java class reflection instance


【解决方案1】:

标准 API 中没有任何内容可让您获取此信息。有点不清楚“声明类”或“所有者类”是什么意思,但为了这个答案,我假设它是代码创建对象实例的类(你想要所有者类) .

JVM 默认不存储此信息。

但是,使用the heap profiler that is packaged along with the JDK distribution,您可以记录分配对象的点的堆栈跟踪,并且可以将该信息在不同的时间点写入文件。

这仍然没有为您提供 API 调用来检索信息,但它表明在技术上可以记录此类信息。

我在 Google 上搜索了一下,发现有人确实创建了一个 API,它使用与堆分析器相同的基本技术(java.lang.instrumentation package/JVMTI 接口)

通过一些工作,您应该能够用它构建一些东西。

该网站有一个很好的例子:

AllocationRecorder.addSampler(new Sampler() {
    public void sampleAllocation(int count, String desc, Object newObj, long size) {
      System.out.println("I just allocated the object " + newObj + 
        " of type " + desc + " whose size is " + size);
      if (count != -1) { System.out.println("It's an array of size " + count); }
    }
});

您应该使用new Exception().getStackTrace() 获取堆栈跟踪,而不是打印,删除前几个引用采样器和API 类的StackTraceElement 对象,然后调用StackTraceElement.getClassName() 以获取创建的类的名称对象实例,也就是您的 OwnerClass。

【讨论】:

  • 我很抱歉造成混乱;你的假设是正确的。然而,虽然 Allocation Instrumenter 项目确实很有趣,但它并不是我想要的——它会使代码变得过于复杂(和依赖),而我原本希望相当简单。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-02-07
  • 2018-03-08
  • 1970-01-01
  • 2011-06-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多