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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With