2008-12-18 103 views
12

爲什麼它(顯然)有所作爲是否我直接傳遞null作爲參數,或者傳遞一個Object,我分配null與null參數的Java方法分派

Object testVal = null; 
test.foo(testVal); // dispatched to foo(Object) 
// test.foo(null); // compilation problem -> "The method foo(String) is ambiguous" 

public void foo(String arg) { // More-specific 
    System.out.println("foo(String)"); 
} 

public void foo(Object arg) { // Generic 
    System.out.println("foo(Object)"); 
} 

換句話說,爲什麼是(註釋掉)以foo(...)秒呼叫沒有分派到foo(Object)

更新:我使用Java 1.6。我可以毫無問題地編譯Hemal的代碼,但是我仍然無法編譯。我看到的唯一差別是Hemal的方法是靜態的,而我的方法不是。但我真的不明白爲什麼這應該有所作爲......?

更新2:已解決。我在我的類中有另一個方法foo(Runnable),所以調度程序不能明確地選擇最具體的方法。 (請參閱我在Hemal的第二個回答中的評論。)感謝大家的幫助。

回答

24

您使用的是哪個版本的Java?在1.6.0_11中,代碼(粘貼在下面)編譯並運行。

我相信它明顯的原因foo(testVal)foo(Object)

foo(null)轉到foo(String)的原因有點複雜。常數null的類型爲nulltype,它是所有類型的子類型。所以,這nulltype延伸String,延伸Object

當您致電foo(null)編譯器查找最具體類型的重載方法。由於String更具體,因此Object即被調用的方法。

如果你有另一個與字符串一樣特定的過載,比如說foo(Integer),那麼你會得到一個模糊的過載錯誤。

class NullType { 

    public static final void main(final String[] args) { 
    foo(); 
    } 

    static void foo() 
    { 
    Object testVal = null; 
    foo(testVal); // dispatched to foo(Object) 
    foo(null); // compilation problem -> "The method foo(String) is ambiguous" 
    } 

    public static void foo(String arg) { // More-specific 
    System.out.println("foo(String)"); 
    } 

    public static void foo(Object arg) { // Generic 
    System.out.println("foo(Object)"); 
    } 

} 
+0

剛剛測試這一點,我目瞪口呆的是,(一)6u11不說這是不明確的,和(b)在空解析字符串不會反對。每天學習新東西 - +1課程。 – 2008-12-18 09:17:32

+1

@Software Monkey:一旦您接受常量null爲null類型,並且null類型爲所有類型的子類型,這是非常明顯的。 Object 2008-12-18 10:16:39

2

因爲第二個註釋爲空的調用對編譯器來說是不明確的。字面null可以是一個字符串或一個對象。而指定的值具有確定的類型。您需要投射null,例如test.foo((String)null)來消除歧義。

1

有沒有人試過這個例子?

隨着1.6.0富(空)被分派到適用的最具體的方法是FOO(字符串)...

如果添加了新的方法說FOO(整數)編譯器不能選擇最具體適用的方法並顯示錯誤。

-Patrick

1

對不起使用一個答案,對於一個評論,但我需要張貼代碼,將不適合評論。

@Yang,我也能夠編譯和運行以下內容。你能發表一個完整的代碼,編譯一行評論,如果我取消註釋該行,它不會編譯?

class NullType { 

    public static final void main(final String[] args) { 
    foo(); 
    new Test().bar(new Test()); 
    } 

    static void foo() 
    { 
    Object testVal = null; 
    foo(testVal); // dispatched to foo(Object) 
    // foo(null); // compilation problem -> "The method foo(String) is ambiguous" 
    } 

    public static void foo(String arg) { // More-specific 
    System.out.println("foo(String)"); 
    } 

    public static void foo(Integer arg) { // More-specific 
    System.out.println("foo(Integer)"); 
    } 

    public static void foo(Object arg) { // Generic 
    System.out.println("foo(Object)"); 
    } 


} 


class Test 
{ 
    void bar(Test test) 
    { 
    Object testVal = null; 
    test.foo(testVal); // dispatched to foo(Object) 
    test.foo(null); // compilation problem -> "The method foo(String) is ambiguous" 
    } 

    public void foo(String arg) { // More-specific 
    System.out.println("foo(String)"); 
    } 

    public void foo(Object arg) { // Generic 
    System.out.println("foo(Object)"); 
    } 
}