Mak*_*kky 5 java reflection primitive class
我有一种情况,我必须改变java常量.
我有以下代码工作
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
public class Main {
    public static final Integer FLAG = 44;
    static void setFinalStatic(Class<?> clazz, String fieldName, Object newValue) throws NoSuchFieldException, IllegalAccessException {
        Field field = clazz.getDeclaredField(fieldName);
        field.setAccessible(true);
        Field modifiers = field.getClass().getDeclaredField("modifiers");
        modifiers.setAccessible(true);
        modifiers.setInt(field, field.getModifiers() & ~Modifier.FINAL);
        field.set(null, newValue);
    }
    public static void main(String... args) throws Exception {
        System.out.printf("Everything is %s%n", FLAG);
        setFinalStatic(Main.class, "FLAG", 33);
        System.out.printf("Everything is %s%n", FLAG);
    }
}
如果我在上面运行,我得到以下输出:
Everything is 44
Everything is 33
但是,如果我将FLAG变量更改为int即
public static final int FLAG = 44;
这是行不通的.输出是:
Everything is 44
Everything is 44
有没有其他方法可以使它与PrimitiveType一起使用int.
原始类型或类型String的变量,最终并使用编译时常量表达式(第15.28节)初始化,称为a
constant variable.
第13.1节也说(强调我的)
3 .. 对常量变量字段(第4.12.4节)的引用在编译时被解析为表示的常量值.二进制文件中的代码中不应存在对此类字段的引用(包含该字段的类或接口除外,该字段将具有初始化它的代码).这样的字段必须总是看似已经初始化(§12.4.2); 绝不能遵守此类字段类型的默认初始值.
这意味着来自常量变量的编译时常量表达式将由编译器直接放入代码中(它将被内联),而不是在运行时从最终引用中读取.
例如,如果您main从Bar类执行方法
class Foo{
    static{
        System.out.println("test if class will be loaded");
    }
    public static final int x = 42;
}
class Bar{
    public static void main(String [] args){
        System.out.println(Foo.x);
    }
}
您将看不到Foo类的静态块的输出,这意味着Foo类尚未加载,这意味着该值Foo.x不是来自此类.实际上Bar是这样编译的
class Bar{
    public static void main(String [] args){
        System.out.println(42); // reference Foo.x will be removed by compiler 
                                // and replaced with actual value because
                                // compiler assumes that value can't/shouldn't
                                // change at runtime
    }
}
因此,即使Foo.x在运行时更改值也不会影响类中main方法中打印的值Bar.
你无法改变这种机制.
可能的方法是使用在运行时创建的值初始化最终字段(它们在编译时不存在,这将阻止它们成为编译时常量表达式).而不是
public static final String x = "foo";
尝试
public static final String x = new String("foo");
或者在原始类型的情况下使用取消装箱而不是
public static final int x = 42;
使用
public static final int x = new Integer(42);
| 归档时间: | 
 | 
| 查看次数: | 292 次 | 
| 最近记录: |