ओवरलोड विधि से बाइट तर्क पारित करना


12

मैंने कुछ क्विज़ से यह कोड स्निपेट लिया, IDE का उपयोग करके मैंने इसे निष्पादित किया और एक परिणाम प्राप्त किया लंबा, लंबा लेकिन सही उत्तर है बाइट, बाइट , मुझे अलग परिणाम क्यों मिला? प्रश्न JDK 11 से संबंधित है

public class Client {
    static void doCalc(byte... a) {
        System.out.print("byte...");
    }

    static void doCalc(long a, long b) {
        System.out.print("long, long");
    }

    static void doCalc(Byte s1, Byte s2) {
        System.out.print("Byte, Byte");
    }

    public static void main(String[] args) {
        byte b = 5;
        doCalc(b, b);
    }
}

संपादित:

यहाँ कोड लिया गया था: Oracle प्रमाणन अवलोकन और नमूना प्रश्न (पृष्ठ: 13, प्रश्न: 5)


1
क्या आपको यकीन है कि यह Byte b = 5;राजधानी बी के साथ नहीं है
जोप एगेन

4
मैं long, longJava8 पर भी FYI करवाता हूं ... यकीन नहीं होता कि ईमानदार क्यों हूं , जवाब का इंतजार भी करना होगा :)
sp00m

जवाबों:


6

इसलिए, यदि आप संकलन समय पर विधि हस्ताक्षर निर्धारित करने के लिए जावा भाषा विनिर्देश के माध्यम से जाते हैं, तो यह स्पष्ट हो जाएगा:

  1. पहला चरण (.1215.12.2.2) बॉक्सिंग या अनबॉक्सिंग रूपांतरण की अनुमति के बिना या वैरिएबल एरिटी विधि आह्वान के उपयोग के बिना अधिभार संकल्प करता है। यदि इस चरण के दौरान कोई लागू विधि नहीं मिलती है तो प्रसंस्करण दूसरे चरण में जारी रहता है।

  2. दूसरा चरण (.1215.12.2.3) बॉक्सिंग और अनबॉक्सिंग की अनुमति देते हुए ओवरलोड रिज़ॉल्यूशन करता है, लेकिन फिर भी वेरिएबल एरिटी मेथड इनवोकेशन के उपयोग को रोकता है। यदि इस चरण के दौरान कोई लागू विधि नहीं मिली है तो प्रसंस्करण तीसरे चरण में जारी है।

  3. तीसरा चरण (.1215.12.2.4) ओवरलोडिंग को वैरिएबल एरिटी मेथड, बॉक्सिंग और अनबॉक्सिंग के साथ जोड़ा जा सकता है।

तो, उपरोक्त चरणों से, यह स्पष्ट है कि आपके मामले में पहले चरण में जावा कंपाइलर एक मिलान विधि प्राप्त करेगा जो करता है doCalc(long a,long b)। आपके तरीके doCalc(Byte s1, Byte s2)को कॉल के दौरान एक ऑटोबॉक्सिंग की आवश्यकता होती है, इसलिए इसे कम वरीयता मिलेगी।


1
यह longस्वीकार करना कि क्यों स्वीकार करता है byte, एक व्यापक आदिम रूपांतरण का पालन करता है : docs.oracle.com/javase/specs/jls/se7/html/jls-5.html#jls-5.1.2 । तो बुनियादी तौर पर, +widening -boxing -varargsतो +widening +boxing -varargsफिर +widening +boxing +varargs
sp00m

@kbo आपको क्यों लगता है कि सही उत्तर है Byte, Byte?
अमित बेरा

3
@kbo मुझे लगता है कि सही उत्तर गलत है :) यदि आप कर सकते हैं तो इस सवाल के लिए लेखकों को इंगित करने के लायक हो सकता है।
sp00m

3
@ sp00m मुझे ओरेकल के नमूनों में यह प्रश्न मिला, कृपया संपादित भाग पर एक नज़र डालें
kbo

@kbo वाह ... फिर आगे बढ़ने का कोई विचार नहीं!
sp00m

2

कृपया रूपांतरणों पर जेएलएस अध्याय को पढ़ें ।

आपके मामले में क्या हो रहा है कि रनटाइम के दौरान, जेवीएम एक व्यापक रूपांतरण करने का विकल्प चुनता byte -> longहै क्योंकि यह रूपांतरण सुरक्षित है क्योंकि यह गारंटी है कि इसका कारण नहीं है RuntimeException

से परिवर्तित byteकरने के लिए Byteभी कहा जाता है मुक्केबाजी में परिणाम कर सकते OutOfMemoryError के रूप में JVM ढेर पर नई वस्तुओं के आवंटन के लिए है:

यदि एक रैपर क्लासेस (बुलियन, बाइट, कैरेक्टर, शॉर्ट, इंटेगर, लॉन्ग, फ्लोट, या डबल) में से एक का एक नया उदाहरण आवंटित किया जाए और अपर्याप्त स्टोरेज उपलब्ध हो तो एक बॉक्सिंग रूपांतरण का परिणाम हो सकता है।

उस वजह से, सुरक्षित byte -> long व्यापक रूपांतरण को प्राथमिकता दी जाती है।


2
बस ध्यान दें, बॉक्सिंग कभी भी कारणों byteसे Byteनहीं होती है OutOfMemoryException, क्योंकि Byte(-128 - 127) के सभी मूल्य आंतरिक रूप से कैश हैं। लेकिन यह अन्य प्रकारों के साथ समान नहीं हो सकता है, इसलिए अंगूठे के नियम के रूप में, व्यापक रूपांतरण को प्राथमिकता मिलती है।
पावेल स्मिरनोव

1

सही अधिभार खोजने के लिए, आदेश है:

  1. मापदंडों की संख्या से
  2. मुक्केबाजी / unboxing
  3. वैरेडिक पैरामीटर

इसलिए

  • अगर bजहां Byteपरिणाम होगा Byte, Byte
  • यदि उत्तीर्ण होता तो new byte[] { b, b }परिणाम होता byte, byte
  • यदि दो बाइट बी पास की जाती हैं, तो बाइट से इंट तक लंबे समय तक चौड़ीकरण संभव है और इसका परिणाम है long, long
  • जब लंबे, लंबे अधिभार को हटा दिया जाता है, तो Byte, Byteपरिणाम।
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.