我试图使用Java反射遵循这个Change private static final字段
但由于某种原因,我得到了java.lang.IllegalAccessException: Can not set static final java.lang.Long field DataRepositoryTests.Item.id to java.lang.Integer
for (Field field : Table.getDeclaredFields()){
System.out.println(Table.getSimpleName()); //prints "Item"
field.setAccessible(true);
if (field.getName().equals(GeneratedValueFields.get(i).getName())) {
System.out.println(field.getName()); //prints "id"
Field modifiersField = Table.getDeclaredField(GeneratedValueFields.get(i).getName());
System.out.println(modifiersField.getName()); //prints "id" as expected
modifiersField.setAccessible(true);
modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL); //error here
//data = 9 (Long)
field.set(null,data);
};
现在,如果我删除线路modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL);
我得到java.lang.IllegalAccessException: Can not set static final java.lang.Long field DataRepositoryTests.Item.id to java.lang.Long
如果我将字段更改为私有最终字段并指定一个对象
field.set(TableModel,data);
工作正常
使用Java反射的Change private static final字段中的代码在Java 1.8中有效,但在Java 17中无效。
在Java17中,jdk.internal.reflect.Reflection
类包含一个类的映射,这些类的一些或所有成员应该对反射不可见:
/** Used to filter out fields and methods from certain classes from public
view, where they are sensitive or they may contain VM-internal objects.
These Maps are updated very rarely. Rather than synchronize on
each access, we use copy-on-write */
private static volatile Map<Class<?>, Set<String>> fieldFilterMap;
...
private static final String WILDCARD = "*";
public static final Set<String> ALL_MEMBERS = Set.of(WILDCARD);
static {
fieldFilterMap = Map.of(
Reflection.class, ALL_MEMBERS,
...
);
...
}
因此,该示例将不适用于较新的JDK。
自Java 12以来,情况一直如此:https://bugs.java.com/bugdatabase/view_bug.do?bug_id=8210496