2011-06-06 71 views
15

據說當輸入參數爲空時,compareTo()應該拋出一個NullPointerException異常。但是,我正在實現一個需要將字段與String類型進行比較的類。這些字段不一定是強制性的。我想知道在這種情況下,當參數字符串爲空時,int compareTo()會返回什麼?

1)當輸入爲空時應該返回什麼?任何非空字符串是否按字典順序大於或小於空?

2)如果這被認爲是不好的做法,有沒有什麼論據?我應該強制用戶使用空字符串嗎?如果使用空字符串,這不會混淆字段不適用的情況和字段爲空的情況嗎?如果必須拋出異常,那麼除了在手冊中警告用戶之外,還能做什麼?

編輯:我可能不會在這裏明確表達自己,但在我正在實施的程序中,可能爲空的字符串是所有字段或類,它們不應該爲空。換句話說,compareTo()使用的對象不能爲空,只能是它們的私有字段。所以在這種情況下,我相信如果我正確實現了compareTo(),它不會違反傳遞要求,因爲具有空字段的類將始終被視爲相同。我是對的還是我解釋這個錯誤?

謝謝大家的答案!

+0

如何最好地實現它:http://stackoverflow.com/questions/481813/how-to-simplify-a-null-safe-compareto-implementation – 2015-06-02 12:33:27

回答

12

是的,允許null作爲實例字段沒有問題 - 只要確保它的排序順序已定義。最自然的就是把它放在所有真正的琴絃之前或之後,但你可以在這裏做任何事情,只要一直做。 (例如,你可以進行排序null"null"

這裏是一個成員的範例:

class Example implements Comparable<Example> { 

    @Nullable 
    private String member; 

    // TODO: getter, setter, constructor, ... 

    public int compareTo(Example that) { 
     if(this.member == null) 
     if(that.member == null) 
      return 0; //equal 
     else 
      return -1; // null is before other strings 
     else // this.member != null 
     if(that.member == null) 
      return 1; // all other strings are after null 
     else 
      return this.member.compareTo(that.member); 
    } 
} 

請注意,Comparable.compareTo()的規範只對o.compareTo(null)約束(它應該像- null.compareTo(o)一樣),但不是關於如何處理字段(它根本沒有提到字段,所以只要反對稱性,反射性和傳遞性得到保證,類就可以返回任何想要的東西)。

+0

呃,存在的問題是它不同意規範;-) – EJP 2011-06-07 01:48:49

+2

@EJP:'compareTo'的規範沒有說明如何(甚至是否)比較對象的實例字段。 – 2011-06-07 10:48:50

+0

compareTo()的規範說'e.compareTo(null)應該拋出一個NullPointerException'。 – EJP 2011-06-09 10:47:05

23

從Javadoc文檔Comparable

注意,空不是 實例的任何類,並e.compareTo(空) 應該拋出一個NullPointerException 即使e.equals(空)返回 假。

7

這將是一個不好的做法,因爲它違反的compareTo的 傳遞 反對稱自然不會拋出異常。

Comparable.compareTo文檔:

實現程序必須確保 SGN(則x.compareTo(Y))== -sgn(y.compareTo(X))對於所有的x和y。 (這意味着則x.compareTo(Y)必須 拋出一個異常,如果y.compareTo(X) 拋出異常。)

實現類還必須確保 的關係是傳遞的: (則x.compareTo( y)> 0 & & y.compareTo(z)> 0) 意味着x.compareTo(z)> 0。

最後,實現程序必須確保 則x.compareTo(Y)== 0意味着 SGN(則x.compareTo(Z))== SGN(y.compareTo(Z)),對所有的Z。

更重要的是,在您的對象上使用compareTo來比較它們與字符串是一個壞主意,出於同樣的原因:sign(obj.compareTo(str)) != -sign(str.compareTo(obj))。實施自定義Comparator並做任何你想要的。

+0

謝謝!但是,在我正在執行的程序中,可能爲空的字符串都是零件或類,它們不應爲空。所以在這種情況下,我相信如果我正確實現了compareTo(),它不會違反傳遞要求,因爲具有空字段的類將始終被視爲相同。我是對的還是我解釋這個錯誤? – 2011-06-07 00:08:50

+0

比較兩個實例可能或可能沒有設置實例字段是完全正確的。只要確保你實現了傳遞。 I.E. c1.compareTo(c2)== -c2.compareTo(c1) – ykaganovich 2011-06-07 00:13:36

+1

僅用於術語:條件'c1.compareTo(c2)== -c2.compareTo(c1)'被稱爲反對稱,而不是傳遞性。傳遞性主要是您的報價中的第二個條件(也可能是第三個條件)。 – 2011-06-07 00:18:05

3

由於compareTo文檔指出它應該拋出一個NullPointerException,你應該遵循這些準則所以您的實現與接口文檔保持一致。這也處理了非空字符串是否按字典順序小於或大於null的問題。

關於如何處理此問題,您有幾個選項。如果空和不適用是不同的,那麼你應該把字符串字段包裝在你自己的字段類中。例如,假設您可以創建一種可能有isApplicable方法的MyField類型,該方法指示該字段是否適用於此案例(或類似情況)。或者你可以重新考慮你的設計,並確保一個空字符串和N/A真的是兩個不同的東西。如果是這樣,你需要一種方法來區分兩者。

3

您需要確定null是否大於或小於非空值。您可以設計compareTo以滿足您班級自然排序的需要,因此這不是一種壞習慣。

相關問題