2012-12-31 15 views
5

Son zamanlarda Change private static final field using Java reflection tökezledim ve poligonalubricants 'EverythingIsTrue sınıfını test ettim, iyi çalışıyor, System.out.format("Everything is %s", false); baskıları Everything is true gerçekten. BenJava yansımasını kullanarak statik final alanını değiştiremez misiniz?

public class EverythingIsTrue { 

    public static final boolean FALSE = false; 

    static void setFinalStatic(Field field, Object newValue) throws Exception { 
     field.setAccessible(true); 
     Field modifiersField = Field.class.getDeclaredField("modifiers"); 
     modifiersField.setAccessible(true); 
     modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL); 
     field.set(null, newValue); 
    } 

    public static void main(String[] args) throws Exception { 
     setFinalStatic(EverythingIsTrue.class.getField("FALSE"), true); 
     System.out.format("Everything is %s", FALSE); 
    } 
} 

olarak kodunu değiştirmek Ama ne zaman

herkes neden biliyor mu

Everything is false 
yazdırır? SetFinalStatic aslında çalışıyor mu, değil mi?

cevap

13

İlkel statik son alanlara erişilirken, Java derleyici, değerin sabit olduğunu ve alana erişen kod oluşturmak yerine değeri satır içi olarak üstlenir. Bu, derleyicinin false değeriyle FALSE alanına başvurusuyla değiştirileceği anlamına gelir. Alana erişmek için yansıma kullanırsanız, alanın değerinin gerçekten değiştiğini görürsünüz.

Bu, ilkel olmayan alanlar için çalışmayacaktır, çünkü bir nesne referansının değeri derleme zamanında belirtilemez.

+1

- sadece daha sözlerle! – dty

+0

@dty bu, sonsuz sayıda kelime bile gibi görünüyor;) –

+0

Sizin cevabınız kabul edildi ve benimki hiçbir değer eklemediğinden silindi - sadece kıskançlık! ;-) – dty

17

Değeri, bir yöntem çağrısının bir sonucu, bir manken bile olsa, derleyici inline etmekten kaçınabilirsiniz. aynen benim gibi aynı cevaptır

public class Main { 
    // value is not known at compile time, so not inlined 
    public static final boolean FLAG = Boolean.parseBoolean("false"); 

    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", true); 
     System.out.printf("Everything is %s%n", FLAG); 
    } 
} 

baskılar

Everything is false 
Everything is true 
+0

Bu harika! Jenerik bir yöntem kullanarak, ilkel olmayanlar için kukla bir yöntem oluşturabilirsiniz statik T placeHolder() {return null; } ' – flakes

+0

@ mc-imparator, eski sürüm daha okunabilir oldu. – dit

+0

@dit Konsol çıkışı, bu yüzden kaynak kodmuş gibi biçimlendirilmemelidir. –

İlgili konular