mercredi 25 août 2021

How can I reflectively get parameter names for a method included with Java SE?

I'm looking to create some code designed for static imports based on classes in Java SE 8 (specifically, with regards to threeten-extra#166).

As a first pass, I'm automatically generating the Java code for methods based on static factory methods in a specific set of classes. My hope is to ensure I don't miss anything, reduce the chance for manual error, as well as eliminate repetitive copy/pasting on my part.

I am using the Java reflection API to retrieve Method objects for the methods I want to automatically generate code for. I am then generating a method signature using that Method object.

For instance, for the LocalDate.of(int year, int month, int dayOfMonth) method, I would want something like this:

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

Of key importance, I want to ensure that my generated Java code signature has parameter names that are the same as those in the JDK. I know that Java has the ability to get parameter names for a method using Parameter.getName(). However, the method parameter names are not guaranteed to be present; .class files do not store them by default (the -parameters option to javac will cause them to be included). For my particular case, the parameter names are in Java, which (for my version at least), does not have them compiled in.

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("}");

Output:

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

I attempted to use the Paranamer library to read the argument names from the Java 8 Javadoc, but it appears that it does not support the Java 8 Javadoc HTML format (paranamer#39).

I am currently using SDKMAN! on macOS to manage the version of Java, which is AdoptOpenJDK 8.x. Given that the methods should be identical across Java versions, it would not need to be this specific version of Java 8, though it would have to be a version of Java 8.

How can I get the parameter names of a Method for built-in Java SE 8 classes in this situation?





Aucun commentaire:

Enregistrer un commentaire