fun initTypeface( name:String, path :String) {
try {
val field = Typeface::class.java.getDeclaredField(name)
field.isAccessible = true
field.set(null, Typeface.createFromAsset(CoreApp.get().assets, path))
} catch (e: NoSuchFieldException) {
e.printStackTrace()
} catch (e: IllegalAccessException) {
e.printStackTrace()
}
}
上面代码是我的一个用来修改字体的方法。用到了反射修改Typeface
类中的字段。
/** The NORMAL style of the default serif typeface. */
public static final Typeface SERIF;
//...
static {
init();
// Set up defaults and typefaces exposed in public API
//..
SERIF = create("serif", 0);
//..
}
可以看到这个静态成员在初始化的时候就被赋值了。但是我的反射方法却有效果?的确修改掉了字段。
所以我就写了以下代码来看反射是否能修改字段。
//FinalTest
class FinalTest {
public static void main(String[] args) {
try {
Field field = TestHelper.class.getDeclaredField("ENTITY");
field.setAccessible(true);
Entity entity = new Entity("reflection name");
field.set(null, entity);
} catch (Exception e) {
e.printStackTrace();
}
System.out.println(TestHelper.getENTITY().name);
}
static class Entity {
public String name;
public Entity(String name) {
this.name = name;
}
}
}
//..TestHelper
class TestHelper {
private static final FinalTest.Entity ENTITY;
static {
ENTITY = new FinalTest.Entity("init name");
}
public static FinalTest.Entity getENTITY() {
return ENTITY;
}
}
想通过反射的方法修改TestHelper
中的ENTITY
字段,但是没有成功 。没有被修改掉。而且抛出了异常。
Can not set static final com.company.finaltest.Entity field
java.lang.IllegalAccessException: Can not set static final com.company.finaltest.Entity field com.company.finaltest.TestHelper.ENTITY to com.company.finaltest.Entity
at sun.reflect.UnsafeFieldAccessorImpl.throwFinalFieldIllegalAccessException(UnsafeFieldAccessorImpl.java:76)
at sun.reflect.UnsafeFieldAccessorImpl.throwFinalFieldIllegalAccessException(UnsafeFieldAccessorImpl.java:80)
at sun.reflect.UnsafeQualifiedStaticObjectFieldAccessorImpl.set(UnsafeQualifiedStaticObjectFieldAccessorImpl.java:77)
at java.lang.reflect.Field.set(Field.java:764)
at com.company.finaltest.FinalTest.main(FinalTest.java:13)
所以我就很奇怪,为什么一开始的代码可以修改掉final的值?
——————————
更新,是因为我的代码被编译器优化了?
kotlin不知道,但Java确实不允许修改静态常量字段的值,非静态的可以。