Apa itu enum dan mengapa itu berguna?

488

Hari ini saya sedang menelusuri beberapa pertanyaan di situs ini dan saya menemukan sebuah penyebutan enum yang digunakan dalam pola tunggal tentang manfaat keamanan utas yang diakui untuk solusi tersebut.

Saya tidak pernah menggunakan enumdan saya telah memprogram di Jawa selama lebih dari beberapa tahun sekarang. Dan ternyata mereka banyak berubah. Sekarang mereka bahkan melakukan dukungan penuh OOP dalam diri mereka sendiri.

Sekarang mengapa dan untuk apa saya harus menggunakan enum dalam pemrograman sehari-hari?

Mat B.
sumber
6
Dalam bukunya , Java Efektif, Edisi Kedua , Joshua Bloch menguraikan pendekatan ini dalam Item 3: Menegakkan Properti Singleton dengan Konstruktor Pribadi atau Tipe Enum , dicetak ulang di Dr. Dobb's .
trashgod
kemungkinan duplikat Enum di Jawa. Keuntungan?
finnw
Anda tidak dapat instantiate enum karena memiliki konstruktor pribadi, mereka instantiated pada jvm startup, jadi singleton-nya, Enums tidak aman untuk thread.
Arnav Joshi

Jawaban:

633

Anda harus selalu menggunakan enum ketika suatu variabel (terutama parameter metode) hanya dapat mengambil satu dari sekumpulan nilai yang mungkin. Contohnya adalah hal-hal seperti konstanta tipe (status kontrak: "permanen", "temp", "magang"), atau bendera ("jalankan sekarang", "penundaan eksekusi").

Jika Anda menggunakan enum alih-alih bilangan bulat (atau kode String), Anda meningkatkan pemeriksaan waktu kompilasi dan menghindari kesalahan dari memasukkan konstanta yang tidak valid, dan Anda mendokumentasikan nilai mana yang legal untuk digunakan.

BTW, terlalu sering menggunakan enum dapat berarti bahwa metode Anda melakukan terlalu banyak (seringkali lebih baik untuk memiliki beberapa metode terpisah, daripada satu metode yang menggunakan beberapa flag yang memodifikasi apa yang dilakukannya), tetapi jika Anda harus menggunakan flag atau kode jenis, enum adalah cara untuk pergi.

Sebagai contoh, mana yang lebih baik?

/** Counts number of foobangs.
 * @param type Type of foobangs to count. Can be 1=green foobangs,
 * 2=wrinkled foobangs, 3=sweet foobangs, 0=all types.
 * @return number of foobangs of type
 */
public int countFoobangs(int type)

melawan

/** Types of foobangs. */
public enum FB_TYPE {
 GREEN, WRINKLED, SWEET, 
 /** special type for all types combined */
 ALL;
}

/** Counts number of foobangs.
 * @param type Type of foobangs to count
 * @return number of foobangs of type
 */
public int countFoobangs(FB_TYPE type)

Panggilan metode seperti:

int sweetFoobangCount = countFoobangs(3);

kemudian menjadi:

int sweetFoobangCount = countFoobangs(FB_TYPE.SWEET);

Dalam contoh kedua, segera jelas jenis mana yang diizinkan, dokumen dan implementasi tidak dapat disinkronkan, dan kompiler dapat menegakkan ini. Juga, panggilan yang tidak valid seperti

int sweetFoobangCount = countFoobangs(99);

tidak mungkin lagi.

sleske
sumber
41
Jika Anda menggunakan enum dan ingin mengizinkan kombinasi nilai, gunakan EnumSet. Ini hadir dengan semua jenis pembantu yang rapi, seperti EnumSet final public static <FB_TYPE> ALL = EnumSet.allOf (FB_TYPE.class);
RobAu
20
Jawaban-jawaban ini adalah yang saya benar-benar suka lihat di SO karena seseorang telah melakukan upaya nyata di dalamnya, pekerjaan yang baik saya mengerti enum sekarang!
Dediqated
1
Saya pikir itu tidak benar you should *always* use enums when a variable can only take one out of a small set of possible values. Menggunakan nilai-nilai konstan sebagai 'bendera biner' (dengan logika or) dapat berguna untuk aplikasi waktu nyata di mana Anda kekurangan memori.
Elist
@Daftar menggunakan enum meningkatkan keterbacaan kode Anda, Jika Anda menggunakan konstanta pada suatu waktu Anda atau penerus Anda tidak tahu mengapa itu digunakan ...
:)
136

Mengapa menggunakan fitur bahasa pemrograman? Alasan kami memiliki bahasa sama sekali adalah untuk

  1. Pemrogram untuk mengekspresikan algoritma secara efisien dan benar dalam bentuk komputer dapat digunakan.
  2. Pemelihara untuk memahami algoritma yang telah ditulis orang lain dan membuat perubahan dengan benar .

Enum meningkatkan kemungkinan kebenaran dan keterbacaan tanpa menulis banyak boilerplate. Jika Anda ingin menulis boilerplate, maka Anda dapat "mensimulasikan" enum:

public class Color {
    private Color() {} // Prevent others from making colors.
    public static final Color RED = new Color();
    public static final Color AMBER = new Color();
    public static final Color GREEN = new Color();
}

Sekarang Anda dapat menulis:

Color trafficLightColor = Color.RED;

Pelat di atas memiliki efek yang sama dengan

public enum Color { RED, AMBER, GREEN };

Keduanya memberikan tingkat bantuan pemeriksaan yang sama dari kompiler. Boilerplate lebih banyak mengetik. Tetapi menghemat banyak mengetik membuat programmer lebih efisien (lihat 1), jadi ini adalah fitur yang bermanfaat.

Ini bermanfaat untuk setidaknya satu alasan lagi, juga:

Ganti pernyataan

Satu hal yang tidak diberikan static finalsimulasi enum di atas adalah case yang bagus . Untuk tipe enum, Java switch menggunakan tipe variabelnya untuk menyimpulkan lingkup kasus enum, jadi untuk hal di atas Anda hanya perlu mengatakan:switchenum Color

Color color = ... ;
switch (color) {
    case RED:
        ...
        break;
}

Perhatikan itu tidak ada Color.REDdalam kasing. Jika Anda tidak menggunakan enum, satu-satunya cara untuk menggunakan jumlah bernama dengan switchsesuatu seperti:

public Class Color {
    public static final int RED = 0;
    public static final int AMBER = 1;
    public static final int GREEN = 2;
}

Tapi sekarang variabel untuk menahan warna harus memiliki tipe int. Kompiler memeriksa enum danstatic final simulasi hilang. Tidak senang.

Kompromi adalah menggunakan anggota bernilai skalar dalam simulasi:

public class Color {
    public static final int RED_TAG = 1;
    public static final int AMBER_TAG = 2;
    public static final int GREEN_TAG = 3;

    public final int tag;

    private Color(int tag) { this.tag = tag; } 
    public static final Color RED = new Color(RED_TAG);
    public static final Color AMBER = new Color(AMBER_TAG);
    public static final Color GREEN = new Color(GREEN_TAG);
}

Sekarang:

Color color = ... ;
switch (color.tag) {
    case Color.RED_TAG:
        ...
        break;
}

Tetapi perhatikan, bahkan lebih banyak lagi boilerplate!

Menggunakan enum sebagai singleton

Dari pelat ketel di atas, Anda dapat melihat mengapa enum menyediakan cara untuk mengimplementasikan singleton. Alih-alih menulis:

public class SingletonClass {
    public static final void INSTANCE = new SingletonClass();
    private SingletonClass() {}

    // all the methods and instance data for the class here
}

dan kemudian mengaksesnya dengan

SingletonClass.INSTANCE

kita bisa katakan saja

public enum SingletonClass {
    INSTANCE;

    // all the methods and instance data for the class here
}

yang memberi kita hal yang sama. Kami bisa lolos dengan ini karena enum Java yang diimplementasikan sebagai kelas penuh dengan hanya sintaksis gula sedikit ditaburi di atas. Lagi-lagi ini kurang matang, tetapi tidak jelas kecuali jika idiomnya sudah Anda kenal. Saya juga tidak suka fakta bahwa Anda mendapatkan berbagai fungsi enum meskipun mereka tidak masuk akal untuk singleton: orddan values, dll. (Sebenarnya ada simulasi yang lebih rumit di mana Color extends Integeritu akan bekerja dengan switch, tapi itu sangat rumit sehingga bahkan lebih rumit jelas menunjukkan mengapa enumitu ide yang lebih baik.)

Keamanan benang

Keamanan utas merupakan masalah potensial hanya saat singleton dibuat malas tanpa penguncian.

public class SingletonClass {
    private static SingletonClass INSTANCE;
    private SingletonClass() {}
    public SingletonClass getInstance() {
        if (INSTANCE == null) INSTANCE = new SingletonClass();
        return INSTANCE;
    }

    // all the methods and instance data for the class here
}

Jika banyak utas memanggil getInstancesecara bersamaan saat INSTANCEmasih nol, sejumlah instance dapat dibuat. Ini buruk. Satu-satunya solusi adalah menambahkan synchronizedakses untuk melindungi variabel INSTANCE.

Namun, static finalkode di atas tidak memiliki masalah ini. Ini menciptakan instance dengan penuh semangat pada waktu pemuatan kelas. Pemuatan kelas disinkronkan.

The enumtunggal secara efektif malas karena tidak diinisialisasi sampai digunakan pertama. Inisialisasi Java juga disinkronkan, jadi beberapa utas tidak dapat menginisialisasi lebih dari satu instance INSTANCE. Anda mendapatkan singleton diinisialisasi malas dengan kode yang sangat sedikit. Satu-satunya negatif adalah sintaks yang agak kabur. Anda perlu mengetahui idiom atau memahami sepenuhnya bagaimana pemuatan kelas dan inisialisasi bekerja untuk mengetahui apa yang terjadi.

Gene
sumber
15
Paragraf terakhir itu benar-benar menjelaskan situasi tunggal bagi saya. Terima kasih! Setiap pembaca yang membaca sepintas harus membaca kembali itu.
Basil Bourque
Saya membaca ini, stackoverflow.com/questions/16771373/… . Sekarang saya bingung dengan para terakhir Anda. Bagaimana enum tidak menyediakan fitur inisialisasi awam?
Deepankar Singh
static finalbidang diinisialisasi pada waktu inisialisasi kelas , bukan waktu memuat. Persis sama dengan enuminisialisasi konstan (pada kenyataannya, mereka identik di bawah tenda). Itu sebabnya mencoba menerapkan kode inisialisasi malas "pintar" untuk lajang selalu sia-sia, bahkan dalam versi Java pertama.
Holger
42

Selain kasus penggunaan yang telah disebutkan, saya sering menemukan enum berguna untuk menerapkan pola strategi, mengikuti beberapa pedoman OOP dasar:

  1. Memiliki kode di mana data berada (yaitu, di dalam enum itu sendiri - atau sering dalam konstanta enum, yang dapat menggantikan metode).
  2. Menerapkan antarmuka (atau lebih) agar tidak mengikat kode klien ke enum (yang seharusnya hanya menyediakan satu set implementasi standar).

Contoh paling sederhana adalah seperangkat Comparatorimplementasi:

enum StringComparator implements Comparator<String> {
    NATURAL {
        @Override
        public int compare(String s1, String s2) {
            return s1.compareTo(s2);
        }
    },
    REVERSE {
        @Override
        public int compare(String s1, String s2) {
            return NATURAL.compare(s2, s1);
        }
    },
    LENGTH {
        @Override
        public int compare(String s1, String s2) {
            return new Integer(s1.length()).compareTo(s2.length());
        }
    };
}

"Pola" ini dapat digunakan dalam skenario yang jauh lebih kompleks, memanfaatkan secara luas semua barang yang datang dengan enum: iterasi pada instance, mengandalkan urutan implisit mereka, mengambil sebuah instance dengan namanya, metode statis menyediakan instance yang tepat untuk konteks tertentu dll. Dan Anda masih memiliki semua ini tersembunyi di balik antarmuka sehingga kode Anda akan bekerja dengan implementasi kustom tanpa modifikasi jika Anda menginginkan sesuatu yang tidak tersedia di antara "opsi default".

Saya telah melihat ini berhasil diterapkan untuk memodelkan konsep waktu granularity (harian, mingguan, dll) di mana semua logika dirangkum dalam enum (memilih granularity yang tepat untuk rentang waktu tertentu, perilaku spesifik terikat ke setiap granularity sebagai konstan metode dll.). Dan masih, Granularityseperti yang terlihat oleh lapisan layanan hanyalah sebuah antarmuka.

Costi Ciudatu
sumber
2
Anda juga bisa menambahkan CASE_INSENSITIVE { @Override public int compare(String s1, String s2) { return s1.compareToIgnoreCase(s2); }. Satu keuntungan yang belum disebutkan adalah bahwa Anda mendapatkan dukungan Serialisasi yang kuat; formulir persisten hanya berisi nama kelas dan nama konstan, tidak tergantung pada detail implementasi komparator Anda.
Holger
32

Sesuatu yang tidak ada dari jawaban lain yang dibahas yang membuat enum sangat kuat adalah kemampuan untuk memiliki metode templat . Metode dapat menjadi bagian dari base enum dan diganti oleh masing-masing jenis. Dan, dengan perilaku yang melekat pada enum, sering menghilangkan kebutuhan untuk jika-membangun atau beralih pernyataan seperti yang ditunjukkan posting blog ini - di mana enum.method()apa yang awalnya akan dieksekusi di dalam kondisi. Contoh yang sama juga menunjukkan penggunaan impor statis dengan enum serta menghasilkan kode seperti DSL yang jauh lebih bersih.

Beberapa kualitas menarik lainnya termasuk fakta bahwa enum menyediakan implementasi untuk equals(), toString()dan hashCode()dan mengimplementasikan Serializabledan Comparable.

Untuk rundown lengkap dari semua yang ditawarkan enum, saya sangat merekomendasikan Bruce Eckel's Thinking in Java edisi ke 4 yang mencurahkan seluruh bab untuk topik ini. Terutama menerangi adalah contoh-contoh yang melibatkan permainan Rock, Paper, Scissors (yaitu RoShamBo) sebagai enum.

jeruk nipis
sumber
23

Dari dokumen Java -

Anda harus menggunakan tipe enum kapan saja Anda perlu merepresentasikan konstanta yang tetap. Itu termasuk tipe enum alami seperti planet di tata surya kita dan set data di mana Anda mengetahui semua nilai yang mungkin pada waktu kompilasi — misalnya, pilihan pada menu, bendera baris perintah, dan sebagainya.

Contoh umum adalah mengganti kelas dengan seperangkat konstanta int akhir statis privat (dalam jumlah konstanta yang wajar) dengan tipe enum. Pada dasarnya jika Anda pikir Anda tahu semua nilai yang mungkin dari "sesuatu" pada waktu kompilasi Anda dapat menyatakan bahwa sebagai tipe enum. Enum memberikan keterbacaan dan fleksibilitas atas kelas dengan konstanta.

Beberapa keunggulan lain yang bisa saya pikirkan tentang jenis enum. Mereka selalu merupakan salah satu contoh dari kelas enum tertentu (maka konsep menggunakan enum sebagai singleton tiba). Keuntungan lain adalah Anda dapat menggunakan enums sebagai jenis dalam pernyataan switch-case. Anda juga dapat menggunakan toString () pada enum untuk mencetaknya sebagai string yang dapat dibaca.

CoolBeans
sumber
8
Apakah Anda menggunakan enum untuk semua 366 hari dalam setahun? Ini adalah konstanta tetap (366) (hari tidak berubah). Jadi ini menyarankan Anda harus. : - / Saya akan membatasi ukuran set tetap.
moinudin
2
@marcog Dengan sedikit pemikiran cerdas mungkin untuk meringkas hari dalam seminggu dan hari dalam setiap bulan dalam enum ringkas.
James P.
1
Berbicara tentang hari dalam seminggu ... DayOfWeekenum sekarang telah ditentukan sebelumnya, dibangun ke dalam Java 8 dan kemudian sebagai bagian dari kerangka kerja java.time (dan kembali-porting ke Java 6 & 7 dan ke Android ).
Basil Bourque
19

Sekarang mengapa dan untuk apa saya harus menggunakan enum dalam pemrograman sehari-hari?

Anda dapat menggunakan Enum untuk mewakili konstanta tetap yang bertubuh kecil atau mode kelas internal sambil meningkatkan keterbacaan. Juga, Enums dapat menegakkan kekakuan tertentu ketika digunakan dalam parameter metode. Mereka menawarkan kemungkinan menarik untuk menyampaikan informasi ke konstruktor seperti pada contoh Planet di situs Oracle dan, seperti yang Anda temukan, juga memungkinkan cara sederhana untuk membuat pola tunggal.

mis: Locale.setDefault(Locale.US)membaca lebih baik daripada Locale.setDefault(1)dan menegakkan penggunaan set nilai tetap yang ditunjukkan dalam IDE ketika Anda menambahkan .pemisah dan bukan semua bilangan bulat.

James P.
sumber
@arnt Saya sudah memperbaiki tata bahasa di pertanyaan juga. Terima kasih.
James P.
13

Enums sebutkan seperangkat nilai tetap, dengan cara mendokumentasikan diri.
Mereka membuat kode Anda lebih eksplisit, dan juga lebih sedikit rawan kesalahan.

Mengapa tidak menggunakan String, atau int, alih-alih Enum, untuk konstanta?

  1. Kompiler tidak akan mengizinkan kesalahan ketik , tidak ada nilai yang keluar dari set tetap, karena enum adalah tipe sendiri. Konsekuensi:
    • Anda tidak perlu menulis pra-kondisi (atau manual if) untuk memastikan argumen Anda dalam kisaran yang valid.
    • The jenis invarian datang secara gratis.
  2. Enum dapat memiliki perilaku, sama seperti kelas lainnya.
  3. Anda mungkin membutuhkan jumlah memori yang sama untuk menggunakan Strings, bagaimanapun (ini tergantung pada kompleksitasnya Enum).

Selain itu, masing-masing Enuminstance adalah kelas, di mana Anda dapat mendefinisikan perilaku individualnya.

Plus, mereka menjamin keamanan thread saat membuat instance (ketika enum dimuat), yang telah melihat aplikasi hebat dalam menyederhanakan Pola Singleton .

Blog ini menggambarkan beberapa aplikasi, seperti Mesin Negara untuk parser.

afsantos
sumber
13

Sangat berguna untuk mengetahui bahwa enumssama seperti kelas lain dengan Constantbidang dan a private constructor.

Sebagai contoh,

public enum Weekday
{
  MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY
} 

Kompiler mengkompilasinya sebagai berikut;

class Weekday extends Enum
{
  public static final Weekday MONDAY  = new Weekday( "MONDAY",   0 );
  public static final Weekday TUESDAY = new Weekday( "TUESDAY ", 1 );
  public static final Weekday WEDNESDAY= new Weekday( "WEDNESDAY", 2 );
  public static final Weekday THURSDAY= new Weekday( "THURSDAY", 3 );
  public static final Weekday FRIDAY= new Weekday( "FRIDAY", 4 );
  public static final Weekday SATURDAY= new Weekday( "SATURDAY", 5 );
  public static final Weekday SUNDAY= new Weekday( "SUNDAY", 6 );

  private Weekday( String s, int i )
  {
    super( s, i );
  }

  // other methods...
}
Ad Infinitum
sumber
12

enumberarti enum eration yaitu menyebutkan (sejumlah hal) satu per satu.

Sebuah enum adalah tipe data yang berisi fixed mengatur konstanta.

ATAU

Sebuah enumadalah seperti class, dengan satu set tetap contoh diketahui pada waktu kompilasi.

Sebagai contoh:

public class EnumExample {
    interface SeasonInt {
        String seasonDuration();
    }

    private enum Season implements SeasonInt {
        // except the enum constants remaining code looks same as class
        // enum constants are implicitly public static final we have used all caps to specify them like Constants in Java
        WINTER(88, "DEC - FEB"), SPRING(92, "MAR - JUN"), SUMMER(91, "JUN - AUG"), FALL(90, "SEP - NOV");

        private int days;
        private String months;

        Season(int days, String months) { // note: constructor is by default private 
            this.days = days;
            this.months = months;
        }

        @Override
        public String seasonDuration() {
            return this+" -> "+this.days + "days,   " + this.months+" months";
        }

    }
    public static void main(String[] args) {
        System.out.println(Season.SPRING.seasonDuration());
        for (Season season : Season.values()){
            System.out.println(season.seasonDuration());
        }

    }
}

Keuntungan enum:

  • enum meningkatkan keamanan tipe pada pemeriksaan waktu kompilasi untuk menghindari kesalahan pada saat run-time.
  • enum dapat dengan mudah digunakan secara bergantian
  • enum dapat dilalui
  • enum dapat memiliki bidang, konstruktor dan metode
  • enum dapat mengimplementasikan banyak antarmuka tetapi tidak dapat memperluas kelas apa pun karena secara internal memperluas kelas Enum

untuk lebih

Premraj
sumber
9

Apa itu enum

  • enum adalah kata kunci yang ditentukan untuk Enumerasi tipe data baru. Enumerasi typesafe harus digunakan secara bebas. Secara khusus, mereka adalah alternatif yang kuat untuk String sederhana atau konstanta int yang digunakan dalam API yang jauh lebih tua untuk mewakili set item terkait.

Mengapa menggunakan enum

  • enum adalah subclass final implisit dari java.lang.Enum
  • jika enum adalah anggota kelas, itu secara implisit statis
  • baru tidak pernah bisa digunakan dengan enum, bahkan di dalam tipe enum itu sendiri
  • nama dan nilai. Jika cukup gunakan teks konstanta enum, sedangkan toString dapat diganti untuk memberikan konten apa pun, jika diinginkan
  • untuk konstanta enum, sama dengan dan = = jumlah untuk hal yang sama, dan dapat digunakan secara bergantian
  • konstanta enum adalah final statis publik

Catatan

  • enum tidak dapat memperpanjang kelas apa pun.
  • Enum tidak bisa menjadi superclass.
  • urutan penampilan konstanta enum disebut "tatanan alami" mereka, dan menentukan urutan yang digunakan oleh item lain juga: compareTo, urutan iterasi nilai, EnumSet, EnumSet.range.
  • Pencacahan dapat memiliki konstruktor, blok statis dan contoh, variabel, dan metode tetapi tidak dapat memiliki metode abstrak.
tinker_fairy
sumber
4
Anda tidak menjelaskan mengapa menggunakan enum. Anda cukup mendaftar beberapa properti enum di bawah tajuk yang tidak terkait.
Duncan Jones
@DuncanJones tidak syarat akhir, statis memberikan tujuan menggunakan enum?
tinker_fairy
8

Terlepas dari semua yang dikatakan oleh orang lain .. Dalam proyek yang lebih tua yang saya gunakan untuk bekerja, banyak komunikasi antara entitas (aplikasi independen) menggunakan bilangan bulat yang mewakili satu set kecil. Itu berguna untuk mendeklarasikan set enumdengan metode statis untuk mendapatkan enumobjek dari valuedan sebaliknya. Kode tampak lebih bersih, beralih kegunaan huruf besar dan menulis lebih mudah ke log.

enum ProtocolType {
    TCP_IP (1, "Transmission Control Protocol"), 
    IP (2, "Internet Protocol"), 
    UDP (3, "User Datagram Protocol");

    public int code;
    public String name;

    private ProtocolType(int code, String name) {
        this.code = code;
        this.name = name;
    }

    public static ProtocolType fromInt(int code) {
    switch(code) {
    case 1:
        return TCP_IP;
    case 2:
        return IP;
    case 3:
        return UDP;
    }

    // we had some exception handling for this
    // as the contract for these was between 2 independent applications
    // liable to change between versions (mostly adding new stuff)
    // but keeping it simple here.
    return null;
    }
}

Buat enumobjek dari nilai yang diterima (misalnya 1,2) menggunakan ProtocolType.fromInt(2) Tulis ke log menggunakanmyEnumObj.name

Semoga ini membantu.

sErVerdevIL
sumber
6

Enum mewarisi semua metode Objectkelas dan kelas abstrak Enum. Jadi Anda dapat menggunakan metode itu untuk refleksi, multithreading, serilisasi, sebanding, dll. Jika Anda hanya mendeklarasikan konstanta statis bukan Enum, Anda tidak bisa. Selain itu, nilai Enum dapat dikirimkan ke lapisan DAO juga.

Berikut ini contoh program untuk diperagakan.

public enum State {

    Start("1"),
    Wait("1"),
    Notify("2"),
    NotifyAll("3"),
    Run("4"),
    SystemInatilize("5"),
    VendorInatilize("6"),
    test,
    FrameworkInatilize("7");

    public static State getState(String value) {
        return State.Wait;
    }

    private String value;
    State test;

    private State(String value) {
        this.value = value;
    }

    private State() {
    }

    public String getValue() {
        return value;
    }

    public void setCurrentState(State currentState) {
        test = currentState;
    }

    public boolean isNotify() {
        return this.equals(Notify);
    }
}

public class EnumTest {

    State test;

    public void setCurrentState(State currentState) {
        test = currentState;
    }

    public State getCurrentState() {
        return test;
    }

    public static void main(String[] args) {
        System.out.println(State.test);
        System.out.println(State.FrameworkInatilize);
        EnumTest test=new EnumTest();
        test.setCurrentState(State.Notify);
        test. stateSwitch();
    }

    public void stateSwitch() {
        switch (getCurrentState()) {
        case Notify:
            System.out.println("Notify");
            System.out.println(test.isNotify());
            break;
        default:
            break;
        }
    }
}
abishkar bhattarai
sumber
4

ENum adalah singkatan dari "Enumerated Type". Ini adalah tipe data yang memiliki konstanta yang Anda tentukan sendiri.

Steve
sumber
Anda belum menjelaskan mengapa menggunakan enum.
Duncan Jones
4
Ya saya lakukan. Anda menggunakannya untuk menyimpan satu set konstanta tetap yang Anda tetapkan sendiri. Aplikasi spesifik terserah Anda. Tidak ada yang mengatakan kapan, mengapa, atau bagaimana menggunakan sesuatu. Itu terserah kebutuhan pengembang. Yang perlu Anda pahami adalah apa itu dan bagaimana cara kerjanya.
Steve
4

Menurut pendapat saya, semua jawaban yang Anda jawab sekarang valid, tetapi dalam pengalaman saya, saya akan mengungkapkannya dalam beberapa kata:

Gunakan enums jika Anda ingin kompiler memeriksa validitas nilai pengidentifikasi.

Jika tidak, Anda dapat menggunakan string seperti biasa (mungkin Anda mendefinisikan beberapa "konvensi" untuk aplikasi Anda) dan Anda akan sangat fleksibel ... tetapi Anda tidak akan mendapatkan keamanan 100% terhadap kesalahan ketik pada string Anda dan Anda hanya akan menyadarinya dalam runtime.

Rafa
sumber
3

Gunakan enums untuk TYPE SAFETY, ini adalah fitur bahasa sehingga Anda biasanya akan mendapatkan:

  • Dukungan kompiler (segera lihat masalah jenis)
  • Dukungan alat dalam IDE (pelengkapan otomatis dalam kasus sakelar, kasus yang hilang, force default, ...)
  • Dalam beberapa kasus, kinerja enum juga bagus ( EnumSet , typesafe alternatif dari "flag bit" berbasis int tradisional )

Enums dapat memiliki metode, konstruktor, Anda bahkan dapat menggunakan enums di dalam enums dan menggabungkan enums dengan antarmuka.

Anggap enum sebagai tipe untuk menggantikan set konstanta int yang terdefinisi dengan baik (yang Java 'warisi' dari C / C ++) dan dalam beberapa kasus untuk menggantikan bit flag.

Buku Effective Java 2nd Edition memiliki seluruh bab tentang mereka dan membahas lebih detail. Juga lihat posting Stack Overflow ini .

Christophe Roussy
sumber
2

Java memungkinkan Anda membatasi variabel untuk memiliki salah satu dari hanya beberapa nilai yang telah ditentukan - dengan kata lain, satu nilai dari daftar yang disebutkan. Menggunakan enumsdapat membantu mengurangi bug dalam kode Anda. Berikut ini contoh di enumsluar kelas:

enums coffeesize{BIG , HUGE , OVERWHELMING }; 
//This semicolon is optional.

Hal ini membatasi coffeesizeuntuk memiliki baik: BIG, HUGE, atau OVERWHELMINGsebagai variabel.

Rahul Prajapat
sumber
2

Enum? Mengapa harus digunakan? Saya pikir itu lebih dipahami ketika Anda akan menggunakannya. Saya memiliki pengalaman yang sama.

Katakanlah Anda memiliki operasi buat, hapus, edit, dan baca basis data.

Sekarang jika Anda membuat enum sebagai operasi:

public enum operation {
    create("1")
    delete("2")
    edit("3")
    read("4")

    // You may have is methods here
    public boolean isCreate() {
        return this.equals(create);
    }
    // More methods like the above can be written

}

Sekarang, Anda dapat mendeklarasikan sesuatu seperti:

private operation currentOperation;

// And assign the value for it 
currentOperation = operation.create

Jadi Anda bisa menggunakannya dengan banyak cara. Itu selalu baik untuk memiliki enum untuk hal-hal tertentu karena operasi database pada contoh di atas dapat dikontrol dengan memeriksa operasi saat ini . Mungkin orang bisa mengatakan ini bisa diselesaikan dengan variabel dan nilai integer juga. Tapi saya percaya Enum adalah cara yang lebih aman dan programmer.

Hal lain: Saya pikir setiap programmer menyukai boolean , bukan? Karena hanya dapat menyimpan dua nilai, dua nilai spesifik. Jadi Enum dapat dianggap memiliki jenis fasilitas yang sama di mana pengguna akan menentukan berapa banyak dan jenis nilai apa yang akan disimpan, hanya dengan cara yang sedikit berbeda. :)

Abhishek Bhandari
sumber
1

Sejauh ini, saya tidak pernah perlu menggunakan enum. Saya telah membaca tentang mereka sejak mereka diperkenalkan dalam versi 1,5 atau harimau seperti yang disebut kembali pada hari itu. Mereka tidak pernah benar-benar memecahkan 'masalah' bagi saya. Bagi mereka yang menggunakannya (dan saya melihat banyak dari mereka melakukan), yakin itu pasti melayani beberapa tujuan. Hanya 2 pound saya.

happybuddha
sumber
1

Yang memberi saya momen Ah-Ha adalah realisasi ini: bahwa Enum memiliki konstruktor pribadi yang hanya dapat diakses melalui pencacahan publik:

enum RGB {
    RED("Red"), GREEN("Green"), BLUE("Blue");

    public static final String PREFIX = "color ";

    public String getRGBString() {
        return PREFIX + color;
    }

    String color;

    RGB(String color) {
        this.color = color;
    }
}

public class HelloWorld {
    public static void main(String[] args) {
        String c = RGB.RED.getRGBString();
        System.out.print("Hello " + c);
    }
}
Djangofan
sumber
1

Bagi saya untuk membuat kode dapat dibaca di masa depan, kasus enumerasi aplyable yang paling berguna diwakili dalam cuplikan berikutnya:

public enum Items {
    MESSAGES, CHATS, CITY_ONLINE, FRIENDS, PROFILE, SETTINGS, PEOPLE_SEARCH, CREATE_CHAT
}

@Override
public boolean onCreateOptionsMenu(Menu menuPrm) {
    // Inflate the menu; this adds items to the action bar if it is present.
    getMenuInflater().inflate(R.menu.main, menuPrm);
    View itemChooserLcl;
    for (int i = 0; i < menuPrm.size(); i++) {
        MenuItem itemLcl  = menuPrm.getItem(i);
            itemChooserLcl = itemLcl.getActionView();
            if (itemChooserLcl != null) {
                 //here Im marking each View' tag by enume values:
                itemChooserLcl.setTag(Items.values()[i]);
                itemChooserLcl.setOnClickListener(drawerMenuListener);
            }
        }
    return true;
}
private View.OnClickListener drawerMenuListener=new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        Items tagLcl= (Items) v.getTag();
        switch (tagLcl){
            case MESSAGES: ;
            break;
            case CHATS : ;
            break;
            case CITY_ONLINE : ;
            break;
            case FRIENDS : ;
            break;
            case  PROFILE: ;
            break;
            case  SETTINGS: ;
            break;
            case  PEOPLE_SEARCH: ;
            break;
            case  CREATE_CHAT: ;
            break;
        }
    }
};
CodeToLife
sumber
1

Dalam pengalaman saya, saya telah melihat penggunaan Enum terkadang menyebabkan sistem menjadi sangat sulit untuk diubah. Jika Anda menggunakan Enum untuk serangkaian nilai spesifik domain yang sering berubah, dan memiliki banyak kelas dan komponen lain yang bergantung padanya, Anda mungkin ingin mempertimbangkan untuk tidak menggunakan Enum.

Misalnya, sistem perdagangan yang menggunakan Enum untuk pasar / pertukaran. Ada banyak pasar di luar sana dan hampir pasti akan ada banyak sub-sistem yang perlu mengakses daftar pasar ini. Setiap kali Anda ingin pasar baru ditambahkan ke sistem Anda, atau jika Anda ingin menghapus pasar, semua yang ada di bawah matahari harus dibangun kembali dan dilepaskan.

Contoh yang lebih baik adalah sesuatu seperti jenis kategori produk. Katakanlah perangkat lunak Anda mengelola inventaris untuk department store. Ada banyak kategori produk, dan banyak alasan mengapa daftar kategori ini dapat berubah. Manajer mungkin ingin menyediakan lini produk baru, menyingkirkan lini produk lain, dan mungkin mengatur ulang kategori dari waktu ke waktu. Jika Anda harus membangun kembali dan memindahkan semua sistem Anda hanya karena pengguna ingin menambahkan kategori produk, maka Anda telah mengambil sesuatu yang seharusnya sederhana dan cepat (menambahkan kategori) dan membuatnya sangat sulit dan lambat.

Intinya, Enums baik jika data yang Anda wakili sangat statis dari waktu ke waktu dan memiliki jumlah dependensi yang terbatas. Tetapi jika data banyak berubah dan memiliki banyak dependensi, maka Anda memerlukan sesuatu yang dinamis yang tidak diperiksa pada waktu kompilasi (seperti tabel database).

BradB
sumber
1

Singleton berbasis enum

tampilan modern pada masalah lama

Pendekatan ini mengimplementasikan singleton dengan mengambil keuntungan dari jaminan Java bahwa setiap nilai enum hanya dipakai satu kali dalam program Java dan enum memberikan dukungan implisit untuk keselamatan benang. Karena nilai Java enum dapat diakses secara global, sehingga dapat digunakan sebagai singleton.

public enum Singleton {
    SINGLETON; 
    public void method() { }
}

Bagaimana cara kerjanya? Nah, baris dua kode dapat dianggap sesuatu seperti ini:

public final static Singleton SINGLETON = new Singleton(); 

Dan kita mendapatkan singleton awal awal yang bagus.

Ingatlah bahwa karena ini adalah enum, Anda juga selalu dapat mengakses instance via Singleton.INSTANCE:

Singleton s = Singleton.INSTANCE;
Keuntungan
  • Untuk mencegah pembuatan instance lain dari singleton selama deserialisasi gunakan singleton berbasis enum karena serialisasi enum dirawat oleh JVM. Enum serialisasi dan deserialisasi bekerja secara berbeda daripada untuk objek java normal. Satu-satunya hal yang menjadi serial adalah nama nilai enum. Selama proses deserialisasi, enumvalueOf metode digunakan dengan nama deserialisasi untuk mendapatkan contoh yang diinginkan.
  • Singleton berbasis Enum memungkinkan untuk melindungi diri dari serangan refleksi. Tipe enum sebenarnya memperluas Enumkelas java . Alasan bahwa refleksi tidak dapat digunakan untuk instantiate objek dari tipe enum adalah karena spesifikasi java tidak diizinkan dan aturan tersebut dikodekan dalam implementasi newInstancemetode Constructorkelas, yang biasanya digunakan untuk membuat objek melalui refleksi:
if ((clazz.getModifiers() & Modifier.ENUM) != 0)
    throw new IllegalArgumentException("Cannot reflectively create enum objects");
  • Enum tidak seharusnya dikloning karena harus ada tepat satu instance dari setiap nilai.
  • Kode paling singkat di antara semua realisasi tunggal.
Kekurangan
  • Singleton berbasis enum tidak memungkinkan inisialisasi malas.
  • Jika Anda mengubah desain dan ingin mengubah singleton menjadi multiton, enum tidak akan mengizinkan ini. Pola multiton digunakan untuk pembuatan beberapa contoh yang terkontrol, yang dikelola melalui penggunaan a map. Alih-alih memiliki satu instance per aplikasi (misalnya java.lang.Runtime), pola multiton bukannya memastikan satu instance per kunci .
  • Enum hanya muncul di Java 5 sehingga Anda tidak dapat menggunakannya dalam versi sebelumnya.

Ada beberapa realisasi pola tunggal masing-masing dengan kelebihan dan kekurangan.

  • Ingin memuat singleton
  • Penguncian tunggal singleton
  • Idiom inisialisasi sesuai permintaan
  • Singleton berbasis enum

Deskripsi mendetail masing-masing dari mereka terlalu bertele-tele jadi saya hanya menaruh tautan ke artikel yang bagus - Yang ingin Anda ketahui tentang Singleton

Oleg Poltoratskii
sumber
0

Saya akan menggunakan enum sebagai instrumen pemetaan yang berguna, menghindari beberapa if-else asalkan beberapa metode diterapkan.

public enum Mapping {

    ONE("1"),
    TWO("2");

    private String label;

    private Mapping(String label){
        this.label = label;
    }

    public static Mapping by(String label) {

        for(Mapping m: values() {
            if(m.label.equals(label)) return m;
        }

        return null;
    }

}

Jadi metodenya by(String label) memungkinkan Anda untuk mendapatkan nilai yang dihitung dengan non-disebutkan. Selanjutnya, seseorang dapat menemukan pemetaan antara 2 enum. Bisa juga mencoba '1 ke banyak' atau 'banyak ke banyak' selain hubungan default 'satu ke satu'

Pada akhirnya, enumadalah kelas Java. Jadi, Anda dapat memiliki mainmetode di dalamnya, yang mungkin berguna ketika perlu melakukan beberapa operasi pemetaan argssegera.

TEH EMPRAH
sumber
0

Alih-alih membuat banyak deklarasi const int

Anda dapat mengelompokkan semuanya dalam 1 enum

Jadi semuanya diatur oleh kelompok umum tempat mereka berada

Vincent Tang
sumber
0

Enum seperti kelas. Seperti kelas, ia juga memiliki metode dan atribut.

Perbedaan dengan kelas adalah: 1. konstanta enum bersifat publik, statis, final. 2. enum tidak dapat digunakan untuk membuat objek dan itu tidak dapat memperluas kelas lain. Tetapi dapat mengimplementasikan antarmuka.

Shetu
sumber
0

Selain @BradB Jawab:

Itu sangat benar ... Aneh bahwa itu adalah satu-satunya jawaban yang menyebutkan itu. Ketika pemula menemukan enum, mereka dengan cepat menganggapnya sebagai trik sulap untuk pengidentifikasi pengenal yang valid untuk kompiler. Dan ketika kode itu dimaksudkan untuk digunakan pada sistem terdistribusi, mereka menangis ... beberapa bulan kemudian. Mempertahankan kompatibilitas ke belakang dengan enum yang berisi daftar nilai yang tidak statis adalah masalah nyata, dan menyakitkan. Ini karena ketika Anda menambahkan nilai ke enum yang ada, tipenya berubah (meskipun namanya tidak).

"Ho, tunggu, ini mungkin terlihat seperti tipe yang sama, kan? Lagipula, mereka enum dengan nama yang sama - dan bukankah enums hanya bilangan bulat di bawah tenda?" Dan untuk alasan ini, kompiler Anda kemungkinan tidak akan menandai penggunaan satu definisi dari tipe itu sendiri di mana ia mengharapkan yang lain. Tetapi pada kenyataannya, mereka (dalam cara yang paling penting) adalah tipe yang berbeda. Yang paling penting, mereka memiliki domain data yang berbeda - nilai yang dapat diterima mengingat jenisnya. Dengan menambahkan nilai, kami telah secara efektif mengubah jenis enum dan karenanya merusak kompatibilitas.

Kesimpulannya: Gunakan saat Anda inginkan, tetapi, harap periksa apakah domain data yang digunakan adalah kumpulan yang terbatas, sudah dikenal, dan telah diperbaiki .

Nicolas Voron
sumber