enum.values()-決定論的に返される列挙型の順序


105

列挙型がありSOME_ENUMます:

public enum SOME_ENUM {
  EN_ONE,
  EN_TWO,
  EN_THREE;
}

ウィルSOME_ENUM.values()常にenum宣言の順に列挙型を返しますか EN_ONE, EN_TWO, EN_THREE?それはルールですか、それとも次のJDKリリースで変更されないことが保証されていませんか?


1
私は列挙型を繰り返し処理してリストを作成します。これは、コードの他の場所よりも、この列挙型を繰り返し処理して読み取りました。
Skarab

11
@MitchWheatリストの保持順序に依存するのと同じ理由で、JDKは特定の保証を提供するツールであり、これらの保証に依存することで、より簡潔で優れたコードを作成できます。確かに、「変更されないことが保証されているか」という質問です。答えることは不可能です、あなたは確かにそれに頼ることはできません、何もその保証はありません。
Fletch 2012

回答:


144

Java言語仕様では、次の明示的な言語を使用しています。

この列挙型の定数を含む配列を、宣言された順序で返します[ソース]

そのため、はい、それらは宣言順に返されます。誰かがクラスを変更すると、時間の経過とともに順序が変わる可能性があるので、これを使用する方法には十分注意してください。


1
それ以降のコードバージョンで誰かが途中で値を追加した場合、他の要素の序数値が変更されるため(Enum.ordinal()メソッドを参照)、これにより問題が発生する可能性があります。このため、シリアル化メカニズムとして序数の位置に依存しない(つまり、それをデータベースに格納しない)のが最善です。
マット

1
その仕様のソースへのリンク?
Dan Grahn、2015


16

はい、その順序で返品することが保証されています。

ただしordinal()、たとえば、新しい項目を挿入した後に変更される可能性があるため、これと値に依存することは避けてください。


セージのアドバイスは+1。ordinal()のトピックでは、Effective Javaはenum型にメンバーフィールドを追加することを提案しています。
2010

9

これは、値が宣言された順序によって決定されます。ただし、ユーザー(または他の誰か)が将来、値を並べ替え/挿入/削除しないという保証はありません。したがって、注文に依存するべきではありません。

効果的なJava 2番目。エディションは、アイテム31を密接に関連するトピックに特化しています。序数の代わりにインスタンスフィールドを使用してください

序数から列挙型に関連付けられた値を派生させないでください。代わりにインスタンスフィールドに保存してください。


3
「誰かが将来値を並べ替えないという保証はありません」-しかし、それが私が順序に依存したい理由です:-)!今後アイテムを再注文して、プログラムの動作を変更できるようにしたいと考えています。Blochは序数に依存しないのが正解です。質問者の例に実際にEN_TWOのような列挙型が含まれる場合、彼は序数に依存しているため、これを行うべきではありません。しかし、順序に依存することは完全に問題ありません。実際、順序が保証されているので、順序に特化したフィールドを作成することは冗長なコードを書くことになるため、Effective Javaのような本ではそうしないように指示しています。
Fletch

@フレッチ、申し訳ありませんが、私はあなたを完全にはフォローしていません。私には、これenumは意図されていない何らかの目的で使用しようとしているように聞こえます。
ペーテルTörök

有名な「プラネット」列挙型があるとします。UIで、太陽からの距離順に惑星をリストする必要があります。どうすればこれを達成できますか?enumクラス内で惑星定数を正しい順序で並べ、UIでenumを列挙します。順序は信頼できるので、これは機能します。それは私が話しているようなものです。ある日、地球が火星よりも太陽に近づいた場合、もちろんその瞬間、あなたの暖かい心の最初のことはコードを維持することです!つまり、Planetクラスに移動し、EARTHをMARSの前に移動します。
Fletch 2012

@フレッチ、地球はすでに火星より太陽に近いです;-)しかし、私はあなたが何を意味するかを理解しています。ただし、この場合、惑星の順序は実際には太陽からの平均距離の関数であり、単純な序数ではないため、IMHOは各惑星の個別のフィールドとして保存する必要があります。次に、簡単なコンパレーターを使用して、太陽からの平均距離に基づいて惑星を比較し、このコンパレーターを使用して惑星を並べ替えます。これは私にとってクリーンでフールプルーフなソリューションです。もうすぐ例えば新しい同僚は、惑星がすべきことを決定したとして、ソリューションの休憩のに対し、明らかにアルファベット順;-)に記載されていること
ペーテルTörök

1
ええと、ええとにかくそれはすべて陰謀であり、火星はありません。最初は土星を使用するつもりでしたが、近くにある惑星を思い出せませんでしたが、火星計画は裏目に出たようです:-)。とにかく...この場合、比較子は良いでしょうが、明らかにより多くのコードを必要とするという欠点があります。ソースコードの順序付けに依存している場合は、これをクラスのコメントに文書化することは良いことだと思います。あなたの同僚もそれを読むかもしれません。
Fletch、

7

他の答えは良いですが、これについてコメントしないでください:

「ルールですか、それとも次のJdkリリースで変更されないことが保証されていませんか?」

将来のJDKに保証があるとは思わないので、心配する必要はありません。それらを強制する方法はないでしょう。将来のJDKリードは、そのような保証を放棄することを決定するかもしれません。それはウェストミンスターの議会制度に似ています。「どの議会も将来の議会を拘束することはできません」。

そうは言っても、JDKの歴史は優れた一貫性を示しています。それらは多くの重大な変更を加えないので、現在の指定された(観察されただけでなく)動作が保持されることを確信できます。

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