2016-03-26 14 views
9
int a = 2; 
int b = a + a; 

Class cache = Integer.class.getDeclaredClasses()[0]; 
Field myCache = cache.getDeclaredField("cache"); 
myCache.setAccessible(true); 

Integer[] newCache = (Integer[]) myCache.get(cache); 
newCache[132] = newCache[133]; 

System.out.printf("%d",b); // 5 
System.out.println(b); // 4 

यहाँ मैं अब cache[132] == 5 printf() विधि यह 5 ठीक प्रिंट में लेकिन println() में क्यों यह प्रिंट 4 यह 5 कारण उस पर पीछे क्या होना चाहिए इसका मतलब है कि cache[133] को cache[132] का मूल्य बदल?यहां विभिन्न आउटपुट का कारण क्या है?

+5

देख रहे हैं, आप पुस्तकालय वर्ग के अनियंत्रित आंतरिक के साथ झुका रहे हैं - आप यहां उचित व्यवहार की अपेक्षा क्यों करेंगे? –

+4

आप यहां वास्तविक प्रतिबिंब के लिए प्रतिबिंब का उपयोग कर रहे हैं। यह अस्पष्ट है कि आप ऐसा क्यों करना चाहते हैं या आप क्या करने की कोशिश कर रहे हैं। इसके अलावा, जब आप प्रतिबिंब का उपयोग करते हैं, तो वस्तु स्थिति और अपरिवर्तनीयता की बहुत सारी गारंटी तेजी से शून्य और शून्य हो जाती है, इसलिए सावधानी के साथ चलें। – Makoto

+0

यदि आप अच्छे कारण को नहीं जानते हैं लेकिन आप इसे "fiddling" नहीं कह सकते हैं @ ओलिवर चार्ल्सवर्थ –

उत्तर

6

println में एक अधिभार है जो int स्वीकार करता है। लाइन

System.out.println(b); 

int में इसलिए Integer.valueOf का उपयोग कर एक Object में बदला कभी नहीं किया गया है।

printf हस्ताक्षर

public PrintStream printf(String format, Object ... args) 

तो 4Integer वस्तु 5 (संशोधित कैश का उपयोग करके) के लिए autoboxed है है, और इसलिए 5 छपा है।

+1

यह रखता है। यही कारण है कि मैं इसे डीबगर में नहीं देख सका; जब 'printf' कहा जाता था तब ऑटोबॉक्स पहले से ही प्रभावी हो चुका था। – Makoto

1

बाद javap -verbose package.YourClassName

51: getstatic  #67     // Field java/lang/System.out:Ljava/io/PrintStream; 
    54: ldc   #73     // String %d 
    56: iconst_1 
    57: anewarray  #3     // class java/lang/Object 
    60: dup 
    61: iconst_0 
    62: iload_2 
    63: invokestatic #75     // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer; 
    66: aastore 
    67: invokevirtual #79     // Method java/io/PrintStream.printf:(Ljava/lang/String;[Ljava/lang/Object;)Ljava/io/PrintStream; 
    70: pop 
    71: getstatic  #67     // Field java/lang/System.out:Ljava/io/PrintStream; 
    74: iload_2 
    75: invokevirtual #85     // Method java/io/PrintStream.println:(I)V 
    78: return 

आप देखते हैं कि शिक्षा 63 में Integer.valueOf कहा जाता हो जाता है, इस प्रकार पूर्णांक कैश का उपयोग कर। बिंदु 75 println हस्ताक्षर एक वस्तु नहीं लेता है बल्कि एक प्रत्यक्ष आदिम int है, इसलिए कोई इंटीजर कैश शामिल नहीं है।

1

आप कोड

नीचे का प्रयास करें
System.out.println(Integer.valueOf(b)); 

आप देखेंगे 5 इस के लिए मुद्रित किया जा रहा। अब printf विधि के लिए आपके पास कोड नीचे है।

System.out.printf("%d",b); 

आप printf देखते हैं, तो पहले पैरामीटर और दूसरा पैरामीटर के रूप में वस्तु के रूप में स्ट्रिंग स्वीकार करता है। आपके पास बी आदिम प्रकार (int) है। ऑटो मुक्केबाजी होती है और इसके लिए Integer.java class method : valueOf(int i) का उपयोग किया जाता है।

यदि आप इंटीजर घोषित करते हैं तो आपको 4 मामलों में मुद्रित किया जाएगा क्योंकि कोई ऑटो मुक्केबाजी नहीं होती है। आम तौर पर -128 से 127 कैश किए जाते हैं और आपने आंतरिक कैश को संशोधित किया है। valueOf कैश का उपयोग करता है और यही कारण है कि आप अलग-अलग oputputs

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