.equals()がJavaのクラスにあるのに、なぜ.compareTo()がインターフェイスにあるのですか?


30

クラス内にあるようなメソッド.compareTo()Comparableインターフェイスにある理由を知りたいです。私には、なぜそのようなメソッドがクラスにないのかはarbitrary意的に思えます。.equalsObject.compareTo()Object

を使用する.compareTo()には、目的に応じてComparableインターフェイスを実装し、.compareTo()メソッドを実装します。以下のために.equals()、すべてのクラスから継承するため、この方法は、単に、あなたのクラスのメソッドをオーバーライドしObjectたクラス。

私の質問は、なぜ.compareTo()クラスのようなものではなく、実装するインターフェースのようなメソッドなのObjectですか?同様に、実装されるインターフェースではなく.equals()、クラスのメソッドがなぜObjectですか?



2
これは、Java言語の設計上の選択です(必ずしも正しい選択であったとは限りません)。Haskellなどの他の言語では、値の等価性を得るために等価インターフェース実装する必要があります(実際には、Eqタイプクラスにインスタンスを提供します)。
ムカホ

回答:


58

すべてのオブジェクトを比較できるわけではありませんが、すべてのオブジェクトが等しいかどうかを確認できます。それ以外の場合は、2つのオブジェクトがメモリ内の同じ場所に存在するかどうかを確認できます(参照の等価性)。

compareTo()2つのThreadオブジェクトで何を意味しますか?あるスレッドが別のスレッドよりも「大きい」のはどうですか?2つArrayList<T>のsをどのように比較しますか?

Object契約はに適用されるすべてのJavaクラス。1つのクラスでさえ、それ自身のクラスの他のインスタンスと比較Objectできない場合、インターフェースの一部である必要はありません。

ジョシュアブロッホは、クラスが実装したい理由を説明するときに「自然順序付け」というキーワードを使用しますComparable。上記の例で述べたように、すべてのクラスが自然な順序を持っているわけではないため、すべてのクラスがメソッドを実装しComparableたりObjectcompareToメソッドを持つ必要はありません。

... compareTo方法はで宣言されていませんObject。...文字の点ではObjectequalsメソッドと似ていますが、単純な等価比較に加えて順序比較が可能であり、汎用である点が異なります。実装Comparableすることにより、クラスはそのインスタンスに自然な順序があることを示します。

効果的なJava、第2版:Joshua Bloch。項目12、ページ62。省略記号は、他の章およびコード例への参照を削除します。

あなたは例のため非の順序課したいComparable自然順序付けを持っていないクラスを、あなたは常に供給することができComparator、それは一種の助けにインスタンスを。


3
compareTo with Exception(抽象クラ​​スではないため、aNullPointerException.compareTo(anUnsupportedFlavorException)が...を意味することを実装していたと考えると、さらに楽しいことがありますか?

10
Javaではすべてのオブジェクトの等価性を確認できますが、一般的にはいいえです。等値比較が意味をなさない(参照等でさえない)オブジェクトの例がいくつかあります-シングルトンなど。ValueEqualityやReferenceEqualityのようなインターフェイス(抽象クラ​​ス)があります。それはそれほど悪い考えではないかもしれません
...-qbd

5
「すべてのオブジェクトが等しいかどうかを確認できます。他に何もない場合、2つのオブジェクトがメモリ内の同じ場所に存在するかどうかを確認できます(参照の等価性)。」- ==後者については持っているので、これには中空のリングがあります。冗長なデフォルトを無視すると、すべての型が同値関係をサポートするとは限らないため、すべてのクラスを想定しない有効な理由を見つけることができますequals
ラファエル

3
等式を定義することが賢明ではないタイプの2つの例:ストリーム(例:遅延可能性のある無限リストまたは無限精度数)と関数。前者には、平等を確立するには無限に比較する必要があるという問題があります。2つの関数が等しいかどうかを判断することはできません。これらのタイプの2つのインスタンスが同じメモリ位置に存在するかどうかを尋ねることは、1)あまり有用ではなく、2)クライアントが実装の詳細に敏感なコードを記述できるようにすることです。今日、私はあなたが尋ねるたびに同じ無限リストの新しいインスタンスをあなたに与えるかもしれません、明日私はそれをメモするかもしれません。
ドーバル

6
@Snowmanそれが役に立たないという事実と実装の詳細を公開するという事実は、それを許可しないのに十分な理由です。Java 8のほとんどすべての「値ベースの」クラスには、「使用した場合に何が起こるかについて責任を負いません」という定型文==があります。Integer参照によって2つのsを比較する人は誰でも愚か者であると言うことができますが、比較の開始を許可するのはまだ愚かです。
ドーバル

8

§4.3.2JLS定義しclass、次のようにオブジェクトを:

4.3.2。クラスオブジェクト

このクラスObjectは、他のすべてのクラスのスーパークラス(§8.1.4)です。

すべてのクラスおよび配列タイプObjectは、次のように要約されるclassのメソッドを継承します(§8.4.8):

  • このメソッドcloneは、オブジェクトの複製を作成するために使用されます。

  • このメソッドequalsは、オブジェクト比較の概念を定義します。これは、参照ではなく値の比較に基づいています。

  • このメソッドfinalizeは、オブジェクトが破棄される直前に実行されます(§12.6)。

  • メソッドgetClassは、オブジェクトのクラスを表すClassオブジェクトを返します。

  • Classオブジェクトは、各参照型のために存在します。たとえば、クラスの完全修飾名、そのメンバー、その直接のスーパークラス、および実装するインターフェースを検出するために使用できます。

    のメソッド呼び出し式のタイプgetClassClass<? extends |T|>Tが検索されるクラスまたはインターフェース(§15.12.1)ですgetClass

    宣言されたクラスメソッドsynchronized(§8.4.3.6)は、クラスのClassオブジェクトに関連付けられたモニター上で同期します。

  • このメソッドhashCodeは、等のメソッドとともに、などのハッシュテーブルで非常に便利ですjava.util.Hashmap

  • 方法waitnotifyおよびnotifyAllスレッド(§17.2)を使用して並行プログラミングで使用されています。

  • このメソッドtoStringは、オブジェクトの文字列表現を返します。

だから、それが理由equalsですObjectcompareTo、別のインターフェイスにあります。私は彼らがObject可能な限り最小限に抑えたいと推測します。彼らはおそらくことを考え出し、ほぼすべての Objects必要があるだろうequalsし、hashCodeすべてのオブジェクトがの概念持っている必要があります(実際には平等テストのちょうど形態である)ではなく発注するもので、compareTo使用されています。


理論的にはインターフェースEquitable<T>があるかもしれませんがObject、それを実装すると、すべてのクラスがになりますEquitable<Object>。その時点で、違いはありますか?実際にはそうではなく、複雑さにおいてそうです。
キャプテンマン

1
@CaptainMan .NetにobjectEquals(object)、Javaの場合と同じように持っていIEquatable<T>ますが、インターフェイスもあります。存在する主な理由Tは、Javaでは不可能な値型である場合のボクシングを回避することです。
svick

hashCodeは、ハッシュの衝突があるため、同等性テストの形式ではありません。AとBが等しい場合、それらは同じhashCodeを持っていますが、AとBが同じhashCodeを持っている場合、これはそれらが等しいという意味ではありません!
ジョセフ

実際には、あなたの答えは古いJLS(チタン .cs.berkeley.edu / doc / java- langspec - 1.0.pdf )に切り替えることで大いに役立つでしょう- 直接equals宣言された理由についてのより良い引用がありますObjectThe methods equals and hashCode are declared for the benefit of hashtables such as java.util.Hashtable (§21.7)-Javaデザインとして下位互換性があり、Java 1.0設計の選択が実際に存在する理由equalsです。
vaxquis

私が提案してきた編集はおそらく、「あまりにも抜本的」であることのため拒否されますので、ケースには、あなたの答えにだけはCtrl + C / Ctrlキー+ Vに関連するものをしたいと思います:pastebin.com/8c4EpLRX
vaxquis

2

Snowmanの優れた答えに加えて、それComparableが長い間一般的なインターフェイスであったことを思い出してください。型は実装せず、独自の型であるwhereをcompareTo(object)実装します。これは上に実装することができないため、そこから派生されるクラスを知りません。compareTo(T)Tobjectobject

objectcompareTo(object)メソッドを定義できたかもしれませんが、これにより、スノーマンが指摘したことだけでなく、2 ArrayList<T>sまたは2 Threadsの比較だけでなく、an ArrayList<T>とaの比較も可能になりますThread。それはさらに無意味です。


0

2つのオブジェクト参照があるとします。XはString、コンテンツ「George」を保持するインスタンスを識別します。YはPoint、座標[12,34] を保持するインスタンスを識別します。次の2つの質問を検討してください。

  • XとYは同等のオブジェクトを識別しますか?

  • XはYの前、後、または同等にソートする必要がありますか?

XとYが無関係な型のインスタンスを識別するという事実は、最初の質問を検討するときに問題を引き起こしません。オブジェクトが同等であると定義する共通のベースを共有している場合にのみ、オブジェクトを同等と見なすことができます。以降StringおよびPointそのような塩基(その唯一の共通基本型が非等価なように、すべての異なるオブジェクトに関して)答えが「ノー」単になかったです。

ただし、型が無関係であるという事実は、2番目の質問に関して大きな問題となります。いくつかの種類がそのインスタンス間の順序関係を定義し、いくつかの順序関係でも複数の種類を超える延長することができる[例えばのために、それは可能でしょうBigIntegerし、BigDecimalどちらのタイプのインスタンスが他のインスタンスに対してランク付けできるようになる比較メソッドを定義する]が、一般に、2つの任意のインスタンスを取得し、「XをYの前、後、または同等にソートする」と尋ねて、全体の順序を導出することはできません。オブジェクトが合計ではなく一貫した順序を報告する必要がある場合、「Yに関してXをソートする前、後、同等、またはランク付けしない」と尋ねることができます。1つですが、ほとんどのソートアルゴリズムには完全な順序付けが必要です。したがって、compareTo「非ランク」が有効な戻り値である場合、すべてのオブジェクトがメソッドを実装できたとしても、そのようなメソッドはその存在を正当化するほど有用ではありません。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.