2012-12-31 8 views
5

मैंने हाल ही में Change private static final field using Java reflection पर ठोकर खाई और polygenelubricants 'EverythingIsTrue कक्षा का परीक्षण किया, ठीक काम करता है, System.out.format("Everything is %s", false); प्रिंट Everything is true वास्तव में प्रिंट करता है। लेकिन जब मैं के रूप मेंजावा प्रतिबिंब का उपयोग कर स्थैतिक अंतिम क्षेत्र को बदल नहीं सकते?

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); 
    } 
} 

कोड बदलने यह प्रिंट

Everything is false 

किसी को भी पता है क्यों? क्या फाइनलस्टैटिक वास्तव में काम करता है या नहीं?

उत्तर

13

जब आदिम स्थिर अंतिम क्षेत्रों तक पहुँचने, जावा कम्पाइलर को लगता है कि मूल्य स्थिर है और इसके बजाय कोड है कि क्षेत्र तक पहुँचता पैदा करने की मूल्य इनलाइन होगा। इसका मतलब है कि संकलक मूल्य false साथ FALSE क्षेत्र के संदर्भ में बदल देगा। यदि आप फ़ील्ड तक पहुंचने के लिए प्रतिबिंब का उपयोग करते हैं, तो आप देखेंगे कि फ़ील्ड का मान वास्तव में बदल गया है।

यह गैर-आदिम फ़ील्ड के लिए काम नहीं करेगा, क्योंकि किसी ऑब्जेक्ट संदर्भ के मान को संकलित समय पर रेखांकित नहीं किया जा सकता है।

+1

वास्तव में मेरा रूप में एक ही जवाब है कौन - केवल अधिक शब्दों के साथ! – dty

+0

@dty ऐसा लगता है कि यह अनंत अधिक शब्दों भी कर रहे हैं! ;-) –

+0

) मैं अपने उत्तर हटा दिया गया था के रूप में स्वीकार कर लिया गया तुम्हारा और मेरा किसी भी ख़ास नहीं कर पा रहा था - केवल संक्षिप्तता; – dty

17

आप मूल्य एक विधि कॉल, यहां तक ​​कि एक डमी एक का एक परिणाम बनाकर संकलक इनलाइनिंग बच सकते हैं।

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); 
    } 
} 

प्रिंट

Everything is false 
Everything is true 
+0

यह कमाल है! एक सामान्य विधि कर सकते हैं गैर पुरातन 'स्थिर टी प्लेसहोल्डर() {वापसी अशक्त के लिए एक डमी विधि बनाने का उपयोग करके आप; } ' – flakes

+0

@ एमसी-सम्राट, पूर्व संस्करण अधिक पठनीय था। – dit

+0

@dit यह कंसोल आउटपुट है, इसलिए इसे स्वरूपित नहीं किया जाना चाहिए जैसे कि यह स्रोत कोड था। –

संबंधित मुद्दे