Saya sangat akrab dengan C # tetapi mulai bekerja lebih banyak di Jawa. Saya berharap untuk mengetahui bahwa enum di Jawa pada dasarnya setara dengan yang di C # tetapi ternyata ini tidak terjadi. Awalnya saya senang mengetahui bahwa enum Java dapat berisi banyak data yang tampaknya sangat menguntungkan ( http://docs.oracle.com/javase/tutorial/java/javaOO/enum.html ). Namun, sejak itu saya telah menemukan banyak fitur yang hilang yang sepele di C #, seperti kemampuan untuk dengan mudah menetapkan elemen enum nilai tertentu, dan akibatnya kemampuan untuk mengkonversi integer ke enum tanpa usaha yang layak () yaitu Konversi nilai integer ke Java Enum yang cocok ).
Jadi pertanyaan saya adalah ini: apakah ada manfaat untuk Java enum atas kelas dengan sekelompok bidang final statis publik? Atau apakah itu hanya memberikan sintaks yang lebih kompak?
EDIT: Biarkan saya lebih jelas. Apa manfaat Java enums di atas kelas dengan sekelompok bidang final statis publik dari jenis yang sama ? Sebagai contoh, dalam contoh planet di tautan pertama, apa keuntungan enum dibandingkan kelas dengan konstanta publik ini:
public static final Planet MERCURY = new Planet(3.303e+23, 2.4397e6);
public static final Planet VENUS = new Planet(4.869e+24, 6.0518e6);
public static final Planet EARTH = new Planet(5.976e+24, 6.37814e6);
public static final Planet MARS = new Planet(6.421e+23, 3.3972e6);
public static final Planet JUPITER = new Planet(1.9e+27, 7.1492e7);
public static final Planet SATURN = new Planet(5.688e+26, 6.0268e7);
public static final Planet URANUS = new Planet(8.686e+25, 2.5559e7);
public static final Planet NEPTUNE = new Planet(1.024e+26, 2.4746e7);
Sejauh yang saya tahu, jawaban casablanca adalah satu-satunya yang memuaskan ini.
public static final
, yang mungkin diketik nilai dan tidak harusint
s.S
, jadi sekarang kita berbicara tentang kemungkinan meneruskannya ke fungsi, dll. Apakah kita perlu mengetikkan keselamatan? Ya, tidak, tapi kebanyakan orang menganggap tipe c-style "semuanya adalahvoid*
gaya yang bagus" dan itu bisa menghentikan bug (terutama jika melewati lebih dari satu parameter enum / string!). Juga menempatkan konstanta ke dalam namespace mereka sendiri, dll. Bertentangan dengan itu, tidak ada keuntungan nyata untuk hanya memiliki variabel sederhana.int
s, tidak ada jenis keamanan karena seseorang dapat melewati nilai apa pun. Objek yang diketik, di sisi lain, tidak berbeda dengan enum dalam hal keamanan tipe.Jawaban:
Secara teknis orang memang bisa melihat enum sebagai kelas dengan sekelompok konstanta yang diketik, dan inilah sebenarnya bagaimana konstanta enum diimplementasikan secara internal.
enum
Namun menggunakan metode memberi Anda berguna ( Enum javadoc ) yang Anda harus menerapkan sendiri, sepertiEnum.valueOf
.sumber
.values()
untuk mengulangi daftar nilai.switch
pernyataancase
pernyataan tanpa kualifikasi.ordinal().
EnumSet
danEnumMap
kelas.sumber
switch
pernyataan yang merupakan motivasi asli untuk menggunakanEnum
sama sekali.Tidak ada yang menyebutkan kemampuan untuk menggunakannya dalam
switch
pernyataan; Saya akan melemparkan itu juga.Hal ini memungkinkan enum kompleks sewenang-wenang untuk digunakan dengan cara yang bersih tanpa menggunakan
instanceof
,if
urutan yang berpotensi membingungkan , atau nilai switching non-string / int. Contoh kanonik adalah mesin negara.sumber
Keuntungan utama adalah keamanan jenis. Dengan seperangkat konstanta, nilai apa pun dari tipe intrinsik yang sama dapat digunakan, menyebabkan kesalahan. Dengan enum hanya nilai yang berlaku yang dapat digunakan.
Sebagai contoh
vs.
sumber
setSize(null)
dalam contoh kedua Anda, tetapi kemungkinan besar gagal lebih cepat daripada kesalahan contoh pertama.Ada sedikit kebingungan. Ambil
Font
contoh. Ini memiliki konstruktor yang mengambil nama yangFont
Anda inginkan, ukurannya dan gayanya (new Font(String, int, int)
). Sampai hari ini saya tidak ingat apakah gaya atau ukuran lebih dulu. JikaFont
telah menggunakan sebuahenum
untuk semua gaya yang berbeda (PLAIN
,BOLD
,ITALIC
,BOLD_ITALIC
), konstruktor akan terlihat sepertiFont(String, Style, int)
, mencegah kebingungan. Sayangnya,enum
tidak ada ketikaFont
kelas dibuat, dan karena Java harus mempertahankan kompatibilitas terbalik, kita akan selalu terganggu oleh ambiguitas ini.Tentu saja, ini hanya sebuah argumen untuk menggunakan
enum
bukanpublic static final
konstanta. Enum juga sempurna untuk lajang dan menerapkan perilaku default sambil memungkinkan penyesuaian selanjutnya (yaitu pola strategi ). Contoh yang terakhir adalahjava.nio.file
'sOpenOption
danStandardOpenOption
: jika pengembang ingin membuat sendiri non-standar nyaOpenOption
, dia bisa.sumber
enum
tanpa menggunakan varargs atau aSet
untuk mengambil angka acak dari mereka.interface Foo { public void bar(String baz); }
. Seseorang membuat sebuah kelas yang memanggilbar
:someFoo.bar(baz = "hello");
. Saya mengubah tanda tanganFoo::bar
menjadipublic void bar(String foobar)
. Sekarang orang yang dipanggilsomeFoo
harus mengubah kode mereka jika mereka masih ingin berfungsi.Ada banyak jawaban bagus di sini, tetapi tidak ada yang menyebutkan bahwa ada implementasi yang sangat optimal dari kelas API / interface Collection khusus untuk enum :
Kelas khusus enum ini hanya menerima
Enum
instance (EnumMap
satu - satunya yang menerimaEnum
hanya sebagai kunci), dan bila memungkinkan, mereka kembali ke representasi kompak dan manipulasi bit dalam implementasinya.Apa artinya ini?
Jika
Enum
jenis kami tidak memiliki lebih dari 64 elemen (sebagian besarEnum
contoh kehidupan nyata akan memenuhi syarat untuk ini), implementasi menyimpan elemen dalamlong
nilai tunggal , setiapEnum
contoh yang bersangkutan akan dikaitkan dengan sedikit dari panjang 64-bit inilong
. Menambahkan elemen keEnumSet
hanya dengan menetapkan bit yang tepat ke 1, menghapusnya hanya mengatur bit ke 0. Menguji apakah suatu elemen ada di dalamSet
hanya satu uji bitmask! Sekarang kamu harus cintaEnum
untuk ini!sumber
What does this mean?
bagian Anda . Saya tahu ada kesenjangan dalam implementasi pada ukuran 64, tapi saya tidak benar-benar tahu mengapacontoh:
Batasan konstanta java
1) Tidak Ada Jenis Keamanan : Pertama-tama ini bukan tipe-safe; Anda dapat menetapkan nilai int yang valid ke int misalnya 99 meskipun tidak ada koin untuk mewakili nilai itu.
2) Tidak Mencetak Berarti : nilai pencetakan konstanta ini akan mencetak nilai numeriknya alih-alih nama koin yang berarti, misal, ketika Anda mencetak NICKLE, ia akan mencetak "5" alih-alih "NICKLE"
3) Tidak ada namespace : untuk mengakses konstanta currencyDenom kita perlu awalan nama kelas mis. CurrencyDenom.PENNY alih-alih hanya menggunakan PENNY meskipun ini juga dapat dicapai dengan menggunakan impor statis di JDK 1.5
Keuntungan enum
1) Enums di Jawa adalah tipe-safe dan memiliki ruang nama sendiri. Ini berarti enum Anda akan memiliki jenis misalnya "Mata Uang" dalam contoh di bawah ini dan Anda tidak dapat menetapkan nilai apa pun selain yang ditentukan dalam Enum Constants.
Currency coin = Currency.PENNY; coin = 1; //compilation error
2) Enum di Jawa adalah tipe referensi seperti kelas atau antarmuka dan Anda dapat menentukan konstruktor, metode dan variabel di dalam java Enum yang membuatnya lebih kuat daripada Enum dalam C dan C ++ seperti yang ditunjukkan dalam contoh berikutnya dari tipe Java Enum.
3) Anda dapat menentukan nilai konstanta enum pada waktu pembuatan seperti yang ditunjukkan pada contoh di bawah ini: public enum Currency {PENNY (1), NICKLE (5), DIME (10), QUARTER (25)}; Tetapi agar ini berfungsi, Anda perlu mendefinisikan variabel anggota dan konstruktor karena PENNY (1) sebenarnya memanggil konstruktor yang menerima nilai int, lihat contoh di bawah ini.
Referensi: https://javarevisited.blogspot.com/2011/08/enum-in-java-example-tutorial.html
sumber
Manfaat pertama enum, seperti yang telah Anda perhatikan, adalah kesederhanaan sintaksis. Tetapi poin utama enum adalah untuk menyediakan seperangkat konstanta terkenal yang, secara default, membentuk rentang dan membantu untuk melakukan analisis kode yang lebih komprehensif melalui pemeriksaan keamanan tipe & nilai.
Atribut enum tersebut membantu programmer dan kompiler. Misalnya, Anda melihat fungsi yang menerima bilangan bulat. Apa artinya bilangan bulat itu? Nilai seperti apa yang bisa Anda berikan? Anda tidak benar-benar tahu segera. Tetapi jika Anda melihat fungsi yang menerima enum, Anda tahu betul semua kemungkinan nilai yang bisa Anda sampaikan.
Untuk kompiler, enum membantu untuk menentukan rentang nilai dan kecuali Anda menetapkan nilai khusus untuk anggota enum, mereka dengan baik berkisar dari 0 dan lebih tinggi. Ini membantu untuk secara otomatis melacak kesalahan dalam kode melalui pemeriksaan keamanan jenis dan banyak lagi. Sebagai contoh, kompiler dapat memperingatkan Anda bahwa Anda tidak menangani semua nilai enum yang mungkin dalam pernyataan switch Anda (yaitu ketika Anda tidak memilikinya
default
kasing dan hanya menangani satu dari nilai N enum). Ini juga memperingatkan Anda ketika Anda mengkonversi bilangan bulat arbitrer menjadi enum karena rentang nilai enum kurang dari bilangan bulat dan yang pada gilirannya dapat memicu kesalahan dalam fungsi yang tidak benar-benar menerima bilangan bulat. Selain itu, membuat tabel lompat untuk sakelar menjadi lebih mudah ketika nilainya dari 0 ke atas.Ini tidak hanya berlaku untuk Java, tetapi untuk bahasa lain dengan pemeriksaan tipe yang ketat juga. C, C ++, D, C # adalah contoh yang baik.
sumber
Enum adalah implictly akhir, dengan konstruktor pribadi, semua nilai-nilainya adalah dari jenis yang sama atau sub-jenis, Anda dapat memperoleh semua nilai dengan menggunakan
values()
, mendapat nyaname()
atauordinal()
nilai atau Anda dapat melihat sebuah enum dengan nomor atau nama.Anda juga dapat mendefinisikan subclass (meskipun secara final dianggap final, sesuatu yang tidak dapat Anda lakukan dengan cara lain)
sumber
enum Manfaat:
"seperti kemampuan untuk dengan mudah menetapkan elemen enum nilai tertentu"
"dan akibatnya kemampuan untuk mengubah bilangan bulat menjadi enum tanpa usaha yang layak" Tambahkan metode konversi int ke enum yang melakukan itu. Cukup tambahkan HashMap <Integer, EnumX> statis yang berisi pemetaan java enum .
Jika Anda benar-benar ingin mengonversi ord = VAL_200.ordinal () kembali ke val_200 cukup gunakan: EnumX.values () [ord]
sumber
Perbedaan penting lainnya adalah bahwa kompiler java memperlakukan
static final
bidang tipe primitif dan String sebagai literal. Ini berarti konstanta ini menjadi sejajar. Ini mirip denganC/C++
#define
preprocessor. Lihat pertanyaan SO ini . Ini tidak terjadi dengan enum.sumber
Anda mendapatkan waktu kompilasi memeriksa nilai-nilai yang valid ketika Anda menggunakan enum. Lihatlah pertanyaan ini.
sumber
Keuntungan terbesar adalah enum Singletons mudah ditulis dan aman utas:
dan
keduanya serupa dan menangani serialisasi sendiri dengan menerapkan
lebih
sumber
Saya pikir
enum
tidak bisafinal
, karena di bawah kap kompiler menghasilkan subclass untuk setiapenum
entri.Informasi lebih lanjut Dari sumber
sumber
Ada banyak keuntungan enum yang diposting di sini, dan saya membuat enum seperti itu sekarang seperti yang ditanyakan dalam pertanyaan. Tapi saya punya enum dengan 5-6 bidang.
Dalam kasus-kasus seperti ini, ketika Anda memiliki beberapa bidang dalam enum, sangat sulit untuk memahami nilai mana yang dimiliki bidang mana yang Anda perlukan untuk melihat konstruktor dan bola mata.
Kelas dengan
static final
konstanta dan menggunakanBuilder
pola untuk membuat objek seperti itu membuatnya lebih mudah dibaca. Tapi, Anda akan kehilangan semua keuntungan lain menggunakan enum, jika Anda membutuhkannya. Salah satu kelemahan dari kelas tersebut adalah, Anda perlu menambahkanPlanet
objek secara manual kelist/set
dariPlanets.
Aku masih lebih suka enum lebih kelas tersebut, seperti
values()
berguna dan Anda tidak pernah tahu apakah Anda membutuhkan mereka untuk digunakan dalamswitch
atauEnumSet
atauEnumMap
di masa depan :)sumber
Alasan utama: Enums membantu Anda untuk menulis kode yang terstruktur dengan baik di mana makna parameter semantik jelas dan diketik dengan kuat pada waktu kompilasi - untuk semua alasan yang diberikan jawaban lain.
Quid pro quo: di Jawa di luar kotak, susunan anggota Enum adalah final. Itu biasanya baik karena membantu nilai keamanan dan pengujian, tetapi dalam beberapa situasi itu bisa menjadi kelemahan, misalnya jika Anda memperluas kode dasar yang ada mungkin dari perpustakaan. Sebaliknya, jika data yang sama ada di kelas dengan bidang statis, Anda dapat dengan mudah menambahkan instance baru dari kelas tersebut saat runtime (Anda mungkin juga perlu menulis kode untuk menambahkan ini ke Iterable yang Anda miliki untuk kelas itu). Tetapi perilaku Enums ini dapat diubah: menggunakan refleksi Anda dapat menambahkan anggota baru saat runtime atau mengganti anggota yang sudah ada, meskipun ini mungkin hanya boleh dilakukan dalam situasi khusus di mana tidak ada alternatif: yaitu itu adalah solusi hacky dan dapat menghasilkan masalah yang tidak terduga, lihat jawaban saya diDapatkah saya menambah dan menghapus elemen enumerasi saat runtime di Java .
sumber