19

入力パラメーターが null の場合、compareTo() は NullPointerException をスローする必要があると言われています。ただし、フィールドを String 型と比較する必要があるクラスを実装しています。これらのフィールドは必須ではありません。この場合気になるのは、

1) 入力が null の場合、何を返す必要がありますか? null 以外の文字列は辞書的に null より大きいか小さいか?

2) これが悪い習慣と見なされる場合、それを裏付ける議論はありますか? 代わりに空の文字列を使用するようユーザーに強制する必要がありますか? 空の文字列を使用すると、フィールドが適用されない場合とフィールドが空の場合が混同されませんか? また、例外をスローする必要がある場合は、マニュアルでユーザーに警告する以外に、他に何ができる/すべきでしょうか?

編集:ここでは明確に表現できないかもしれませんが、実装しているプログラムでは、null になる可能性のある文字列はすべてフィールドまたはクラスであり、null であってはなりません。つまり、comparedTo() が使用するオブジェクトを null にすることはできず、プライベート フィールドのみを null にすることができます。したがって、この場合、compareTo() を適切に実装すれば、null フィールドを持つクラスは常に同じと見なされるため、推移的な要件に違反しないと思います。私は正しいですか、それともこれを間違って解釈していますか?

答えてくれてありがとう!

4

6 に答える 6

24

javadocからComparable

nullはどのクラスのインスタンスでもないことに注意してください。また、e.equals(null)がfalseを返したとしても、e.compareTo(null)はNullPointerExceptionをスローする必要があります。

于 2011-06-07T00:02:57.590 に答える
15

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

o.compareTo(null)Comparable.compareTo() の仕様には ( のように動作する- null.compareTo(o)、つまり NullPointerException をスローする)ための制約のみがあり、フィールドの処理方法に関する制約はないことに注意してください(nullフィールドについてはまったく言及されていないため、クラスは反対称性、再帰性、および推移性が保証されている限り、必要なものは何でも返します)。

于 2011-06-07T00:20:54.103 に答える
7

compareToの推移的な反対称の性質に違反するため、例外をスローしないことは悪い習慣です。

Comparable.compareToドキュメントから:

実装者は、すべてのxとyに対してsgn(x.compareTo(y))== -sgn(y.compareTo(x))を確認する必要があります。(これは、y.compareTo(x)が例外をスローする場合、x.compareTo(y)が例外をスローする必要があることを意味します。)

実装者は、関係が推移的であることも確認する必要があります。(x.compareTo(y)> 0 && y.compareTo(z)> 0)は、x.compareTo(z)>0を意味します。

最後に、実装者は、すべてのzについて、x.compareTo(y)== 0がsgn(x.compareTo(z))== sgn(y.compareTo(z))を意味することを確認する必要があります。

さらに重要なことに、同じ理由で、オブジェクトでcompareToを使用して、オブジェクトを文字列と比較することはお勧めできませんsign(obj.compareTo(str)) != -sign(str.compareTo(obj))。カスタムコンパレータを実装し、必要な処理を実行します。

于 2011-06-07T00:03:23.977 に答える
3

のドキュメントにcompareToは、をスローする必要があると記載されNullPointerExceptionているため、実装がインターフェイスのドキュメントと一致するように、これらのガイドラインに従う必要があります。これは、null以外の文字列が辞書式に小さいか大きいかという質問も処理しますnull

これを処理する方法については、いくつかのオプションがあります。空と該当しないものが異なる場合は、おそらく文字列フィールドを独自のフィールドクラスでラップする必要があります。たとえばisApplicable、フィールドがこのケース(または同様のもの)に適用可能かどうかを示すメソッドを持つ可能性のあるタイプのMyFieldを作成できるとします。または、デザインを再考して、空の文字列とN/Aが実際には2つの異なるものであることを確認することもできます。もしそうなら、あなたは2つを区別する方法が必要です。

于 2011-06-07T00:05:13.503 に答える
3

null が null 以外の値よりも大きいか小さいかを判断する必要があります。クラスの自然な順序付けのニーズを満たすように設計できるcompareToため、悪い習慣ではありません。

于 2011-06-07T00:08:44.383 に答える