प्रश्न 1:
निम्नलिखित कोड रिटर्न स्टेटमेंट के बिना संकलन क्यों करता है?
public int a()
{
while(true);
}
यह JLS§8.4.7 द्वारा कवर किया गया है :
यदि किसी विधि को रिटर्न प्रकार (.48.4.5) घोषित किया जाता है, तो कंपाइल-टाइम त्रुटि तब होती है जब विधि का शरीर सामान्य रूप से पूरा हो सकता है (.114.1)।
दूसरे शब्दों में, रिटर्न प्रकार के साथ एक विधि को केवल रिटर्न स्टेटमेंट का उपयोग करके वापस लौटना चाहिए जो मूल्य वापसी प्रदान करता है; विधि को "उसके शरीर के अंत को छोड़ने" की अनुमति नहीं है। विधि बॉडी में रिटर्न स्टेटमेंट के बारे में सटीक नियमों के लिए statements14.17 देखें।
एक विधि के लिए रिटर्न टाइप करना संभव है और फिर भी कोई रिटर्न स्टेटमेंट नहीं है। यहाँ एक उदाहरण है:
class DizzyDean {
int pitch() { throw new RuntimeException("90 mph?!"); }
}
चूंकि कंपाइलर जानता है कि लूप कभी भी समाप्त नहीं होगा ( true
यह हमेशा सच है, निश्चित रूप से), यह जानता है कि फ़ंक्शन "सामान्य रूप से वापस नहीं" हो सकता है (इसके शरीर के अंत को छोड़ दें), और इस तरह यह ठीक है कि नहीं return
।
प्रश्न 2:
दूसरी ओर, निम्न कोड क्यों संकलित करता है,
public int a()
{
while(0 == 0);
}
हालांकि निम्नलिखित नहीं है।
public int a(int b)
{
while(b == b);
}
में 0 == 0
मामला है, संकलक जानता है कि पाश समाप्त कभी नहीं होगा (कि 0 == 0
हमेशा सच हो जाएगा)। लेकिन यह पता नहीं है कि के लिए b == b
।
क्यों नहीं?
कंपाइलर निरंतर अभिव्यक्तियों (.215.28) को समझता है । उद्धरण ( 15.2 - अभिव्यक्ति के रूप (क्योंकि अजीब तरह से यह वाक्य .215.28 में नहीं है) :
कुछ अभिव्यक्तियों में एक मूल्य होता है जिसे संकलन समय पर निर्धारित किया जा सकता है। ये निरंतर अभिव्यक्ति हैं (.215.28)।
आपके b == b
उदाहरण में, क्योंकि इसमें एक चर शामिल है, यह एक स्थिर अभिव्यक्ति नहीं है और इसे संकलन समय पर निर्धारित नहीं किया गया है। हम देख सकते हैं कि यह इस मामले में हमेशा सही साबित होने वाला है (हालाँकि यदि b
क double
, जैसा कि QBrute ने कहा है , तो हमें आसानी से मूर्ख बनाया जा सकता है Double.NaN
, जो कि स्वयं नहीं ==
है ), लेकिन JLS केवल यह निर्दिष्ट करता है कि लगातार अभिव्यक्तियाँ संकलन समय पर निर्धारित की जाती हैं , यह संकलक को गैर-स्थिर अभिव्यक्तियों का मूल्यांकन करने की कोशिश करने की अनुमति नहीं देता है। bayou.io ने इसके लिए एक अच्छा बिंदु क्यों नहीं उठाया : यदि आप संकलन समय पर चर को शामिल करने वाले भावों को निर्धारित करने की कोशिश के लिए नीचे जाना शुरू करते हैं, तो आप कहां रुकते हैं? b == b
स्पष्ट है (एर, गैर के लिएNaN
मान), लेकिन किस बारे में a + b == b + a
? या (a + b) * 2 == a * 2 + b * 2
? स्थिरांक पर रेखा खींचना समझ में आता है।
इसलिए चूंकि यह अभिव्यक्ति को "निर्धारित" नहीं करता है, इसलिए संकलक को पता नहीं है कि लूप कभी भी समाप्त नहीं होगा, इसलिए यह सोचता है कि विधि सामान्य रूप से वापस आ सकती है - जो इसे करने की अनुमति नहीं है, क्योंकि इसका उपयोग करना आवश्यक है return
। तो यह एक की कमी के बारे में शिकायत करता है return
।