java varargs और overloading के साथ बग?




variadic-functions (3)

समस्या यह है कि यह संदिग्ध है।

doIt(1, 2);

ऐसा करने के लिए एक कॉल हो सकता है doIt(int ...) , या doIt(double ...) । बाद के मामले में, पूर्णांक अक्षर को double मानों में बढ़ावा दिया जाएगा।

मुझे पूरा यकीन है कि जावा स्पेक कहता है कि यह एक अस्पष्ट निर्माण है, और संकलक सिर्फ spec द्वारा निर्धारित नियमों का पालन कर रहा है। (मुझे यह सुनिश्चित करने के लिए और आगे शोध करना होगा।)

संपादित करें - जेएलएस का प्रासंगिक हिस्सा " 15.12.2.5 सबसे विशिष्ट विधि का चयन करना " है, लेकिन यह मेरे सिर को चोट पहुंचा रहा है।

मुझे लगता है कि तर्क यह होगा कि void doIt(int[]) void doIt(double[]) से अधिक विशिष्ट (या इसके विपरीत) void doIt(double[]) क्योंकि int[] double[] (और इसके विपरीत) का उप प्रकार नहीं है। चूंकि दो ओवरलोड समान रूप से विशिष्ट हैं, इसलिए कॉल संदिग्ध है।

इसके विपरीत, void doItAgain(int) void doItAgain(double) से अधिक विशिष्ट है void doItAgain(double) क्योंकि int जेएलएस के अनुसार double उप प्रकार है। इसलिए, यह करने के लिए एक कॉल doItAgain(42) संदिग्ध नहीं है।

संपादित करें 2 - @ फिन्न सही है, यह एक बग है। 15.12.2.5 के इस भाग पर विचार करें (गैर-लागू मामलों को हटाने के लिए संपादित):

एम नामक एक परिवर्तनीय धैर्य सदस्य विधि एक ही नाम के किसी अन्य परिवर्तनीय धैर्य सदस्य विधि से अधिक विशिष्ट है यदि:

एक सदस्य विधि में एन पैरामीटर होते हैं और दूसरे के पास के पैरामीटर होते हैं, जहां n ≥ k। पहली सदस्य विधि के पैरामीटर के प्रकार टी 1 हैं,। । । , टीएन -1, टीएन [], अन्य विधि के पैरामीटर के प्रकार यू 1 हैं,। । । , ब्रिटेन -1, ब्रिटेन []। चलो Si = उई, 1 <= i <= k। फिर:

  • सभी जे से 1 से के -1 तक, टीजे <: एसजे, और,
  • सभी जे से के लिए एन, टीजे <: स्क

इसे उस मामले में लागू करें जहां n = k = 1, और हम देखते हैं कि ऐसा doIt(int[]) ऐसा करने से अधिक विशिष्ट है doIt(double[])

वास्तव में, इसके लिए एक bugs.sun.com/bugdatabase/view_bug.do?bug_id=6199075 है और सूर्य स्वीकार करता है कि यह वास्तव में एक बग है, हालांकि उन्होंने इसे "बहुत कम" के रूप में प्राथमिकता दी है । बग अब जावा 7 (बी 123) में फिक्स्ड के रूप में चिह्नित है।

जावा varargs कार्यान्वयन में एक बग प्रतीत होता है। विभिन्न प्रकार के vararg पैरामीटर के साथ विधि ओवरलोड होने पर जावा उपयुक्त प्रकार को अलग नहीं कर सकता है।

यह मुझे एक त्रुटि देता है The method ... is ambiguous for the type ...

निम्नलिखित कोड पर विचार करें:

public class Test
{
    public static void main(String[] args) throws Throwable
    {
        doit(new int[]{1, 2}); // <- no problem
        doit(new double[]{1.2, 2.2}); // <- no problem
        doit(1.2f, 2.2f); // <- no problem
        doit(1.2d, 2.2d); // <- no problem
        doit(1, 2); // <- The method doit(double[]) is ambiguous for the type Test
    }

    public static void doit(double... ds)
    {
        System.out.println("doubles");
    }

    public static void doit(int... is)
    {
        System.out.println("ints");
    }
}

docs कहते हैं: "आम तौर पर, आपको एक varargs विधि अधिभारित नहीं करना चाहिए, या प्रोग्रामर के लिए यह पता लगाना मुश्किल होगा कि ओवरलोडिंग कहलाती है।"

हालांकि वे इस त्रुटि का जिक्र नहीं करते हैं, और यह प्रोग्रामर नहीं है जो इसे मुश्किल लग रहे हैं, यह संकलक है।

विचार?

संपादित करें - कंपाइलर: सूर्य जेडीके 1.6.0 u18


दिलचस्प। सौभाग्य से, इस समस्या से बचने के लिए कुछ अलग तरीके हैं:

आप विधि हस्ताक्षर में बजाय रैपर प्रकार का उपयोग कर सकते हैं:

   public static void doit(Double... ds) {
       for(Double currD : ds) {
          System.out.println(currD);
       }
    }

    public static void doit(Integer... is) {
       for(Integer currI : is) {
          System.out.println(currI);
       }
    }

या, आप जेनिक्स का उपयोग कर सकते हैं:

   public static <T> void doit(T... ts) {
      for(T currT : ts) {
         System.out.println(currT);
      }
   }

सूर्य मंचों पर इस बारे में एक चर्चा है।

वहां कोई वास्तविक संकल्प नहीं है, बस इस्तीफा।

वरर्ग (और ऑटो-मुक्केबाजी, जो विशेष रूप से वर्गार्ग के साथ संयोजन में कठोर व्यवहार का कारण बनती है) को जावा के जीवन में बाद में बोल्ट किया गया है, और यह एक ऐसा क्षेत्र है जहां यह दिखाता है। तो यह कंपाइलर की तुलना में, spec में एक और बग है।

कम से कम, यह अच्छा (?) एससीजेपी चाल प्रश्नों के लिए बनाता है।







variadic-functions