Record cannot get parameter names from constructors?
Asked Answered
A

1

13

Looking to see how to use Records with reflection under Java 16 (and 15 same behavior)

public record RecordTest2(int id, int something, double total, LocalDateTime createdOn) {

    public RecordTest2(int id, int something, double total) {
        this(id, something, total, LocalDateTime.now());
    }
}

Looking at the canonical constructor I do see the parameter names, but not in the other ones.

var recordTest2 = new RecordTest2(1, 2, 3.0, LocalDateTime.now());
Class<?> objectClass = recordTest2.getClass();

Constructor<?>[] constructors = objectClass.getConstructors();

for (Constructor<?> con : constructors) {
    System.out.println(con.getName());
    Parameter[] parameters = con.getParameters();
    for (Parameter parameter : parameters) {
        System.out.printf("param: %s\n", parameter.getName());
    }
}

output:

net.sf.persism.dao.records.RecordTest2
param: arg0
param: arg1
param: arg2
net.sf.persism.dao.records.RecordTest2
param: id
param: something
param: total
param: createdOn

Any work-around to this?

Edit: Just to dot the "I" here. I can use the @ConstructorProperties annotation from java.beans.

Aby answered 10/4, 2021 at 18:47 Comment(15)
I do realize that I could use javac -parameters but shouldn't this be a default anyway now?Aby
This works fine for me on Eclipse. How are you compiling your program?Capuche
@SotiriosDelimanolis - What do you mean by works fine for me on Eclipse? Do you mean you get a different output than param: arg0 param: arg1 param: arg2?Hugely
It doesn't really matter if it behaves differently on a particular IDE. Nobody is going to ship Eclipse along with Java to make it "work".Spherics
@Aby I don't think it is the default. But it's easy to find out: enable it, recompile your classes and check if the output changesRemonaremonetize
@arvind Yeah, the parameter names printed are the same as in the source code.Capuche
"Looking to see how to use Records with reflection" - why?Fingerstall
@SotiriosDelimanolis to second the question and to confirm that with javac version OpenJDK Runtime Environment (build 16-ea+29-2091), the behavior is the same as that mentioned in the question.Arcadia
@Fingerstall for this project sproket.github.io/PersismAby
@Aby you succeeded doing this with javac -parameters ?Barra
In JShell, the parameters are printed with their namesBarra
@YassinHajaj That's true. Interestingly on the same version of the JDK, the javac followed by java works differently from how jshell does!Arcadia
something that might be worth looking at could be the implementation of private native Parameter[] getParameters0() declared in Executable.javaArcadia
@Arcadia it does not really do much tbh JVM_GetMethodParameters(env, method)Barra
@YassinHajaj Yes. You need to specify it in maven/gradle and your IDE then clean/rebuildAby
F
24

This is working as designed. Parameter names in Java APIs are, in general, not something you can rely on to not change; they are an implementation detail, and by default, the compiler will not retain them in the classfile.

For the canonical constructor of a record, the parameter names must match the component names, and those are considered a part of the classes public API, and are therefore considered stable. So the compiler retains them in the classfile and reflection dutifully serves them up. The canonical constructor of a record is mandatory, and its form is specified by the language, so it is special in this way.

For the other constructors, neither the constructors nor the the parameter names have the same significance, so these are treated like ordinary members for purposes of the ParameterNames classfile attribute.

Felicle answered 11/4, 2021 at 18:25 Comment(3)
OK but the solution is to use javac -parameters and rebuild.Aby
@sprocketboy For a fairly strange meaning of the word "solution." I would suggest maybe maybe not writing code that won't run properly unless compiled with nonstandard build options.Felicle
Sorry I thought that was a standard. I can use the canonical only then. And why are spelling my name correctly?Aby

© 2022 - 2024 — McMap. All rights reserved.