Java 反射:按声明顺序获取字段和方法

Posted

技术标签:

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

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

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

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

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

【问题讨论】:

【参考方案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 中的顺序(methods、fields,但我见过的每个 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 确实按声明的顺序返回方法,因此代码适用于当前所有主要上下文。

以上是关于Java 反射:按声明顺序获取字段和方法的主要内容,如果未能解决你的问题,请参考以下文章

java 通过反射怎么获取方法中参数值

Java反射----访问字段(Field)

按字母顺序获取对象的java集合

java笔记

使用指定的顺序按字段选择连续组

在 Java 中计算字符串的 1 和 0,并将它们按顺序排列?