【发布时间】:2023-01-27 02:58:36
【问题描述】:
我研究反射并尝试更改 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();
}
}
}
如果我将 Record 转换为 Class 一切正常,但是使用 Record 我会得到异常
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)
我必须做什么才能使代码与记录一起使用?
【问题讨论】:
-
您使用所需的更改创建新记录。您不能更改已经存在的实例。
-
你想要的是不可能的。
record对象是不可变的。充其量,你可以一个新的Account的实例应用了更改。如果Account对象存储在某处,则您可以使用这个新帐户实例覆盖存储帐户的任何字段(如果它不是final)。 -
Hotspot 信任记录中的最终字段 - 这就是您无法更改它们的原因。请参阅
Field.set的规范 - “如果基础字段是最终字段,则当且仅当满足以下条件时,此 Field 对象才具有写访问权限:......字段的声明类不是记录类。” -
怎么样...初始化构造函数中的字段?
-
@dan1st 我希望实现自己的 ORM(用于练习)并使用数据库中的数据创建记录。但是记录将有指向其他记录和记录列表的链接,然后我将不得不把记录创建彻底翻过来。这更难,我希望避免它。
标签: java reflection record