enum.values ​​() - adalah urutan deterministik enum yang dikembalikan

105

Saya memiliki enum SOME_ENUM:

public enum SOME_ENUM {
  EN_ONE,
  EN_TWO,
  EN_THREE;
}

Akan SOME_ENUM.values()selalu mengembalikan enum di urutan deklarasi enum: EN_ONE, EN_TWO, EN_THREE? Apakah ini aturan atau tidak ada jaminan tidak akan diubah di rilis JDK berikutnya?

Skarab
sumber
1
Saya mengulangi enum saya untuk mengisi daftar, yang daripada di tempat lain dalam kode saya membaca iterasi atas enum ini.
Skarab
11
@MitchWheat Untuk alasan yang sama bahwa Anda akan bergantung pada urutan pemeliharaan Daftar: karena JDK adalah alat yang memberi Anda jaminan tertentu dan mengandalkan jaminan ini membantu Anda menulis kode yang lebih ringkas dan lebih baik. Harus diakui, pertanyaan "Apakah dijamin tidak akan diubah?" tidak mungkin untuk menjawab, Anda pasti tidak bisa mengandalkan itu, tidak ada yang menjamin itu.
Fletch

Jawaban:

144

Spesifikasi bahasa Java menggunakan bahasa eksplisit ini:

@return sebuah array yang berisi konstanta dari jenis enum ini, dengan urutan dideklarasikan [Sumber]

Jadi, ya, mereka akan dikembalikan dalam urutan deklarasi. Perlu dicatat bahwa urutan dapat berubah seiring waktu jika seseorang mengubah kelas, jadi berhati-hatilah dalam menggunakan ini.

GaryF
sumber
1
Jika seseorang menambahkan nilai di tengah dalam versi kode yang lebih baru, ini bisa membuat Anda tersendat, karena itu akan mengubah nilai ordinal elemen lain (lihat metode Enum.ordinal ()). Sebaiknya jangan mengandalkan posisi ordinal sebagai mekanisme serialisasi (misalnya, jangan menyimpannya di db) karena alasan ini.
Matt
1
Tautkan ke sumber spesifikasi itu?
Dan Grahn
Java 8 doc
Drew Stephens
16

Ya, dijamin akan mengembalikannya dalam urutan itu.

Namun Anda harus menghindari mengandalkan itu, dan pada ordinal()nilainya, karena dapat berubah setelah memasukkan item baru, misalnya.

Bozho
sumber
1 untuk nasihat bijak. Pada topik ordinal (), Java Efektif menyarankan untuk menambahkan bidang anggota ke jenis enum.
ide
9

Ini ditentukan oleh urutan nilai Anda dideklarasikan. Namun, tidak ada jaminan bahwa Anda (atau orang lain) tidak akan menyusun ulang / menyisipkan / menghapus nilai di masa mendatang . Jadi, Anda tidak harus bergantung pada pesanan.

Java Efektif 2nd. Edisi mendedikasikan Item 31 untuk topik terkait erat: Gunakan bidang contoh sebagai ganti ordinal :

Jangan pernah mendapatkan nilai yang terkait dengan enum dari ordinalnya; simpan di kolom instance sebagai gantinya.

Péter Török
sumber
3
"tidak ada jaminan bahwa seseorang tidak akan menyusun ulang nilai di masa mendatang" - tetapi itulah mengapa saya ingin mengandalkan urutan :-)! Saya ingin dapat memesan ulang item di masa mendatang dan dengan demikian mengubah perilaku program saya. Bloch benar tentang tidak mengandalkan ordinal dan jika contoh penanya benar-benar melibatkan enum seperti EN_TWO maka dia mengandalkan ordinal dan tidak boleh melakukan ini. Tetapi mengandalkan pesanan itu baik-baik saja. Faktanya, karena pesanan dijamin, membuat bidang khusus untuk pesanan akan sama dengan menulis kode yang berlebihan, hal yang menurut buku seperti Java Efektif tidak boleh Anda lakukan.
Fletch
@Fletch, maaf, saya kurang mengikuti Anda. Bagi saya ini terdengar seperti Anda mencoba menggunakan enumuntuk beberapa tujuan yang tidak dimaksudkan untuk itu.
Péter Török
katakanlah Anda memiliki enum "Planet" yang terkenal. Di UI Anda, Anda ingin membuat daftar planet dalam urutan jaraknya dari matahari. Bagaimana cara terbaik Anda mencapai ini? Saya akan memesan konstanta planet dalam urutan yang benar di dalam kelas enum dan kemudian hanya menghitung enumerasi di UI. Karena urutannya dapat diandalkan, ini akan berhasil. Itu adalah hal yang saya bicarakan. Jika suatu hari Bumi bergerak lebih dekat ke matahari daripada Mars, tentu di saat seperti itu hal pertama yang ada di pikiran hangat Anda adalah menjaga kode Anda! Jadi Anda pergi ke kelas Planet Anda dan pindah ke BUMI sebelum MARS.
Fletch
@Fletch, Bumi sudah lebih dekat ke Matahari daripada Mars ;-) tapi saya mengerti maksud Anda. Namun, dalam hal ini urutan planet sebenarnya merupakan fungsi jarak rata-rata mereka dari Matahari, yang bukan merupakan ordinal sederhana, oleh karena itu sebaiknya IMHO disimpan sebagai medan tersendiri untuk setiap planet. Kemudian Anda dapat meminta pembanding sepele untuk membandingkan planet berdasarkan jarak rata-rata dari Matahari, dan memesannya menggunakan pembanding ini. Ini IMHO solusi yang bersih dan sangat mudah. Sedangkan solusi Anda rusak segera setelah kolega baru memutuskan bahwa planet jelas harus terdaftar dalam urutan abjad ;-)
Péter Török
1
Hahaha ermm ya yah pokoknya itu semua konspirasi, Mars tidak ada. Awalnya saya akan menggunakan Saturnus tetapi tidak dapat mengingat planet mana yang dekat, tetapi rencana Mars tampaknya menjadi bumerang :-). Bagaimanapun ... dalam hal ini pembanding akan bagus tetapi memiliki sisi negatif dari membutuhkan lebih banyak kode, jelas. Saya pikir jika Anda mengandalkan pengurutan kode sumber, mendokumentasikan ini di komentar kelas akan menjadi hal yang baik. Rekan Anda bahkan mungkin membacanya.
Fletch
7

Jawaban lain bagus, tapi jangan komentari ini:

"Apakah ini aturan atau tidak dijamin tidak akan diubah dalam rilis Jdk berikutnya?"

Saya tidak percaya bahwa ada jaminan pada JDK di masa mendatang, jadi Anda tidak perlu mengkhawatirkannya. Tidak akan ada cara untuk menegakkannya, pemimpin JDK di masa depan mungkin memutuskan untuk mengingkari jaminan tersebut. Ini seperti sistem parlemen Westminster: "Tidak ada Parlemen yang dapat mengikat parlemen masa depan."

Konon, sejarah JDK menunjukkan konsistensi yang sangat baik. Mereka tidak membuat banyak perubahan yang merusak, jadi Anda bisa yakin bahwa perilaku yang ditentukan saat ini (tidak hanya diamati) akan dipertahankan.

Fletch
sumber