Java Reflection:查看方法中的代码行?

时间:2014-04-07 14:13:25

标签: java reflection

我希望能够使用java反射(或任何其他可能存在的方法)提取方法的内部。

我有一个测试数据,我生成不同风格的图表。我希望能够显示图表,然后在它旁边的面板中显示创建该图表的java代码。

我需要做的就是深入研究这些方法,并提取内部结构。反射允许吗?

chart = TestData.createChart1();
chart.display()
chart = TestData.createChart2();
chart.display()
chart = TestData.createChart3();
    ...
chart = TestData.createChartN();
chart.display()

在我的一个方法中,我可能有这样的东西:

public static PieChart createChart1() {

    //I WANT ALL THE CODE FROM HERE....

    ArrayList<Segment> values = new ArrayList<Segment>();
    values.add(new Segment(0, null, 15, "music", Color.RED));
    values.add(new Segment(0, null, 52, "photos", Color.BLUE));
    values.add(new Segment(0, null, 33, "applications", Color.GREEN));

    PieChart pieChart = new PieChart(values, "Disk Space Usage");

    pieChart.width = 600;
    pieChart.height = 600;
    pieChart.topOffset = 50;
    pieChart.leftOffset = 50;
    pieChart.rightOffset = 50;
    pieChart.bottomOffset = 50;
    pieChart.initialWidth = 100;
    pieChart.incrementWidth = 50;

    //TO HERE....

    return pieChart;
}

2 个答案:

答案 0 :(得分:2)

关于反射的好处是它允许程序访问其源代码的某些方面。不太好的部分是你能得到它的东西是由语言设计者和实施者决定并因此受到限制。原始源代码是他们合理地不想提供的一部分。如果他们这样做,每个编译的反射系统都会包含它的源代码,这会造成巨大的知识产权泄漏。

如果您希望以编程方式访问计算机程序的全部内容(包括Java中的程序),则称为Program Transformation(PTS)系统的工具类是理想的。这些工具通常用于解析感兴趣的源代码语言,构建内部编译器数据结构(通常是抽象语法树或AST),其中包含完整等效的源代码(通常包括精确的源代码位置信息)。从OP的观点来看,真正有用的部分是PTS通常可以反转解析过程,并从内部结构重新生成源(或指定部分)。作为替代方案,可以使用精确的源位置信息从原始文件中提取原始文本;如果您关心精确格式和/或空格中的内容,这通常非常有用。

要使用我们的DMS软件重新设计工具包获得OP的效果,可以使用DMS的Java前端,并使用大致以下代码编写自定义工具:

       (include `Java~v7/ParserComponent.par')
        ...
       (local (;; [myFile string] 
                  [myTree AST:Tree]
              );;
           ...
           (= myFile ... )  ; get a file path from somewhere
           (= myTree (ParserComponent:Parse myFile ...))
           (AST:ScanTree myTree
                 (procedure [subtree AST:Tree]
                     (;;  (ifthen (== (AST:subtree Grammar:Nonterminals:_method_declaration))
                               (;;  (ParserComponent:PrettyPrintFidelity
                                         (AST:GetNthGrammarChild myTree 3) ; the method body
                                         ...
                                     )
                               );;
                          )

                          (return ~t) ; signal to ScanTree to continue looking 
                     );;
                 )
           )AST
       )local

请注意树搜索(将其视为访问者),它搜索类型为&#34; method_declaration&#34;的AST节点,这是一个从Java语法中逐字逐句的术语。找到这样的AST节点类型后,它会导航到方法体并调用DMS的prettyprinter以在Fidelity模式下重新生成文本,该模式从原始源代码再现原始缩进和换行符以及注释。 [所有这些信息都在DMS的树上]。

如果OP需要特定命名的方法;他将使用DMS的NameResolver组件,该组件构建一个完整的符号表,包括每个定义一个引用(特别是树)到提供定义的源代码点。然后,可以使用该符号表查找限定名称,抓取定义树并打印它。

答案 1 :(得分:0)

  1. java reflexion不允许读取代码行,并且反射依赖的pcode不包含源代码,只有编译后的代码,如果是用调试选项编译的,也是行号。

  2. 由于你的方法“createChart”只创建一个对象,你只能分析结果对象的内容(“图表”)

    chart = TestData.createChart1();
    analyze(chart);
    chart.display();
    
  3. 然后在你的“分析”方法中,做任何你想要显示objet的东西,比如Json Serialision,Xml ......或者只是一个toString,如果结果是可利用的。