获取声明的方法,使它们出现在源代码中

时间:2010-06-30 10:20:58

标签: java reflection

情况似乎异常,但我被要求构建序列化程序,它将通过连接“get”方法的结果将对象解析为字符串。这些值的显示顺序与它们在源代码文件中声明的“get”等效顺序相同。

所以,例如,我们有

 Class testBean1{
  public String getValue1(){
   return "value1";
  }

  public String getValue2(){
   return "value2";
  }
 }

结果应为:

"value1 - value2"

不是

"value2 - value1"

根据文档,无法使用Class对象完成。但我想知道我是否可以在“* .class”文件中找到这些信息还是丢失了?如果存在这样的数据,也许有人知道为此目的准备使用的工具?如果无法找到此类信息,请提出最实用的方法来实现目标。我想过要为应该序列化的类的getter添加一些自定义注释。

5 个答案:

答案 0 :(得分:3)

如果您需要,则必须解析源代码,而不是字节代码。

有许多库将源文件解析为节点树,我最喜欢的是javaparser(托管在code.google.com上),在稍微修改过的版本中,它也被春天roo。

the usage page上,你可以找到一些样本。基本上,您将需要使用侦听MethodDefinitions的访问者。

答案 1 :(得分:1)

我认为这些信息不会被保留。

例如,

JAXB具有@XmlType(propOrder="field1, field2"),您可以在其中定义字段在序列化为xml时的顺序。你可以实现类似的东西

答案 2 :(得分:1)

虽然反射不再存在(我认为java 7),它们按照它们在源代码中出现的顺序给出了方法,但是类文件似乎仍然(从Java 8开始)包含顺序中的方法它们出现在源代码中。

因此,您可以解析类文件以查找方法名称,然后根据找到每个方法的文件偏移量对方法进行排序。

如果你想以一种不那么hacky的方式做到这一点,你可以使用Javassist,它将为你提供每个声明方法的行号,这样你就可以按行号对方法进行排序。

答案 3 :(得分:0)

将自定义注释写入商店订购数据,然后使用Method.getAnnotation(Class annotationClass)

答案 4 :(得分:0)

编辑:这仅适用于具体类(要检查的类具有自己的.class文件)。我更改了下面的代码以反映这一点。在深入了解ClassFileAnalyzer库以直接使用类而不是从临时文件中读取它们之前,存在这种限制。

以下方法对我有用:

下载并导入libarary ClassFileAnalyzer

添加以下两个静态方法(注意!getClussDump()需要稍微修改才能将类文件写入临时文件:我在这里删除了我的代码,因为它在这一点上非常特殊):

public static String getClassDump(Class<?> c) throws Exception {
    String classFileName = c.getSimpleName() + ".class";
    URL resource = c.getResource(classFileName);
    if (resource == null) {
        throw new RuntimeException("Works only for concreate classes!");
    }
    String absolutePath = ...; // write to temp file and get absolute path
    ClassFile classFile = new ClassFile(absolutePath);
    classFile.parse();
    Info infos = new Info(classFile, absolutePath);
    StringBuffer infoBuffer = infos.getInfos();
    return infoBuffer.toString();
}

public static <S extends List<Method>> S sortMethodsBySourceOrder(Class<?> c, S methods) throws Exception {
    String classDump = getClassDump(c);
    int index = classDump.indexOf("constant_pool_count:");
    final String dump = classDump.substring(index);
    Collections.sort(methods, new Comparator<Method>() {
    public int compare(Method o1, Method o2) {
        Integer i1 = Integer.valueOf(dump.indexOf(" " + o1.getName() + lineSeparator));
        Integer i2 = Integer.valueOf(dump.indexOf(" " + o2.getName() + lineSeparator));
        return i1.compareTo(i2);
    }});
    return methods;
}

现在你可以使用任何方法列表调用sortMethodsBySourceOrder(因为排序数组不是很舒服),你将获得重新排序的列表。

它的工作原理是查看类转储常量池,而这可以由库确定。

格尔茨, GHAD