1

我正在寻找一些为基于 Java SE 8 中的类(特别是关于threeten-extra#166)的静态导入而设计的代码。

作为第一步,我将自动为基于一组特定类中的静态工厂方法的方法生成 Java 代码。我希望确保我不会错过任何东西,减少手动错误的机会,并消除我重复的复制/粘贴。

我正在使用 Java 反射 API 来检索Method要为其自动生成代码的方法的对象。然后我使用该Method对象生成方法签名。

例如,对于该LocalDate.of(int year, int month, int dayOfMonth)方法,我想要这样的东西:

public static LocalDate date(int year, int month, int dayOfMonth) {
    return LocalDate.of(year, month, dayOfMonth);
}

至关重要的是,我要确保生成的 Java 代码签名具有与 JDK 中相同的参数名称。我知道 Java 能够使用Parameter.getName(). 但是,方法参数名称不保证存在;.class默认情况下,文件不存储它们(-parameters选项javac将导致它们被包含在内)。对于我的特殊情况,参数名称是在 Java 中,它(至少对于我的版本)没有编译它们。

Method method = LocalDate.class
        .getMethod("of", int.class, int.class, int.class);

System.out.printf("public static %s date(%s) {\n",
        method.getReturnType().getSimpleName(),
        Arrays.stream(method.getParameters())
                .map(p -> String.format("%s %s",
                        p.getType().getSimpleName(), p.getName()))
                .collect(Collectors.joining(", ")));
System.out.printf("    return %s.%s(%s);\n",
        method.getDeclaringClass().getSimpleName(),
        method.getName(),
        Arrays.stream(method.getParameters())
                .map(Parameter::getName)
                .collect(Collectors.joining(", ")));
System.out.println("}");

输出:

public static LocalDate date(int arg0, int arg1, int arg2) {
    return LocalDate.of(arg0, arg1, arg2);
}

我尝试使用Paranamer库从Java 8 Javadoc读取参数名称,但它似乎不支持 Java 8 Javadoc HTML 格式(paranamer#39)。

我目前正在使用SDKMAN!在 macOS 上管理 Java 的版本,即AdoptOpenJDK8.x。鉴于 Java 版本之间的方法应该相同,它不需要是 Java 8 的这个特定版本,尽管它必须是Java 8的一个版本。

Method在这种情况下,如何获取内置 Java SE 8 类的参数名称?

4

1 回答 1

0

只要方法信息存储在调试表中(例如不是抽象方法),BytecodeReadingParanamer就可以使用:

Paranamer paranamer = new CachingParanamer(new BytecodeReadingParanamer());

Class<?>[] parameterTypes = method.getParameterTypes();
String[] parameterNames = paranamer.lookupParameterNames(method);

System.out.printf("public static %s date(%s) {\n",
        method.getReturnType().getSimpleName(),
        IntStream.range(0, parameterTypes.length)
                .mapToObj(i -> String.format("%s %s",
                        parameterTypes[i], parameterNames[i]))
                .collect(Collectors.joining(", ")));
System.out.printf("    return %s.%s(%s);\n",
        method.getDeclaringClass().getSimpleName(),
        method.getName(),
        String.join(", ", parameterNames));
System.out.println("}");
于 2021-08-25T20:02:37.520 回答