Java Reflection:按声明顺序获取字段和方法
有没有办法使用反射按声明顺序获取类声明的字段(和方法)?根据文档,getFields()
、getDeclaredFields()
等返回的方法和字段的顺序是未定义的。
有没有更好的选择,即不必手动指定索引?
现在,在你问我需要这个做什么之前:我们有一个方法,它采用相当大的数据结构作为输入并对其执行冗长的计算。为了创建单元测试,我们创建了一个方法,该方法接受输入对象和输出实例,并创建 Java 源代码(设置输入、调用计算方法,然后断言正确的结果)作为输出。当字段按声明顺序写入时,此代码的可读性要高得多。
Is there any way to get a classes declared fields (and methods) in the order of declaration using reflection? According to the documentation, the ordering of Methods and Fields returned by getFields()
, getDeclaredFields()
, etc. is undefined.
Specifying something like an index would be possible using annotation as suggested in Java reflection: Is the order of class fields and methods standardized?
Are there any better options, i.e. not having to specify the index manually?
Now before you ask what I need this for: we have a method that takes a quite big data structure as input and performs a lengthy calculation on it. To create unit tests, we made a method that takes an input object and an output instance and creates the Java source code (setting up input, invoking the calculation method, and asserting the correct results afterwards) as output. This code is much more readable when fields are written in declaration order.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
在 jdk 6 中,反射字段实际上按照其声明顺序排列。在早期的jdk中并不是这样的。显然已经有足够多的人唠叨了。
虽然 javadoc 没有保证,但我仍然认为这个顺序是理所当然的,并且我假设这个顺序也将保留在未来的 jdks 中。
在您的应用程序中,就像在大多数应用程序中一样,对声明顺序的依赖主要是虚荣的 - 如果顺序搞砸了,您的应用程序不会失败,它只是变得有点难看。
With jdk 6, the reflected fields are in deed in their declaration order. In early jdk that wasn't the case. Apparently enough people have nagged.
Although not guaranteed by javadoc, I would still take this order as granted, and I assume the order will be kept in future jdks too.
In your app, like in most apps, the dependency on the declaration order is mostly vanity - your app won't fail if the order screws up, it just become a little uglier.
我将此作为一个孤立的问题,请查看
https://github.com/wmacevoy/kiss/blob/master/src/main/java/kiss/util/Reflect.java
和方法
它通过查看类的字节码来获取顺序。如果你只想使用库,那就是
kiss.util.Reflect.getDeclaredMethodsInOrder(Test.class)
I had this as an isolated problem, look at
https://github.com/wmacevoy/kiss/blob/master/src/main/java/kiss/util/Reflect.java
and the method
It gets the order by looking at the bytecode of the class. If you just want to use the libray, is would be
kiss.util.Reflect.getDeclaredMethodsInOrder(Test.class)
不,通过反射是不可能的。但是,您可以使用 ProcessBuilder 和 javap 命令来解决它:
给定 Test.java:
命令 javap Test > 打印:
No, not possible with reflection. You could however solve it using a
ProcessBuilder
and thejavap
command:Given a
Test.java
:The command
javap Test
prints:不修改编译过程恐怕是不可能的。通常,该字段会以任何顺序写入类文件,并且有关声明顺序的信息会丢失。
您很可能可以使用注释处理器将订单写入辅助文件中。
这应该很容易。例如,查看 interfacegen 的示例,了解注释处理器如何工作。您可能希望将这些信息放在同一个文件中,但这要困难得多。
I'm afraid it's impossible without modifying the compilation process. Normally, the field get written into the classfile in any order and the information about the declaration order gets lost.
Most probably you could use an annotation processor to write the order in an auxiliary file.
It should be quite easy. Look e.g. at interfacegen for an example, how an annotation processor can work. You may want to put the information in the same file, but this is much harder.
您可能会考虑将 Javadoc 与自定义 Doclet 一起使用,但这需要源代码可用。
仍然无法保证 API 中的顺序(方法,fields,但是我见过的每个 javadoc 输出都以正确的顺序排列它们,所以我想 doclet 将它们放入申报单。
You may think about using Javadoc with a custom Doclet, but this requires the source to be available.
There still is no guarantee about the order in the API (methods, fields, but every javadoc output I've ever seen has them in the right order, so I suppose the doclets get them in declaration order.
您将无法从类文件中获取信息。正如亚当在回答其他问题时所说:
其中“无申报单”包括“无申报单”。
我曾经使用 Java 源文件解析器来获取代码生成器的输入数据。这样您就可以按声明顺序获得字段和方法。
You won't be able to get the information from the class file. As Adam said in an answer to the refrenced other question:
And "no order" includes "no declaration order".
I once used a Java source file parser to get input data for code generators. And this way you'll have fields and methods in declaration order.