I study reflection and try to change field's value in Record.
public record Account(Integer id, String login, Boolean blocked) {}
public class Main {
public static void main(String[] args) {
Account account = new Account(null, null, null);
setFieldValue(account, "id", 1);
setFieldValue(account, "login", "admin");
setFieldValue(account, "blocked", false);
System.out.println(account);
}
public static void setFieldValue(Object instance,
String fieldName,
Object value) {
try {
Field field = instance.getClass().getDeclaredField(fieldName);
field.setAccessible(true);
field.set(instance, value);
} catch (NoSuchFieldException | IllegalAccessException e) {
e.printStackTrace();
}
}
}
If I convert Record to Class everything works, but with Record I get Exception
java.lang.IllegalAccessException: Can not set final java.lang.Integer field Account.id to java.lang.Integer
at java.base/jdk.internal.reflect.UnsafeFieldAccessorImpl.throwFinalFieldIllegalAccessException(UnsafeFieldAccessorImpl.java:76)
at java.base/jdk.internal.reflect.UnsafeFieldAccessorImpl.throwFinalFieldIllegalAccessException(UnsafeFieldAccessorImpl.java:80)
at java.base/jdk.internal.reflect.UnsafeQualifiedObjectFieldAccessorImpl.set(UnsafeQualifiedObjectFieldAccessorImpl.java:79)
at java.base/java.lang.reflect.Field.set(Field.java:799)
What do I have to do to make the code work with records?
If for some reason you need a field of a record to be mutable, there is a workaround (not using reflection though). You can add methods to a record:
public record Account(Integer id, String login, Boolean blocked) {
public Account setLogin(String newLogin) {
return new Account(id, newLogin, blocked);
}
}
It doesn't update the record, but returns a new one with the field updated. So the variable needs to be reassigned to the result.
public static void main(String[] args) {
Account account = new Account(1, "admin", false);
System.out.println(account);
account = account.setLogin("root");
System.out.println(account);
}
output:
Account[id=1, login=admin, blocked=false]
Account[id=1, login=root, blocked=false]
If you need mutable fields, you probably should make it a class though.