2010-10-26 155 views
77

如果我有一個可變參數Java方法foo(Object ...arg),我呼叫foo(null, null),我同時使用arg[0]arg[1]作爲null s。但如果我撥打foo(null)arg本身爲空。這是爲什麼發生?用單個null參數調用Java可變參數方法?

如何撥打foo使foo.length == 1 && foo[0] == nulltrue

回答

82

問題是,當您使用字面null時,Java不知道它應該是什麼類型。它可能是一個空對象,或者它可能是一個空對象數組。對於單個論點,它假定後者。

你有兩種選擇。將null顯式轉換爲Object或使用強類型變量調用該方法。請參見下面的示例:

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'方法及其目的,對他人有幫助。 – 2014-06-19 05:34:20

+4

@ArunKumar'asList()'是從'java.util.Arrays'類的靜態導入。我只是假設它很明顯。雖然現在我正在考慮這個問題,但是我應該剛剛使用'Arrays.toString()',因爲它被轉換爲List的唯一原因是它會很好地打印出來。 – 2014-06-20 06:17:58

18

你需要一個顯式的Object

foo((Object) null); 

否則該參數,則是整個陣列的可變參數代表。

+0

不是真的,請看我的帖子。 – 2010-10-26 21:27:58

+11

好吧,我想你錯了:) – Bozho 2010-10-26 21:30:43

+0

哎呀,這裏也一樣...對不起,午夜油。 – 2010-10-26 21:34:30

3

這是因爲varargs方法可以用實際數組而不是一系列數組元素來調用。當你自己提供模糊的null時,它假定nullObject[]。將null投射到Object將解決此問題。

5

測試用例來說明這一點:

的Java代碼與可變參數回吐方法聲明(這恰好是靜態的):

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; 
    } 
} 

這個Java代碼(一個JUnit4測試用例)調用上述(我們使用的測試用例不是測試任何的事情,只是產生一些輸出):

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 

爲了使這更有趣,讓我們調用功能在Groovy 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" 
    } 

} 

將此作爲JUnit測試運行會產生以下結果,其中Java以粗體突出顯示。

 
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

那麼,如果它是可變參數方法,爲什麼不把它叫做'foo()'呢? – 2014-03-11 00:05:22

+0

@ BrainStorm.exe你的答案應該被標記爲答案。謝謝。 – 2016-09-28 08:28:14

相關問題