CRecordComponent - Lenni0451/ClassTransform GitHub Wiki

The CRecordComponent annotation can be used to add a new field to a record class.
A getter and constructor will be generated for the field automatically.
The field will also be added to the automatically generated toString, equals and hashCode methods if they have not been specified manually.

Changing which methods get generated

The automatically generated methods can be individually disabled using the corresponding field.

Generated Annotation Field
Record component addRecordComponent
Constructor addConstructor
Getter addGetter
toString addToString
equals addEquals
hashCode addHashCode

All fields default to true.

Example

Original record class:

public record Test(String s) {
}

Transformer class:

@CTransformer(Test.class)
public class TestTransformer {
    @CRecordComponent
    private int i;
}

Transformed record class:

public record Test(String s, int i) {
    public Test(String s) {
        this(s, 0);
    }
}

Actual bytecode of the transformed class:

public record Test(String s, int i) {
    public Test(String s) {
        this.s = s;
    }

    public Test(String s, int i) {
        this.s = s;
        this.i = i;
    }

    public String s() {
        return this.s;
    }

    public int i() {
        return this.i;
    }

    @Override
    public String toString() {
        //This method is automatically by the compiler
        //The method call is normally done using a InvokeDynamic instruction
        return (String) ObjectMethods.bootstrap("toString", new MethodHandle[]{Test.class, "s;i", "s", "i"}, this);
    }

    @Override
    public boolean equals(Object other) {
        //This method is automatically by the compiler
        //The method call is normally done using a InvokeDynamic instruction
        return (boolean) ObjectMethods.bootstrap("equals", new MethodHandle[]{Test.class, "s;i", "s", "i"}, this, other);
    }

    @Override
    public int hashCode() {
        //This method is automatically by the compiler
        //The method call is normally done using a InvokeDynamic instruction
        return (int) ObjectMethods.bootstrap("hashCode", new MethodHandle[]{Test.class, "s;i", "s", "i"}, this);
    }
}