2013-03-22 10 views
6

बाद java.lang.System वर्ग से कोड है (JDK संस्करण 1,6)अजीब 'बाहर' चर, println()

public final static PrintStream out = nullPrintStream(); //out is set to 'null' 

private static PrintStream nullPrintStream() throws NullPointerException { 
    if (currentTimeMillis() > 0) { 
     return null; 
    } 
    throw new NullPointerException(); 
} 

जब हम अपने कोड में System.out.println("Something"); तो लिखना क्यों डॉन ' टी हम NullPointerException यहाँ तक कि जब 'बाहर' 'अशक्त' पर सेट है मिल

किसी भी तरह out प्रणाली कक्षा में

public static void setOut(PrintStream out) { 
    checkIO(); 
    setOut0(out); 
} 

setOut विधि निम्नलिखित के माध्यम से स्थापित किया जाएगा वे एन जेएलएस को nullPrintStream विधि क्यों चाहिए?

+0

'if (currentTimeMillis()> 0) {वापसी शून्य; } '=> यह वास्तव में अजीब है .. जेडीके 7 में, यह बस है: 'सार्वजनिक अंतिम स्थैतिक प्रिंटस्ट्रीम आउट = शून्य;'। – assylias

+1

@assylias यह जैवैक/जेआईटी कंपाइलर्स के पिछले संस्करणों को शांत करने के लिए सब कुछ है। इसके बिना 'अगर' कंपाइलर को एहसास हो सकता है कि यह हमेशा खराब होता है और सभी खराब परिणामों के साथ संकलन-समय निरंतर के रूप में 'आउट' को संकलित करता है। –

+0

इसका मतलब है कि 'currentTimeMillis() 'के मान को' लम्बी 'के लिए अधिकतम मान ओवरफ्लो करने के लिए पर्याप्त समय बीत चुका है, जावा 7 से पुराने वर्चुअल मशीनों के साथ चल रहे सभी एप्लिकेशन एक त्रुटि के साथ विफल हो जाएंगे:' java.lang ।ExceptionInInitializerError java.lang.NullPointerException द्वारा java.lang.System.nullPrintStream (अज्ञात स्रोत) 'या इसी तरह के कारण हुआ। – gparyani

उत्तर

8

private static void initializeSystemClass() पर एक नजर डालें - इस विधि चीजों को शुरू करने के लिए कहा जाता है, यह कहता है setOut0() जो native विधि है। यह Stream से जुड़ा हुआ है जहां यह माना जाता है।

तो भले ही क्षेत्र लग सकता हैpublic static final यह वास्तव में, native कोड यह परिवर्तन नहीं है।

संपादित

ओपी क्यों JLS nullPrintStream विधि की जरूरत है पूछता है तो फिर?

यह जावा संकलक के साथ क्या करना है - यह "इनलाइन" static final क्षेत्रों वे कुछ संकलन समय पर निरंतर, null की तरह करने के लिए आवंटित कर रहे हैं होगा। कंपाइलर वास्तव में निरंतर के साथ क्षेत्र में प्रत्येक संदर्भ को प्रतिस्थापित करेगा।

यह प्रारंभिकता को तोड़ देगा क्योंकि ऑब्जेक्ट्स Stream पर संदर्भ नहीं रखेंगे लेकिन null पर संदर्भित नहीं होंगे। किसी विधि की वापसी के लिए स्ट्रीम को असाइन करना इनलाइनिंग को रोकता है।

कुछ इसे एक गंदे हैक कह सकते हैं। बिस्मार्क को गलत तरीके से मिटाने के लिए "जेडीके सॉसेज की तरह है, यह देखना सर्वोत्तम नहीं है"।

+0

हालांकि ऊपर टिप्पणी के अनुसार, जावा 7 में इसे संशोधित किया गया है - इसलिए इसे मार्को द्वारा संकेतित पुराने कंपाइलर्स के साथ करें। – assylias

+0

वे 'सार्वजनिक अंतिम स्थैतिक प्रिंटस्ट्रीम आउट = शून्य;' परिभाषित कर सकते थे। स्थिर अंतिम क्षेत्र "lnline" को समझने में मदद करें। – AmitG

+2

@AmitG [इस] पर एक नज़र डालें (http://stackoverflow.com/questions/5173372/java-static-final-values-replaced-in-code-when-compiling) और [यह] (http: // docs.oracle.com/javase/specs/jls/se7/html/jls-13.html#jls-13.4.9)। यदि आप कुछ संकलन समय के रूप में कुछ परिभाषित करते हैं तो (जावा 6) कंपाइलर कोड को अनुकूलित करने के लिए उस जानकारी का उपयोग करेगा - यह शाब्दिक के साथ किसी भी संदर्भ को प्रतिस्थापित करेगा। तो कुछ भी जो 'System.out' कहता है उसे कंपाइलर द्वारा' शून्य 'के साथ प्रतिस्थापित किया जाएगा क्योंकि यह मानता है कि' System.out' बदल नहीं सकता क्योंकि यह 'शून्य' पर सेट है और यह 'अंतिम' है। एक सुंदर स्पष्टीकरण के लिए –

2

यह ठीक है कि System.out क्लास का आकलन कैसे किया जाता है।

private static native void setOut0(PrintStream out); 

निम्नलिखित में से कौन विधि में कहा जाता है::

भी एक विधि है

private static void initializeSystemClass() { 
2

System.in, out, और err को देशी कोड से JVM द्वारा प्रबंधित किया जाता है। नलप्रिंटस्ट्रीम() के साथ यह पूरा जादू इन क्षेत्रों को रेखांकित करने से जावैक रखने के लिए था। चूंकि जावा 7 यह

public final static PrintStream out = null; 
संबंधित मुद्दे