【问题标题】:Java Reflection: Getting fields and methods in declaration orderJava 反射:按声明顺序获取字段和方法
【发布时间】:2011-06-27 10:26:25
【问题描述】:

有没有办法使用反射按声明顺序获取类声明的字段(和方法)?根据文档,getFields()getDeclaredFields() 等返回的方法和字段的顺序是不确定的。

可以使用Java reflection: Is the order of class fields and methods standardized? 中建议的注释来指定类似索引的内容

有没有更好的选择,即不必手动指定索引?

现在在你问我需要这个做什么之前:我们有一个方法,它以一个相当大的数据结构作为输入并对其执行冗长的计算。为了创建单元测试,我们创建了一个方法,该方法接受一个输入对象和一个输出实例,并创建 Java 源代码(设置输入、调用计算方法以及随后断言正确的结果)作为输出。当字段按声明顺序编写时,此代码更具可读性。

【问题讨论】:

    标签: java reflection junit


    【解决方案1】:

    不修改编译过程恐怕是不可能的。通常,该字段以任何顺序写入类文件,而有关声明顺序的信息会丢失。

    您很可能可以使用注释处理器将订单写入辅助文件。

    这应该很容易。看例如以interfacegen 为例,注释处理器如何工作。您可能希望将信息放在同一个文件中,但这要困难得多。

    【讨论】:

      【解决方案2】:

      您将无法从类文件中获取信息。正如亚当在回答其他问题时所说:

      返回的数组中的元素没有排序,也没有任何特定的顺序。

      而“无令”包括“无申报令”。

      我曾经使用 Java 源文件解析器来获取代码生成器的输入数据。这样,您将拥有按声明顺序排列的字段和方法。

      【讨论】:

        【解决方案3】:

        不,反射是不可能的。但是,您可以使用 ProcessBuilderjavap 命令解决它:

        给定一个Test.java

        public abstract class Test {
        
            public void method1() {
            }
        
            public void method2() {
            }
        
            public static void main(String[] args) {
            }
        
            public String method3() {
                return "hello";
            }
        
            abstract void method4();
        
            final int method5() {
                return 0;
            }
        }
        

        命令javap Test 打印:

        ...
        public Test();
        public void method1();
        public void method2();
        public static void main(java.lang.String[]);
        public java.lang.String method3();
        abstract void method4();
        final int method5();
        ...
        

        【讨论】:

          【解决方案4】:

          在 jdk 6 中,反射字段实际上是按照它们的声明顺序。在早期的 jdk 中,情况并非如此。显然已经有足够多的人唠叨了。

          虽然 javadoc 不保证,但我仍然认为这个订单是理所当然的,我认为这个订单也会在未来的 jdks 中保留。

          在您的应用程序中,与大多数应用程序一样,对声明顺序的依赖大多是虚荣的 - 如果顺序搞砸了,您的应用程序不会失败,只是变得更丑了一点。

          【讨论】:

          • 我选择这个答案。即使文档不能保证,它也适用于我。
          • @irreputable,你能提供一个链接吗?还是这种观察仅基于您的经验?
          • 在Oracle JVM 1.7版本上运行发现排序与声明顺序不符。
          • Dalvik 也不符合申报顺序
          • 它们不在声明的顺序中。我刚刚测试了这个。
          【解决方案5】:

          您可能会考虑将 Javadoc 与自定义 Doclet 一起使用,但这需要源可用。

          仍然无法保证 API 中的顺序(methodsfields,但我见过的每个 javadoc 输出都以正确的顺序排列它们,所以我认为 doclet 以声明顺序获取它们。

          【讨论】:

            【解决方案6】:

            这是一个孤立的问题,请看

            https://github.com/wmacevoy/kiss/blob/master/src/main/java/kiss/util/Reflect.java

            方法

            公共静态方法[] getDeclaredMethodsInOrder(Class clazz)

            它通过查看类的字节码来获取顺序。如果您只想使用库,那就是 kiss.util.Reflect.getDeclaredMethodsInOrder(Test.class)

            【讨论】:

            • 但是不能保证类的字节码反映源代码的顺序……
            • 同意;但实际上字节码的声明部分确实按声明顺序排列了它们,正如在 JDK 1.7 和 1.8 上测试的那样。 Android 的 Jack and Jill 未解析(因此未排序),但 Android 确实按声明的顺序返回方法,因此代码适用于当前所有主要上下文。
            猜你喜欢
            • 2015-01-10
            • 1970-01-01
            • 2010-11-09
            • 1970-01-01
            • 2014-04-19
            • 1970-01-01
            • 2011-10-23
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多