从 Field.set 的文档:
如果基础字段是 final,则该方法将为此字段引发一个 if,并且此字段是非静态的。IllegalAccessException
setAccessible(true)
所以一开始看来你运气不好,因为是.令人惊讶的是,有一种方法可以解决这个问题:只需通过反射使该领域不再存在。File.separatorChar
static
static
final
我从 javaspecialist.eu 中采用了这个解决方案:
static void setFinalStatic(Field field, Object newValue) throws Exception {
field.setAccessible(true);
// remove final modifier from field
Field modifiersField = Field.class.getDeclaredField("modifiers");
modifiersField.setAccessible(true);
modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL);
field.set(null, newValue);
}
我已经测试了它,它的工作原理:
setFinalStatic(File.class.getField("separatorChar"), '#');
System.out.println(File.separatorChar); // prints "#"
使用这种技术时要格外小心。撇开破坏性后果不谈,以下情况实际上有效:
setFinalStatic(Boolean.class.getField("FALSE"), true);
System.out.format("Everything is %s", false); // "Everything is true"
重要更新:上述解决方案并非在所有情况下都有效。如果该字段在重置之前可访问并通读反射,则会抛出 。它之所以失败,是因为反射 API 创建了缓存和重用的内部对象(请参阅 java.lang.reflect.Field#acquireFieldAccessor(布尔)实现)。失败的示例测试代码:IllegalAccessException
FieldAccessor
Field f = File.class.getField("separatorChar"); f.setAccessible(true); f.get(null);
// call setFinalStatic as before: throws IllegalAccessException