2015-08-18 44 views
0

如果你有兩個重載的方法,像這樣:我怎樣才能讓一個方法取空值?

public void methodName(File file){} 
public void methodName(String string){} 

如果你試圖調用methodNamenull你會得到一個錯誤,指出它的曖昧這是可以理解的,因爲它不知道該怎麼辦哪一種方法。

我知道你可以只投出null:methodName((String) null)但是我怎樣才能創建一個特別的方法來處理你撥打methodName(null)的情況?

事情是這樣的:

public void methodName(null null){} 

我怎樣才能讓這必須採取一個空的方法?

回答

0

如你所見,編譯器無法解析兩種方法,當你通過null是採取不同類型的對象。

解決這個問題的唯一辦法是要麼類型轉換,就像你做了,或有這需要一個通用的Object類型和嘗試垂頭喪氣的方法:

public void methodName(Object object) { 
    if (object == null) { 
     // do something with null 
    } else if (object instanceof File) { 
     // do something with ((File)object) 
    } else { 
     // do something else 
    } 
} 

編寫代碼,看起來像這樣往往是被視爲臭,並有充分的理由。它得到迅速複雜,難以維護,等等。最好的辦法是強制轉換或改變你的方法簽名,讓你(和編譯器)始終知道哪些功能應該被調用來處理特定的null對象。

+0

帶有參數類型的重載方法確保(和文檔)只給出有效的類型。 – Andreas

+0

爲什麼downvote?這是功能正確的代碼,它實際上回答了被問到的問題。我*直接指出,作爲一種編程練習,它被忽視並給出了原因。 – par

+0

@Andreas,問題是關於如何編寫一個可以使用'null'並解決編譯器歧義的函數,它不是*關於類型化參數優點的問題。 – par

4

只是做一個方法不帶任何參數。

public void methodName(){} 

要求的方法,其must take a null相同要求總是需要5的方法或始終以「foo」的方法。如果傳遞的參數應該總是包含相同的值,則完全不需要該參數。

如果你被要求將被選擇時所傳遞的參數爲空,而不管其類型的方法(即兩個方法調用下面需要調用相同的重載方法),

File f = null; 
String s = null; 
methodName (f); 
methodName (s); 

這不是因爲必須在編譯時使用參數的編譯時類型來選擇要使用的重載方法。在編譯時,編譯器無法知道在執行該方法時傳遞的變量包含null。

+1

方法名的'實現(文件)'和'methodName(String)'當然可以做一個空的檢查,如果該參數爲空,則調用'methodName()',確保你的兩個例子以你定義的無參數重載結束。 – Andreas

+0

@Andreas如果所有這些方法都不是「最終」的,那麼記錄內部呼叫就很重要。 –

+0

沒有真正回答OP的問題。他希望有一個通用的'null'處理程序,並且唯一實現這個功能的方法是使用'Object'並測試'null'或downcasts的函數。它*可以*用Java完成。 – par

0

參數通過可以總是總是爲空如果它是Object。當你嘗試在空引用上運行一個方法時,你會得到一個空指針異常。

所以,public void methodName(File file){}可以被稱爲methodName(null)沒有例外。

然而,

public void methodName(File file) { 
    file.delete(); 
} 

將導致空指針異常,如果傳遞null。

0

你不能寫一個特別需要null的方法。你不得不做這樣的事情:

methodName(File file) { 
    if(file == null) { 
     someOtherMethod(); 
    } 
    else { 
     // other stuff 
    } 
} 

但是這將是更常見的只是methodName(File)手柄null,並記錄它與null一樣。如果你有它調用另一種方法和methodName(File)someOtherMethod()都不是最終的,你應該記錄內部電話。

0

你不能這樣做。請記住,您可能有隱含的null。例如:

File file = null; 
methodName(file); 

然而,Java編譯器必須在呼叫鏈接到特定的方法簽名,所以應該在null是否經過編譯的時候知道。

另一方面爲什麼堅持null?沒有什麼可以阻止你定義的特殊類型:

enum Null { NULL } 
public void methodName(File file){} 
public void methodName(String string){} 
public void methodName(Null n) {} 

methodName(Null.NULL); // or methodName(NULL); with import static 
2

存在被經常用來表示一個null一個類型,這是Void,其中唯一的有效值爲null

你可以寫

void methodName(Void v); 

凡通常用於對通用返回類型等。

Future<Void> future = executorService.submit(new Callable<Void>() { 
    public Void call() throws IOException { 
     try(FileInputStream fis = new FileInputStream(filename)) { 
      doSomething(fis); 
     } 
     return null; 
    } 
}); 

// later 
future.get(); 

你可能會問,爲什麼不使用Runnable,我們就不需要return null;,但是Runnable不能拋出checked異常,所以如果我們希望捕捉IOException異常在future對象,我們多用可贖回。

在Java 8中,您可以使用lambda表達式,但編譯器將仍然期望,如果你拋出checked異常返回null作爲它的作品了,你必須使用可贖回

Future<Void> future = executorService.submit(() -> { 
     try(FileInputStream fis = new FileInputStream(filename)) { 
      doSomething(fis); 
     } 
     return null; 
    }); 
+0

對不起,我不是很理解,我不能'methodName(void null)'?這似乎是完美 – Aequitas

+0

@Aequitas你可以做'methodName((Void)null);'因爲你仍然需要爲重載方法強制轉換。 –