Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Record cannot get parameter names from constructors?

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.

like image 744
sproketboy Avatar asked Apr 10 '21 18:04

sproketboy


Video Answer


1 Answers

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.

like image 73
Brian Goetz Avatar answered Oct 16 '22 15:10

Brian Goetz