2010-10-26 9 views
77

यदि मेरे पास एक vararg जावा विधि foo(Object ...arg) है और मैं foo(null, null) पर कॉल करता हूं, तो मेरे पास arg[0] और arg[1]null एस दोनों हैं। लेकिन अगर मैं foo(null) पर कॉल करता हूं, arg स्वयं शून्य है। ये क्यों हो रहा है?एकल नल तर्क के साथ जावा varargs विधि कॉलिंग?

मुझे foo पर कॉल करना चाहिए जैसे कि foo.length == 1 && foo[0] == nulltrue है?

उत्तर

82

मुद्दा यह है कि जब आप शाब्दिक शून्य का उपयोग करते हैं, जावा नहीं जानता कि यह किस प्रकार का होना चाहिए। यह एक शून्य वस्तु हो सकता है, या यह एक शून्य ऑब्जेक्ट सरणी हो सकता है। एक तर्क के लिए यह बाद वाले को मानता है।

आपके पास दो विकल्प हैं। ऑब्जेक्ट को स्पष्ट रूप से नल कास्ट करें या दृढ़ता से टाइप किए गए चर का उपयोग करके विधि को कॉल करें।

public class Temp{ 
    public static void main(String[] args){ 
     foo("a", "b", "c"); 
     foo(null, null); 
     foo((Object)null); 
     Object bar = null; 
     foo(bar); 
    } 

    private static void foo(Object...args) { 
     System.out.println("foo called, args: " + asList(args)); 
    } 
} 

आउटपुट::

foo called, args: [a, b, c] 
foo called, args: [null, null] 
foo called, args: [null] 
foo called, args: [null] 
+0

दूसरों के लिए सहायक होगा यदि आपने नमूना में 'asList' विधि सूचीबद्ध की थी, और इसका उद्देश्य। –

+4

@ अरुणकुमार 'asList() '' java.util.Arrays' वर्ग से एक स्थिर आयात है। मैंने अभी माना कि यह स्पष्ट था। यद्यपि अब मैं इसके बारे में सोच रहा हूं, शायद मुझे केवल 'Arrays.toString()' का उपयोग करना चाहिए था क्योंकि एक सूची में इसे परिवर्तित करने का एकमात्र कारण यह है कि यह सुंदर प्रिंट करेगा। –

18

आप Object का सुस्पष्ट कलाकारों की जरूरत है:

foo((Object) null); 

अन्यथा तर्क पूरी सरणी कि varargs का प्रतिनिधित्व करता है माना जाता है।

+0

वास्तव में, मेरी पोस्ट देखें। –

+11

अच्छी तरह से, मुझे लगता है कि आप गलत हैं :) – Bozho

+0

ओह, वही यहाँ ... क्षमा करें, आधी रात का तेल। –

3

ऐसा इसलिए है क्योंकि एक varargs विधि को सरणी तत्वों की एक श्रृंखला के बजाय वास्तविक सरणी के साथ बुलाया जा सकता है। जब आप इसे अस्पष्ट null के साथ स्वयं प्रदान करते हैं, तो यह मानता है कि nullObject[] है। null को Object पर कास्ट करने से यह ठीक हो जाएगा।

5

एक टेस्ट केस इस वर्णन करने के लिए: नीचे दिए गए उदाहरण देखें

एक vararg लेने विधि घोषणा (जो स्थिर होता है) के साथ जावा कोड:

public class JavaReceiver { 
    public static String receive(String... x) { 
     String res = ((x == null) ? "null" : ("an array of size " + x.length)); 
     return "received 'x' is " + res; 
    } 
} 

यह जावा कोड (एक जुनीट 4 टेस्ट केस) उपर्युक्त कॉल करता है (हम किसी भी परीक्षण का परीक्षण नहीं कर रहे परीक्षण मामले का उपयोग कर रहे हैं बात है, बस कुछ उत्पादन उत्पन्न करने के लिए):

import org.junit.Test; 

public class JavaSender { 

    @Test 
    public void sendNothing() { 
     System.out.println("sendNothing(): " + JavaReceiver.receive()); 
    } 

    @Test 
    public void sendNullWithNoCast() { 
     System.out.println("sendNullWithNoCast(): " + JavaReceiver.receive(null)); 
    } 

    @Test 
    public void sendNullWithCastToString() { 
     System.out.println("sendNullWithCastToString(): " + JavaReceiver.receive((String)null)); 
    } 

    @Test 
    public void sendNullWithCastToArray() { 
     System.out.println("sendNullWithCastToArray(): " + JavaReceiver.receive((String[])null)); 
    } 

    @Test 
    public void sendOneValue() { 
     System.out.println("sendOneValue(): " + JavaReceiver.receive("a")); 
    } 

    @Test 
    public void sendThreeValues() { 
     System.out.println("sendThreeValues(): " + JavaReceiver.receive("a", "b", "c")); 
    } 

    @Test 
    public void sendArray() { 
     System.out.println("sendArray(): " + JavaReceiver.receive(new String[]{"a", "b", "c"})); 
    } 
} 

एक JUnit परीक्षण पैदावार के रूप में इस चल रहा है:

 
sendNothing(): received 'x' is an array of size 0 
sendNullWithNoCast(): received 'x' is null 
sendNullWithCastToString(): received 'x' is an array of size 1 
sendNullWithCastToArray(): received 'x' is null 
sendOneValue(): received 'x' is an array of size 1 
sendThreeValues(): received 'x' is an array of size 3 
sendArray(): received 'x' is an array of size 3 

इस और अधिक दिलचस्प बनाने के लिए, के ग्रूवी 2.1.2 से फ़ंक्शन को कॉल करें और देखते हैं क्या हो जाता। यह पता चला है कि परिणाम एक जैसे नहीं हैं! हालांकि यह एक बग हो सकता है।

import org.junit.Test 

class GroovySender { 

    @Test 
    void sendNothing() { 
     System.out << "sendNothing(): " << JavaReceiver.receive() << "\n" 
    } 

    @Test 
    void sendNullWithNoCast() { 
     System.out << "sendNullWithNoCast(): " << JavaReceiver.receive(null) << "\n" 
    } 

    @Test 
    void sendNullWithCastToString() { 
     System.out << "sendNullWithCastToString(): " << JavaReceiver.receive((String)null) << "\n" 
    } 

    @Test 
    void sendNullWithCastToArray() { 
     System.out << "sendNullWithCastToArray(): " << JavaReceiver.receive((String[])null) << "\n" 
    } 

    @Test 
    void sendOneValue() { 
     System.out << "sendOneValue(): " + JavaReceiver.receive("a") << "\n" 
    } 

    @Test 
    void sendThreeValues() { 
     System.out << "sendThreeValues(): " + JavaReceiver.receive("a", "b", "c") << "\n" 
    } 

    @Test 
    void sendArray() { 
     System.out << "sendArray(): " + JavaReceiver.receive(["a", "b", "c"] as String[]) << "\n" 
    } 

} 

इसे जुनीट टेस्ट के रूप में चलाने से निम्नलिखित में उत्पन्न होता है, जावा में बोल्ड में हाइलाइट किए गए अंतर के साथ।

 
sendNothing(): received 'x' is an array of size 0 
sendNullWithNoCast(): received 'x' is null 
sendNullWithCastToString(): received 'x' is null 
sendNullWithCastToArray(): received 'x' is null 
sendOneValue(): received 'x' is an array of size 1 
sendThreeValues(): received 'x' is an array of size 3 
sendArray(): received 'x' is an array of size 3 
1

मैं

foo(new Object[0]); 

पसंद करते हैं अशक्त सूचक अपवाद से बचने के लिए।

उम्मीद है कि यह मदद करता है।

+8

ठीक है, अगर यह एक vararg विधि है, तो क्यों न केवल इसे 'foo() 'कहते हैं? –

+0

@ BrainStorm.exe आपका उत्तर उत्तर के रूप में चिह्नित किया जाना चाहिए। धन्यवाद। –

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