エラー - java enum 比較 大小




Javaのenumメンバーの比較:==またはequals()? (10)

tl; dr

もう一つのオプションは、 Objects.equalsユーティリティメソッドです。

Objects.equals( thisEnum , thatEnum )

Objects.equals

.equals()の代わりに演算子==と等しい

どのオペレータが私が使用すべきですか?

3番目のオプションは、 Java 7以降に追加されたObjectsユーティリティー・クラスにあるstatic Objects.equalsメソッドです。

Month列挙型を使用した例を次に示します。

boolean areEqual = Objects.equals( Month.FEBRUARY , Month.JUNE ) ;  // Returns `false`.

利点

私はこの方法にいくつかの利点を見つける:

  • 無安全
    • どちらもnull➙true
    • ヌル➙falseのいずれか
    • NullPointerExceptionをスローする危険性なし
  • コンパクトで読みやすい

使い方

Objects.equals使用するロジックは何ですか?

OpenJDK Java 10ソースコードから自分自身を参照してください。

return (a == b) || (a != null && a.equals(b));

Javaのenumは、privateコンストラクタとパブリック静的メンバーのクラスにコンパイルされています。 与えられたenumの2つのメンバーを比較すると、私は常に.equals()使用しています。

public useEnums(SomeEnum a)
{
    if(a.equals(SomeEnum.SOME_ENUM_VALUE))
    {
        ...
    }
    ...
}

しかし、私はちょうどequals()の代わりにequals演算子==を使用するいくつかのコードに出くわしました:

public useEnums2(SomeEnum a)
{
    if(a == SomeEnum.SOME_ENUM_VALUE)
    {
        ...
    }
    ...
}

どのオペレータが私が使用すべきですか?


Can not == enumで使用できますか?

Yes:enumsには、 ==を使用してインスタンスを比較できる厳密なインスタンスコントロールがあります。 以下は、言語仕様(私の強調)によって保証されています:

JLS 8.9列挙型

列挙型には、その列挙定数で定義されたもの以外のインスタンスはありません。

列挙型を明示的にインスタンス化しようとすると、コンパイル時にエラーが発生します。 Enumfinal cloneメソッドは、 enum定数を決してクローン化できないことを保証し、直列化メカニズムによる特別な処理により、デシリアライズの結果として複製インスタンスが決して生成されないようにします。 列挙型の反映的なインスタンス化は禁止されています。 一緒に、これらの4つのものは、 enum型のインスタンスがenum定数で定義されたものを超えて存在しないことを保証します。

enum定数のインスタンスは1つだけであるため、少なくとも1つがenum定数を参照することがわかっている場合は、2つのオブジェクト参照を比較するときにequalsメソッドの代わりに==演算子を使用できますEnumequalsメソッドは、引数にsuper.equalsを呼び出して結果を返し、アイデンティティ比較を実行するfinalメソッドです。

この保証は、シングルトンパターンの使用を主張する場合、単一要素のenum型を使用することが最善の方法であることをJosh Bloch氏が十分に強く示しています( 効果的なJava第2版、項目3:プライベートコンストラクタまたは列挙型 ; シングルトンのスレッドセーフティ

==equals違いは何ですか?

思い出させるには、一般的に、 ==equals実行可能な代替手段ではないと言われなければならない。 しかし、それがenumようなものである場合、考慮すべき2つの重要な違いがあります。

== NullPointerExceptionスローしない

enum Color { BLACK, WHITE };

Color nothing = null;
if (nothing == Color.BLACK);      // runs fine
if (nothing.equals(Color.BLACK)); // throws NullPointerException

==コンパイル時に型の互換性チェックが行われる

enum Color { BLACK, WHITE };
enum Chiral { LEFT, RIGHT };

if (Color.BLACK.equals(Chiral.LEFT)); // compiles fine
if (Color.BLACK == Chiral.LEFT);      // DOESN'T COMPILE!!! Incompatible types!

該当する場合==を使用する必要がありますか?

Blochは具体的には、インスタンスを適切に制御できる不変クラスがクライアントに==使用可能であることを保証できることを述べています。 例示のためにenumを具体的に挙げています。

項目1:コンストラクタではなく静的なファクトリメソッドを検討する

[...]は、不変クラスが2つの等しいインスタンスが存在しないことを保証することを可能にします: a.equals(b) a==b場合にのみa.equals(b) クラスがこの保証を行う場合、クライアントはequals(Object)メソッドの代わりに==演算子を使用することができ、パフォーマンスが向上する可能性があります。 列挙型はこの保証を提供します。

要約すると、 enum ==を使用する引数は次のとおりです。

  • できます。
  • それはより速いです。
  • 実行時にはより安全です。
  • コンパイル時にはより安全です。

==を使用して2つの列挙型の値を比較すると、各列挙型の定数に1つのオブジェクトしかないために機能します。

==equals()ように記述するequals() 、実際には==を使用してnullセーフコードを書く必要はありません。

public useEnums(SomeEnum a)
{
    if(SomeEnum.SOME_ENUM_VALUE.equals(a))
    {
        ...
    }
    ...
}

これは、あなたが必ず従わなければならない左から定数比較するというベストプラクティスです。


==以外のものを使ってenum定数を比較するのはナンセンスです。 それはclassオブジェクトをequalsと比較するのとequals - しないでください!

しかし、Sun JDK 6u10以前のバグ(BugId 6277781 )は歴史的な理由から興味深いかもしれません。 このバグは、デシリアライズされた列挙型で==を適切に使用することを妨げましたが、これは間違いなく多少のコーナーケースです。


どちらも技術的に正しいです。 .equals()ソースコードを見ると、単純に==ます。

私は==を使用していますが、それはnull安全です。


なぜなら、それぞれの定義されたインスタンスもシングルトンであるからです。 したがって、==を使用したアイデンティティ比較は常に機能します。

しかし、==を使うとenumsと動作するので、あなたのコードはすべてそのenumの使用法と密接に結びついています。

たとえば、列挙型はインターフェイスを実装できます。 現在Interface1を実装しているenumを使用しているとします。 後で、誰かがそれを変更したり、同じインタフェースの実装として新しいクラスImpl1を導入したりします。 Impl1のインスタンスを使用すると、以前の==の使用のために、変更してテストするコードがたくさんあります。

したがって、正当な利益が得られない限り、良い方法とみなされるものに従うことが最善です。


列挙型の場合は、両方が正しいと正しいです!


真ん中の列挙型は、定数の集合です。 "=="は2つの整数を比較したのと同じように有効で適切です。


私はpolygenelubricants答えを補完したい:

私は個人的にはequals()を好む。 しかし、それは型互換性チェックを湖にします。 私はこれが重要な限界だと思います。

コンパイル時にタイプの互換性チェックを行うには、enumでカスタム関数を宣言して使用します。

public boolean isEquals(enumVariable) // compare constant from left
public static boolean areEqual(enumVariable, enumVariable2) // compare two variable

これにより、両方のソリューションの利点がすべて得られます.NPE保護、コンパイル時にコードを読みやすく、タイプの互換性チェックが可能です。

また、enumにUNDEFINEDの値を追加することをお勧めします。


私は、この特定の違いを明示的に強調したいと思います==演算子とequals()メソッド:

equals()メソッドは、関連する参照変数が参照するオブジェクトの内容equals()かどうかをチェックするためのものです。

==演算子は、関与する参照変数が同じオブジェクトを参照しているかどうかをチェックします

アプリケーションによって必要に応じてこの差別化を提供するのは実装クラスによって異なります。

それ以外の場合、デフォルトの動作はObjectクラス(Javaの場合)によって提供され、 http://docs.oracle.com/javase/1.5.0/docs/api/java/lang/Object.html#equals(java.lang.Object)

Objectクラスのequalsメソッドは、 Object上で最も識別可能な等価関係を実装します。 つまり、null以外の参照値xy場合、このメソッドはxyが同じオブジェクトを参照する場合にのみtrue返します( x == yの値がtrue )。





enums