Javaの列挙型で==
を使用しても大丈夫ですか、それとも.equals()
を使用する必要がありますか?私のテストでは、==
は常に動作しますが、それが保証されているかどうかはわかりません。特に、enumには.clone()
メソッドがないため、.equals()
が==
と異なる値を返す列挙型を取得できるかどうかわかりません。
たとえば、これはOKですか:
public int round(RoundingMode roundingMode) {
if(roundingMode == RoundingMode.HALF_UP) {
//do something
} else if (roundingMode == RoundingMode.HALF_EVEN) {
//do something
}
//etc
}
または、このように書く必要がありますか?
public int round(RoundingMode roundingMode) {
if(roundingMode.equals(RoundingMode.HALF_UP)) {
//do something
} else if (roundingMode.equals(RoundingMode.HALF_EVEN)) {
//do something
}
//etc
}
ちょうど私の2セント:これは、Sunによって公開されたEnum.Javaのコードであり、JDKの一部です。
public abstract class Enum<E extends Enum<E>>
implements Comparable<E>, Serializable {
// [...]
/**
* Returns true if the specified object is equal to this
* enum constant.
*
* @param other the object to be compared for equality with this object.
* @return true if the specified object is equal to this
* enum constant.
*/
public final boolean equals(Object other) {
return this==other;
}
}
はい、==で問題ありません-各値に対してただ1つの参照が保証されます。
ただし、ラウンドメソッドを記述するより良い方法があります。
_public int round(RoundingMode roundingMode) {
switch (roundingMode) {
case HALF_UP:
//do something
break;
case HALF_EVEN:
//do something
break;
// etc
}
}
_
偶数betterの方法は、enum内に機能を配置することです。したがって、単にroundingMode.round(someValue)
を呼び出すことができます。これは、Java列挙型-それらはオブジェクト指向の列挙型であり、「名前付き値」とは異なります)他の場所で見つかりました。
編集:仕様はあまり明確ではありませんが、 セクション8.9 の状態:
列挙型の本体には、列挙定数が含まれる場合があります。列挙定数は、列挙型のインスタンスを定義します。列挙型には、その列挙定数で定義されたもの以外のインスタンスはありません。
はい、enumの各値に対してシングルトンインスタンスを作成した場合と同じです。
public abstract class RoundingMode { public static final RoundingMode HALF_UP = new RoundingMode(); public static final RoundingMode HALF_EVEN = new RoundingMode(); private RoundingMode(){ //プライベートスコープは、このクラス } } 外のサブタイプを防止します
しかしながら、enum
コンストラクトにはさまざまな利点があります。
switch-case
制御構造を使用して定数と比較できます。values
フィールドを使用して照会できます。シリアル化は大きな問題です。列挙型の代わりに上記のコードを使用する場合、同一性の等価性は次のようになります。
RoundingMode original = RoundingMode.HALF_UP; assert(RoundingMode.HALF_UP == original); // pass ByteArrayOutputStream baos = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(baos); oos.writeObject(original); oos.flush(); ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray()); ObjectInputStream ois = new ObjectInputStream(bais); RoundingMode deserialized =(RoundingMode)ois.readObject(); assert(RoundingMode.HALF_UP == deserialized); //失敗します assert(RoundingMode.HALF_EVEN == deserialized); //失敗します
君は できる writeReplace
とreadResolve
を含む手法を使用して、enumなしでこの問題に対処します( http://Java.Sun.com/j2se/1.4.2/docs/apiを参照/Java/io/Serializable.html )...
重要な点は、-Javaは、等しいかどうかをテストするために列挙値のIDを使用できるようになり、推奨される方法です。
== 2つのオブジェクトの参照を比較します。列挙型の場合、インスタンスは1つだけであることが保証されているため、同じ2つの列挙型の場合、==はtrueになります。
参照:
http://www.ajaxonomy.com/2007/Java/making-the-most-of-Java-50-enum-tricks
(Sunのドキュメントには何も見つかりませんでした)
ここにあなたが面白いと思うかもしれないいくつかの邪悪なコードがあります。 :D
public enum YesNo {YES, NO}
public static void main(String... args) throws Exception {
Field field = Unsafe.class.getDeclaredField("theUnsafe");
field.setAccessible(true);
Unsafe unsafe = (Unsafe) field.get(null);
YesNo yesNo = (YesNo) unsafe.allocateInstance(YesNo.class);
Field name = Enum.class.getDeclaredField("name");
name.setAccessible(true);
name.set(yesNo, "YES");
Field ordinal = Enum.class.getDeclaredField("ordinal");
ordinal.setAccessible(true);
ordinal.set(yesNo, 0);
System.out.println("yesNo " + yesNo);
System.out.println("YesNo.YES.name().equals(yesNo.name()) "+YesNo.YES.name().equals(yesNo.name()));
System.out.println("YesNo.YES.ordinal() == yesNo.ordinal() "+(YesNo.YES.ordinal() == yesNo.ordinal()));
System.out.println("YesNo.YES.equals(yesNo) "+YesNo.YES.equals(yesNo));
System.out.println("YesNo.YES == yesNo " + (YesNo.YES == yesNo));
}
列挙型は、多態性コードを詰め込むのに最適な場所です。
enum Rounding {
ROUND_UP {
public int round(double n) { ...; }
},
ROUND_DOWN {
public int round(double n) { ...; }
};
public abstract int round(double n);
}
int foo(Rounding roundMethod) {
return roundMethod.round(someCalculation());
}
int bar() {
return foo(Rounding.ROUND_UP);
}
RMI/IIOPを介してenumを転送する場合、問題があることに注意してください。このスレッドを参照してください:
http://www.velocityreviews.com/forums/t390342-enum-equality.html
==は通常大丈夫で、==と.equals()
の両方に利点があります。個人的には、enum
sを含むオブジェクトを比較するときに、常に.equals()
を使用することを好みます。この議論も参照してください。