2011-03-02 45 views
21

每種方法都接受一組參數值。我們是否應始終驗證輸入參數的非空值,還是允許代碼通過經典RunTimeException失敗?我們是否應該總是在第一行中檢查java中的方法的每個參數爲null?

我見過很多代碼,人們並沒有真正檢查輸入參數的無效性,只是使用參數編寫業務邏輯。什麼是最好的方法?

void public(String a, Integer b, Object c) 
{ 
    if(a == null || b == null || c == null) 
    { 
    throw new RunTimeException("Message..."); 
    } 
    .....business logic..... 
} 
+0

的[?在哪裏檢查對象爲空或不是]可能重複(http://stackoverflow.com/questions/706263/where-to-check-if -an-object-is-null-or-not) – NPE 2011-03-02 20:23:04

+0

另一個問題是關於'.net',但實質上是完全相同的。 – NPE 2011-03-02 20:24:04

+0

目前的答案都沒有提到使用註釋和靜態分析,例如FindBugs @NonNull,@CheckForNull等。另外,雖然這不是上面提到的.Net問題的重複,但它可能至少在stackoverflow中覆蓋過一次。 – 2011-03-02 20:48:39

回答

22

最好的辦法是只在必要時檢查。例如,如果你的方法是private,所以你知道沒有其他人使用它,並且你知道你沒有傳入任何空值,那麼沒有必要再檢查一次。

如果你的方法是public雖然,誰知道你的API的用戶將嘗試做什麼,所以更好地檢查。

如果有疑問,請檢查

但是,如果你能做的最好的是拋出NullPointerException,那麼可能不想檢查。例如:

int getStringLength(String str) { 
    return str.length(); 
} 

即使你檢查null,合理的選擇是拋出一個NullPointerException,這str.length()會爲你閒着。

+28

我不會建議依靠自動NullPointerException來取代顯式參數驗證。原因有二:(a)驗證應該儘可能早地發生(想法在遇到NPE之前改變某些狀態)和(b)代碼可支持性。類X中的NPE將首先轉到類X的所有者,因爲它看起來像是實現中的錯誤。但是,如果你顯式檢查args爲null,並且拋出IllegalArgumentException異常(也是類似NPE的RuntimeException),那麼顯然問題在於類X的調用者。 – 2011-03-02 21:00:07

1

我沒有看到這麼做的很多觀點。您只是簡單地複製您在第一次嘗試在abc上運行時免費獲得的行爲。

0

這取決於你的代碼試圖做什麼以及你想拋出一個Exception的情況。有時你會希望你的方法總是拋出一個異常,如果你的方法將無法正確使用空值。如果你的方法可以解決空值,那麼可能不需要拋出異常。

添加太多檢查異常可能會導致非常複雜和複雜的代碼。這是他們沒有被包含在C#中的原因。

1

不可以。假定參數不爲空並且否則將拋出NullPointerException的標準。如果你的方法允許一個參數爲null,你應該在你的api中聲明。

1

這取決於您是否期望您的任何參數是null - 更確切地說,如果您的方法仍然可以做出正確的決定,如果某些參數是null

如果不是,它是很好的做法,以檢查null並拋出一個異常,否則你會得到一個NullPointerException,你應該永遠也追不上,因爲它的出現總是表示您忘了檢查你的變量在你的代碼。 (如果你抓住它,你可能會錯過其他被拋出的事件,並且你可能會引入錯誤)。另一方面,如果拋出RunTimeException或其他一些自定義異常,則可以在上游的某個位置處理它,以便更好地控制所發生的事情。

0

不,你不應該這樣做普遍。

我的喜好,按順序將是:

  1. 理智做事與空。明智的做法完全取決於情況,但拋出自定義異常不應該是您的首選。
  2. 使用一個斷言來檢查null並徹底測試,消除了由於--a.k.a錯誤而產生空輸入的任何情況。
  3. 對於公共API,不允許使用null的文檔,並讓它在NPE中失敗。
+0

@downvoter沒有解釋?只是不喜歡我的臂架的切割? – 2011-03-03 00:29:19

1

你不應該拋出一個運行時異常,除非它是一個真正的系統的操作,如丟失了關鍵的運行參數,一個致命的條件,但即使如此,這是有問題的系統應該只是無法啓動。

業務規則是什麼?該字段允許爲空嗎?不是嗎?

在任何情況下,在嘗試操作它們之前檢查傳入的任何參數的空值總是一個好習慣,所以當有人向您傳遞錯誤數據時,您不會得到NullPointerExceptions

-5

如果你不知道你是否應該這樣做,那麼很可能你不需要這樣做。

JDK源,和Joshua Bloch的書,是可怕學習的榜樣,因爲他們的目標是非常不同的受衆。我們有多少人正在爲數百萬程序員編寫公共API?

2

這是Java的一個不幸的方面是引用可null並沒有辦法,因爲它們不是語言來指定。

所以一般情況是這樣,不要對null做出解釋,也不要陷入以後可能會拋出NPE的情況。

JSR305(現已失效)允許您註釋參數聲明,他們不應該給予null秒。

void fn(@Nonnull String a, @Nonnull Integer b, @Nonnull Object c) { 

冗長,但是這是Java的爲您服務。還有其他的註釋庫和檢查器的功能差不多,但都不是標準的。

(備註大寫:當窗體「非物」的駱駝外殼也就是說,standard不是大寫航線字,除非它是一個類的名稱,以便nonthingnonnull

除了運行檢查程序之外,註釋也不會實際執行規則。您可以靜態地包括一種方法做檢查:

public static <T> T nonnull(T value) { 
    if (value == null) { 
     throwNPE(); 
    } 
    return value; 
} 
private static void throwNPE() { 
    throw new NullPointerException(); 
} 

返回的值是很方便的在構造函數:

import static pkg.Check.nonnull; 

class MyClass { 
    @Nonnull private final String thing; 
    public MyClass(@Nonnull String thing) { 
     this.thing = nonnull(thing); 
    } 
    ... 
+0

謝謝湯姆。我認爲註釋很棒。而且這個實現看起來更乾淨。 – 2011-03-13 18:54:11

1

是的,公共的方法應該擦洗輸入,特別是如果錯誤的輸入可能導致內部問題你的方法的代碼。快速失敗是個好主意;也就是說,儘快檢查。 Java 7中添加了一個新Objects類,可以很容易地檢查null參數,包括自定義消息:

public final void doSomething(String s) 
{ 
    Objects.requireNonNull(s, "The input String cannot be null"); 
    // rest of your code goes here... 
} 

這將引發NullPointerException

Javadoc文檔Objects類:http://docs.oracle.com/javase/7/docs/api/java/util/Objects.html

相關問題