Numaralandırmalar nedir ve neden faydalıdırlar?


488

Bugün bu sitedeki bazı sorulara göz atıyordum ve bu çözüm için iddia edilen iplik güvenliği faydaları hakkında enum singleton deseninde kullanıldığından bahsetmiştim .

Hiç kullanmadım enumve Java'da birkaç yıldan uzun süredir program yapıyorum. Ve görünüşe göre çok değiştiler. Şimdi bile kendi içlerinde OOP tam destek veriyorlar.

Şimdi neden ve ne için günlük programlamada enum kullanmalıyım?




Özel yapıcıya sahip olduğu için enumları başlatamazsınız, jvm başlangıcında somutlaştırılırlar, bu nedenle onun singletonu, Enums iş parçacığı için güvenli değildir.
Arnav Joshi

Yanıtlar:


633

Değişken (özellikle bir yöntem parametresi) olası küçük bir değer kümesinden yalnızca birini alabiliyorsa, her zaman numaralandırma kullanmalısınız. Örnekler, tür sabitleri (sözleşme durumu: "kalıcı", "geçici", "çırak") veya bayraklar ("şimdi çalıştır", "yürütmeyi ertele") olabilir.

Tamsayılar (veya Dize kodları) yerine numaralandırmalar kullanırsanız, derleme zamanı denetimini artırır ve hataların geçersiz sabitlerden geçmesini önlersiniz ve hangi değerlerin yasal olduğunu belgelersiniz.

BTW, numaralandırmaların aşırı kullanımı, yöntemlerinizin çok fazla iş yaptığı anlamına gelebilir (ne yaptığını değiştiren birkaç bayrak alan bir yöntem yerine birkaç ayrı yöntem olması genellikle daha iyidir), ancak bayraklar veya tür kodları kullanmanız gerekiyorsa, enums gitmek için bir yol.

Örnek olarak hangisi daha iyi?

/** 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)

karşı

/** 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)

Aşağıdaki gibi bir yöntem çağrısı:

int sweetFoobangCount = countFoobangs(3);

sonra olur:

int sweetFoobangCount = countFoobangs(FB_TYPE.SWEET);

İkinci örnekte, hangi türlere izin verildiği hemen anlaşılıyor, dokümanlar ve uygulama senkronize edilemiyor ve derleyici bunu zorlayabilir. Ayrıca, geçersiz bir çağrı

int sweetFoobangCount = countFoobangs(99);

artık mümkün değil.


41
Numaralandırma kullanıyorsanız ve değerlerin birleşimine izin vermek istiyorsanız, EnumSet'i kullanın. Bu, genel statik final EnumSet <FB_TYPE> ALL = EnumSet.allOf (FB_TYPE.class) gibi her türlü temiz yardımcıyla birlikte gelir;
RobAu

20
Bu cevaplar SO'da gerçekten görmek istediğim cevaplar, çünkü birisi buna gerçek bir çaba sarf etti, şimdi iyi anladım enumlar!
Dediqated

1
Bunun doğru olduğunu düşünmüyorum you should *always* use enums when a variable can only take one out of a small set of possible values. Sabit değerleri 'ikili bayrak' olarak kullanmak (mantıksal oring ile), bellekte yetersiz olduğunuz gerçek zamanlı uygulamalar için yararlı olabilir.
Elist

@ Enums kullanarak kodlarınızın okunabilirliğini artırır, Eğer belirli bir zamanda sabit kullanırsanız, siz veya halefiniz neden kullanıldığını bilmiyor ...
:)

136

Neden herhangi bir programlama dili özelliği kullanıyorsunuz? Hiç dilimizin olmasının nedeni

  1. Programcılar verimli ve doğru bir şekilde bilgisayarları algoritmaları ifade etmek için bir bilgisayar kullanabilirsiniz.
  2. Başkalarının yazdığı algoritmaları anlamak ve doğru şekilde değiştirmek için bakımcılar.

Enums, çok fazla kazan plakası yazmadan hem doğruluk hem de okunabilirlik olasılığını artırır. Boyler plakası yazmak istiyorsanız, numaralandırmayı "simüle edebilirsiniz":

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();
}

Şimdi yazabilirsiniz:

Color trafficLightColor = Color.RED;

Yukarıdaki kazan plakası ile aynı etkiye sahiptir.

public enum Color { RED, AMBER, GREEN };

Her ikisi de derleyiciden aynı düzeyde denetim yardımı sağlar. Boilerplate sadece daha fazla yazıyor. Ancak çok fazla yazarak programcıyı daha verimli hale getirir (bkz. 1), bu yüzden değerli bir özelliktir.

En az bir nedenden daha değerlidir:

Anahtar ifadeleri

O bir şey static finalenum simülasyon yukarıda gelmez değil size güzel switchdavaları. Numaralandırma türleri için Java anahtarı, numaralandırma durumlarının kapsamını çıkarmak için değişkeninin türünü kullanır, bu nedenle enum Coloryukarıdakiler için yalnızca şunu söylemeniz gerekir:

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

Color.REDDurumlarda olmadığını unutmayın . Enum kullanmıyorsanız, adlandırılmış miktarları kullanmanın tek yolu switchşudur:

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

Ama şimdi bir rengi tutacak bir değişkenin türü olmalıdır int. Enum ve static finalsimülasyonun güzel derleyici kontrolü gitti. Mutlu değil.

Bir uzlaşma, simülasyonda skaler değerli bir üye kullanmaktır:

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);
}

Şimdi:

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

Ama dikkat edin, daha da kazanı!

Bir enum'u singleton olarak kullanma

Yukarıdaki kazan plakasından, bir enumun neden bir tekliton uygulamak için bir yol sağladığını görebilirsiniz. Yazmak yerine:

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

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

ve daha sonra

SingletonClass.INSTANCE

sadece söyleyebiliriz

public enum SingletonClass {
    INSTANCE;

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

bize aynı şeyi verir. Bundan kaçabiliriz , çünkü Java enumları tam sınıflar olarak sadece biraz sözdizimsel şeker serpilir. Bu yine daha az kaynatma plakasıdır, ancak deyim size aşina olmadığı sürece açık değildir. Ben de onlar singleton için çok mantıklı olmasa bile çeşitli enum fonksiyonlarını olsun gerçeği sevmediğim: ordve valuesvb (Orada bir hileli simülasyon aslında Color extends Integero anahtarı ile çalışacak, ama o kadar aldatıcı öyle daha neden enumdaha iyi bir fikir olduğunu açıkça gösteriyor .)

İplik güvenliği

İplik güvenliği, yalnızca kilitlenmeden tembel tembel temalar oluşturulduğunda potansiyel bir sorundur.

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
}

Birçok iş parçacığı hala boşken getInstanceaynı anda çağrı yaparsa INSTANCE, herhangi bir sayıda örnek oluşturulabilir. Bu kötü. Tek çözüm, synchronizeddeğişkeni korumak için erişim eklemektir INSTANCE.

Ancak, static finalyukarıdaki kodda bu sorun yoktur. Örneği sınıf yükleme zamanında hevesle oluşturur. Sınıf yükleme senkronize edilir.

enumİlk kullanımda kadar başlatılmadı çünkü tekil etkin bir tembel. Java başlatma da senkronize edilir, bu nedenle birden çok iş parçacığı birden çok örneğini başlatamaz INSTANCE. Çok az kodla tembel bir şekilde başlatılmış singleton alıyorsunuz. Tek olumsuz, oldukça belirsiz sözdizimidir. Deyimi bilmeniz veya neler olduğunu bilmek için sınıf yükleme ve başlatmanın nasıl çalıştığını iyice anlamanız gerekir.


15
Bu son paragraf benim için singleton durumunu gerçekten açıklığa kavuşturdu. Teşekkürler! Gözden kaçan herhangi bir okuyucu bunu tekrar okumalıdır.
Basil Bourque

Bunu okuyordum, stackoverflow.com/questions/16771373/… . Şimdi son parayla kafam karıştı. Enum, lay başlatma özelliğini nasıl sağlamaz?
Deepankar Singh

static finalalanlar yükleme zamanında değil , sınıf başlatma zamanında başlatılır . enumSabit başlatma ile tam olarak aynıdır (aslında, kaputun altında aynıdır). Bu nedenle, singletons için “zeki” tembel başlatma kodunu uygulamaya çalışmak ilk Java sürümünde bile her zaman anlamsızdı.
Holger

42

Daha önce bahsedilen kullanım örneklerinin yanı sıra, çoğu temel OOP yönergelerini izleyerek enumları strateji modelini uygulamak için yararlı buluyorum:

  1. Verilerin bulunduğu koda sahip olmak (yani, numaralandırmanın içinde - veya genellikle yöntemleri geçersiz kılabilecek numaralandırma sabitleri içinde).
  2. İstemci kodunu numaralandırmaya bağlamak için bir arabirim (veya daha fazlasını) uygulama (yalnızca bir dizi varsayılan uygulama sağlamalıdır).

En basit örnek bir dizi Comparatoruygulama olacaktır:

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());
        }
    };
}

Bu "desen" çok daha karmaşık senaryolarda kullanılabilir ve enum ile birlikte gelen tüm güzellikleri kapsamlı bir şekilde kullanır: örneklerin üzerinde yineleme, örtük sıralarına dayanarak, bir örneği adına göre alma, doğru örneği sağlayan statik yöntemler Ve yine de tüm bunlar arayüzün arkasına gizlenmiştir, böylece kodunuz "varsayılan seçenekler" arasında bulunmayan bir şey istemeniz durumunda özel uygulamalar ile çalışır.

Bunu, tüm mantığın bir enumda kapsüllendiği zaman tanecikliği kavramını (günlük, haftalık, vb.) Modellemek için başarıyla uygulandığını gördüm (belirli bir zaman aralığı için doğru tanecikliği seçerek, her tanecikliğe sabit olarak belirli davranış yöntemleri vb.). Yine de, Granularityhizmet katmanının gördüğü gibi basitçe bir arayüzdü.


2
Ayrıca ekleyebilirsiniz CASE_INSENSITIVE { @Override public int compare(String s1, String s2) { return s1.compareToIgnoreCase(s2); }. Henüz bahsedilmeyen bir avantaj, sağlam bir Serileştirme desteği almanızdır; kalıcı form, karşılaştırıcılarınızın uygulama ayrıntılarına bağlı olarak değil, yalnızca sınıf adını ve sabit adı içerir.
Holger

32

Diğer yanıtların hiçbirini kapsamayan bir şey, enumları özellikle güçlü kılan, şablon yöntemlerine sahip olma yeteneğidir . Yöntemler, taban enumunun bir parçası olabilir ve her tip tarafından geçersiz kılınabilir. Ve, numaralandırmaya ekli davranış ile, bu blog gönderisinin gösterdiği gibi, eğer if-else yapıları veya anahtar ifadeleri gereksinimini genellikle ortadan kaldırır - enum.method()koşullu olarak ilk başta ne yürütülecek. Aynı örnek, daha temiz DSL benzeri kod üretmenin yanı sıra numaralandırmalarla statik içe aktarma kullanımını da gösterir.

Diğer bazı ilginç nitelikler çeteleler için uygulanmasını sağlamak gerçeği içerir equals(), toString()ve hashCode()ve uygulanması Serializableve Comparable.

Tüm bu numaraların sundukları tam bir özet için Bruce Eckel'in Java'nın 4. baskısını , 4. bölümün tamamını konuya adamasını tavsiye ederim . Özellikle aydınlatıcı Rock, Kağıt, Makas (yani RoShamBo) oyununu numaralandırma olarak içeren örnekler.


23

Java belgelerinden -

Sabit bir sabit kümesini temsil etmeniz gerektiğinde enum türlerini kullanmalısınız. Bu, güneş sistemimizdeki gezegenler ve derleme zamanında tüm olası değerleri bildiğiniz veri kümeleri gibi doğal numaralandırma türlerini içerir - örneğin, bir menüdeki seçenekler, komut satırı bayrakları vb.

Yaygın bir örnek, bir sınıfı bir dizi özel statik son int sabitiyle (makul sayıda sabit içinde) bir numaralandırma türüyle değiştirmektir. Temel olarak derleme zamanında "birşeyin" tüm olası değerlerini bildiğinizi düşünüyorsanız bunu bir enum türü olarak temsil edebilirsiniz. Numaralandırmalar sabitleri olan bir sınıfa göre okunabilirlik ve esneklik sağlar.

Enum tiplerini düşünebileceğim birkaç başka avantaj. Her zaman belirli bir numaralandırma sınıfının bir örneğidir (bu nedenle numaralandırmaları singleton geldiğinde kullanma kavramı). Diğer bir avantaj da enumları anahtar-durum ifadesinde bir tür olarak kullanabilmenizdir. Ayrıca , okunabilir dizeler olarak yazdırmak için numara üzerindeki toString () öğesini de kullanabilirsiniz .


8
Yılın 366 günü boyunca bir numaralandırma kullanır mıydınız? Sabit bir sabit (366) kümesidir (günler değişmemektedir). Yani bu yapmanız gerektiğini gösteriyor. : - / Sabit setin boyutunu kısıtlardım.
Ocak'ta

2
@marcog Biraz zekice düşünerek, bir haftanın günlerini ve her ayın günlerini kompakt bir numarada özetlemek mümkün olabilir.
James P.

1
Haftanın günleri bahsetmişken ... DayOfWeekenum şimdi Java 8 yerleşik ve daha sonra bir parçası olarak, önceden tanımlanan java.time çerçevesi (ve Java 6 ve 7 geri portlu ve Android'e ).
Basil Bourque

19

Şimdi neden ve ne için günlük programlamada enum kullanmalıyım?

Okunabilirliği artırırken, ufacık bir sabit sabit kümesini veya bir iç sınıf modunu temsil etmek için bir Numaralandırma kullanabilirsiniz. Ayrıca, Numaralamalar yöntem parametrelerinde kullanıldığında belirli bir katılık uygulayabilir. Oracle'ın sitesindeki Gezegenler örneğindeki gibi bir kurucuya bilgi aktarma ilginç olanağı sunar ve keşfettiğiniz gibi, tek bir desen oluşturmak için basit bir yol sağlar.

ex: ayırıcıyı tüm tamsayılar yerine eklediğinizde, bir IDE'de gösterilen sabit değer kümesini Locale.setDefault(Locale.US)daha iyi okur Locale.setDefault(1)ve kullanımını zorlar ..


@arnt Sorudaki dilbilgisini de düzelttim. Teşekkürler.
James P.

13

Enums kendi kendini belgeleyen bir şekilde sabit bir değerler kümesi numaralandırır.
Kodunuzu daha açık ve daha az hataya açık hale getirir.

Neden sabitler için Stringveya intyerine Enumsabit kullanmıyorsunuz ?

  1. Derleyici yazım hatalarına izin vermez , sabit kümenin dışında değerler de değildir , çünkü numaralandırmalar kendi başlarına türlerdir . Sonuçlar:
    • Argümenizin geçerli aralıkta olduğundan emin olmak için bir ön koşul (veya bir el kitabı if) yazmak zorunda kalmazsınız .
    • Tipi değişmez ücretsiz olarak geliyor.
  2. Diğer numaralar gibi sıralamalar da davranış gösterebilir.
  3. Her Stringneyse, s'yi kullanmak için muhtemelen benzer miktarda belleğe ihtiyacınız olacaktır (bu, karmaşıklığına bağlıdır Enum).

Dahası, Enumörneklerinin her biri kendi davranışını tanımlayabileceğiniz bir sınıftır.

Ayrıca, Singleton Paterninin basitleştirilmesinde büyük bir uygulama görmüş olan örneklerin (numaralandırma yüklendiğinde) oluşturulması sırasında iplik güvenliğini sağlarlar .

Bu blog , ayrıştırıcı için bir Devlet Makinesi gibi bazı uygulamalarını göstermektedir .


13

Bunun alanlar ve a enumsolan diğer sınıflar gibi olduğunu bilmek faydalıdır .Constantprivate constructor

Örneğin,

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

Derleyici bunu şöyle derler;

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...
}

12

enumnumaralandırma anlamına gelir, yani tek tek bahsedin.

Bir enum , sabit sabit kümesi içeren bir veri türüdür.

VEYA

An derleme zamanında bilinen sabit bir örnek kümesiyle a enumgibidir class.

Örneğin:

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());
        }

    }
}

Enum'un avantajları:

  • enum, çalışma zamanında hataları önlemek için derleme zamanı denetiminde tür güvenliğini artırır.
  • enum anahtarda kolayca kullanılabilir
  • enum geçilebilir
  • enum alanları, yapıcıları ve yöntemleri olabilir
  • enum birçok arabirim uygulayabilir, ancak Enum sınıfını dahili olarak genişlettiği için herhangi bir sınıfı genişletemez

için daha fazla


9

Numaralandırma nedir

  • enum Enumeration için yeni bir veri türü olarak tanımlanan bir anahtar kelimedir. Tipik olarak güvenli numaralandırmalar liberal olarak kullanılmalıdır. Özellikle, ilgili öğelerin kümelerini temsil etmek için çok daha eski API'larda kullanılan basit Dize veya int sabitlerine sağlam bir alternatiftir.

Neden numaralandırma kullanılır?

  • numaralandırmalar dolaylı olarak java.lang.Enum alt sınıflarıdır
  • bir enum bir sınıfın üyesiyse, dolaylı olarak statiktir
  • new, enum tipinin içinde bile asla bir enum ile kullanılamaz
  • isim ve değer Sadece numaralandırma sabitlerinin metnini kullanırsanız, istenirse herhangi bir içerik sağlamak için toString geçersiz kılınabilir
  • enum sabitleri için, eşittir ve == aynı şeye eşittir ve birbirinin yerine kullanılabilir
  • enum sabitleri dolaylı olarak halka açık statik final

Not

  • numaralandırmalar hiçbir sınıfı genişletemez.
  • Bir enum bir üst sınıf olamaz.
  • enum sabitlerinin görünme sırasına "doğal düzen" denir ve diğer öğeler tarafından da kullanılan sırayı tanımlar: CompareTo, değerlerin yineleme sırası, EnumSet, EnumSet.range.
  • Numaralandırma yapıcılara, statik ve örnek bloklarına, değişkenlere ve yöntemlere sahip olabilir, ancak soyut yöntemlere sahip olamaz.

4
Neden numaralandırma kullandığınızı açıklamıyorsunuz. Sıralanmamış başlıkların altındaki numaralandırmaların birkaç özelliğini listeliyorsunuz.
Duncan Jones

@DuncanJones final, static terimleri numaralandırma kullanma amacını vermez mi?
tinker_fairy

8

Başkaları tarafından söylenenler dışında .. Eskiden çalıştığım daha eski bir projede, varlıklar (bağımsız uygulamalar) arasında çok sayıda iletişim, küçük bir kümeyi temsil eden tamsayılar kullanıyordu. Kümeyi nesneden enumalmak için statik yöntemlerle ve viceversa'da bildirmek yararlı oldu . Kod daha temiz görünüyordu, büyük / küçük harf kullanımını ve günlüklere daha kolay yazmayı değiştiriyor.enumvalue

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;
    }
}

enumKullanarak ProtocolType.fromInt(2) günlüklere Yaz kullanarak alınan değerlerden (örn. 1,2) nesne oluşturmamyEnumObj.name

Bu yardımcı olur umarım.


6

Enum, tüm Objectsınıf ve soyut sınıf yöntemlerini devralır Enum. Bu yüzden yansıma, çoklu kullanım, serilizasyon, karşılaştırılabilir vb. Yöntemlerini kullanabilirsiniz. Enum yerine statik bir sabit beyan ederseniz, yapamazsınız. Bunun yanı sıra, Enum'un değeri DAO katmanına da aktarılabilir.

Göstermek için örnek bir program.

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;
        }
    }
}

4

ENum "Numaralandırılmış Tip" anlamına gelir. Kendinizi tanımladığınız sabit bir sabitler kümesine sahip bir veri türüdür.


Neden bir numaralandırma kullanacağınızı açıklamadınız.
Duncan Jones

4
Evet yaptım. Kendinizi tanımladığınız sabit bir sabit kümesi saklamak için kullanırsınız. Özel uygulaması size kalmış. Bir şeyin ne zaman, neden veya nasıl kullanılacağını söylemek diye bir şey yoktur. Bu geliştiricinin ihtiyaçlarına bağlıdır. Anlamanız gereken tek şey ne olduğu ve nasıl çalıştığıdır.
Steve

4

Benim düşünceme göre, şimdiye kadar aldığınız tüm cevaplar geçerli, ancak tecrübelerime göre, bunu birkaç kelimeyle ifade ederim:

Derleyicinin bir tanımlayıcının değerinin geçerliliğini denetlemesini istiyorsanız numaralandırmalar kullanın.

Aksi takdirde, dizeleri her zaman yaptığınız gibi kullanabilirsiniz (muhtemelen uygulamanız için bazı "kurallar" tanımladınız) ve çok esnek olacaksınız ... ancak dizelerinizdeki yazım hatalarına karşı% 100 güvenlik elde edemezsiniz ve yalnızca bunları gerçekleştirirsiniz. çalışma zamanında.


3

TYPE SAFETY için numaralandırmalar kullanın, bu bir dil özelliğidir, bu nedenle genellikle şunları elde edersiniz:

  • Derleyici desteği (hemen tür türlerine bakın)
  • IDE'lerde takım desteği (anahtar durumunda otomatik tamamlama, eksik durumlar, varsayılan zorlama, ...)
  • Bazı durumlarda enum performansı da mükemmeldir ( EnumSet , geleneksel int tabanlı "bit bayraklarına" typesafe alternatifi ).

Numaralandırmalar yöntemlere, kuruculara sahip olabilir, hatta numaralandırmaların içindeki sıralamaları kullanabilir ve sıralamaları arabirimlerle birleştirebilirsiniz.

Enumları, iyi tanımlanmış bir int sabitleri (Java'nın C / C ++ 'dan miras aldığı) ve bazı durumlarda bit bayraklarını değiştirmek için türler olarak düşünün.

Effective Java 2nd Edition kitabı onlar hakkında bütün bir bölüm içeriyor ve daha fazla ayrıntıya giriyor. Ayrıca bu Yığın Taşması gönderisine bakın .


2

Java, değişkeni önceden tanımlanmış birkaç değerden birine, başka bir deyişle numaralandırılmış listeden bir değere sahip olacak şekilde kısıtlamanızı sağlar. Kullanmak enums, kodunuzdaki hataların azaltılmasına yardımcı olabilir. enumsSınıf dışında bir örnek :

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

Bu kısıtlar coffeesizeya sahip: BIG, HUGEya da OVERWHELMINGbir değişken olarak.


2

Sıralama? Neden kullanılmalı? Bence ne zaman kullanacağınız daha iyi anlaşılıyor. Aynı deneyime sahibim.

Veritabanı oluşturma, silme, düzenleme ve okuma işlemleriniz olduğunu varsayalım.

Şimdi işlem olarak bir numaralandırma oluşturursanız:

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

}

Şimdi şöyle bir şey beyan edebilirsiniz:

private operation currentOperation;

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

Böylece birçok şekilde kullanabilirsiniz. Yukarıdaki örnekte veritabanı işlemi currentOperation kontrol edilerek kontrol edilebildiğinden, belirli şeyler için numaralandırma her zaman iyidir . Belki de bunun değişkenler ve tamsayı değerleri ile de yapılabileceğini söyleyebiliriz. Ama Enum'un daha güvenli ve programcı bir yol olduğuna inanıyorum.

Başka bir şey: Her programcı seviyor boole biz değil mi? Çünkü sadece iki değer, iki özel değer depolayabilir. Bu yüzden Enum, bir kullanıcının kaç farklı ve ne tür bir değer depolayacağını, sadece biraz farklı bir şekilde tanımlayacağı aynı türdeki tesislere sahip olduğu düşünülebilir. :)


1

Şimdiye kadar hiç numaralandırma kullanmaya ihtiyacım olmadı. Gün içinde çağrıldığı gibi 1.5 veya versiyon kaplanında tanıtıldıklarından beri onları okuyorum. Benim için bir 'problemi' gerçekten hiç çözmediler. Bunu kullananlar için (ve birçoğunun yaptığını görüyorum), kesinlikle bir amaca hizmet ettiğinden eminim . Sadece benim 2 sterlin.


1

Burada birçok cevap var, sadece iki özel soruyu işaret etmek istiyorum:

1) İfadede sabit olarak kullanma Switch-case. Büyük / küçük harf değişimi, büyük / küçük harf kullanımı için String nesneleri kullanmanıza izin vermez. Numaralandırmalar kullanışlı olur. Daha fazla: http://www.javabeat.net/2009/02/how-to-use-enum-in-switch/

2) Uygulama Singleton Design Pattern- Enum yine kurtarmaya geliyor. Kullanım, burada: Bir Enum'u Java'da singleton olarak kullanmak için en iyi yaklaşım nedir?


1

Bana Ah-Ha anını veren şey şu farkındalıktı: Enum'un sadece kamu sayımı yoluyla erişilebilen özel bir kurucusu var:

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);
    }
}

1

Kodu gelecekte okunabilir hale getirmeme gelince, en yararlı uygulanabilir numaralandırma durumu bir sonraki snippet'te temsil edilir:

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;
        }
    }
};

1

Deneyimlerime göre, Enum kullanımının bazen sistemlerin değiştirilmesinin çok zor olmasına neden olduğunu gördüm. Eğer bu değişiklik sıklıkla alana özgü değerler kümesi için bir Enum kullandığınız ve diğer sınıfları ve buna bağlı bileşenlerin bir sürü varsa, dikkate almak isteyebilirsiniz değil bir Enum kullanarak.

Örneğin, piyasalar / borsalar için bir Enum kullanan bir ticaret sistemi. Dışarıda çok sayıda pazar var ve bu pazar listesine erişmesi gereken çok sayıda alt sistemin olacağı neredeyse kesin. Sisteminize her yeni pazar eklenmesini istediğinizde veya bir piyasayı kaldırmak istediğinizde, güneş altındaki her şeyin yeniden inşa edilmesi ve serbest bırakılması gerekebilir.

Daha iyi bir örnek, bir ürün kategorisi türü gibi bir şey olabilir. Yazılımınızın bir mağaza için envanteri yönettiğini varsayalım. Çok sayıda ürün kategorisi ve bu kategori listesinin değişmesinin birçok nedeni vardır. Yöneticiler yeni bir ürün hattı stoklamak, diğer ürün gruplarından kurtulmak ve kategorileri zaman zaman yeniden düzenlemek isteyebilir. Tüm sistemlerinizi yalnızca kullanıcılar bir ürün kategorisi eklemek istedikleri için yeniden kurmanız ve yeniden konuşlandırmanız gerekiyorsa, basit ve hızlı olması gereken (bir kategori ekleyerek) bir şey aldınız ve çok zor ve yavaş hale getirdiniz.

Sonuç olarak, temsil ettiğiniz veriler zaman içinde çok statikse ve sınırlı sayıda bağımlılığa sahipse numaralandırmalar iyidir. Ancak veriler çok değişiyorsa ve çok fazla bağımlılığa sahipse, derleme zamanında kontrol edilmeyen dinamik bir şeye ihtiyacınız var (veritabanı tablosu gibi).


1

Enum Tabanlı Singleton

eski bir probleme modern bir bakış

Bu yaklaşım, Java'nın herhangi bir enum değerinin bir Java programında yalnızca bir kez başlatıldığını ve enum'un iş parçacığı güvenliği için örtük destek sağladığı garantisini kullanarak singletonu uygular. Java numaralandırma değerlerine genel olarak erişilebilir olduğundan, tekil olarak kullanılabilir.

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

Bu nasıl çalışıyor? Kodun ikinci satırı şöyle bir şey olarak düşünülebilir:

public final static Singleton SINGLETON = new Singleton(); 

Ve biz iyi eski erken başlatılmış singleton olsun.

Bu bir numaralandırma olduğundan, örneğe her zaman da erişebilirsiniz Singleton.INSTANCE:

Singleton s = Singleton.INSTANCE;
Avantajları
  • Deserializasyon sırasında başka bir singleton örneği oluşturmayı önlemek için enum tabanlı singleton kullanın çünkü enum serileştirmesi JVM tarafından halledilir. Numaralandırma serileştirme ve serileştirme normal java nesnelerinden farklı çalışır. Serileştirilen tek şey numaralandırma değerinin adıdır. Serileştirme işlemi sırasında enum valueOfyöntemi, serileştirilmiş adla istenen örneği almak için kullanılır.
  • Enum tabanlı singleton kendini yansıma saldırısından korumaya izin verir. Enum türü aslında java Enumsınıfını genişletir . Yansımanın enum türündeki nesneleri somutlaştırmak için kullanılamamasının nedeni, java belirtimine izin verilmemesi ve bu kuralın , genellikle yansıma yoluyla nesne oluşturmak için kullanılan sınıf newInstanceyönteminin uygulanmasında kodlanmış olmasıdır Constructor:
if ((clazz.getModifiers() & Modifier.ENUM) != 0)
    throw new IllegalArgumentException("Cannot reflectively create enum objects");
  • Enum'un klonlanması gerekmez, çünkü her değerin tam olarak bir örneği olmalıdır.
  • Tüm singleton gerçekleştirmeleri arasında en laconic kod.
Dezavantajları
  • Enum tabanlı singleton tembel başlatmaya izin vermez.
  • Tasarımınızı değiştirdiyseniz ve singletonunuzu multiton'a dönüştürmek istiyorsanız, enum buna izin vermez. Çokton paterni, a kullanarak yönettiği birden çok örneğin kontrollü oluşturulması için kullanılır map. Uygulama başına tek bir örneğe (örneğin, java.lang.Runtime) sahip olmak yerine, çoktonlu desen, anahtar başına tek bir örneği garanti eder .
  • Enum yalnızca Java 5'te görünür, böylece önceki sürümde kullanamazsınız.

Her biri avantajları ve dezavantajları olan tekli modelin birkaç gerçekleştirilmesi vardır.

  • İstekli yükleme singletonu
  • Çift kontrollü kilitleme tekli
  • İsteğe bağlı başlatma deyimi
  • Enum Tabanlı Singleton

Ayrıntılı açıklama her biri çok ayrıntılı, bu yüzden sadece iyi bir makaleye bağlantı koydum - Singleton hakkında bilmek istediğiniz her şey


0

if-else Bazı yöntemlerin uygulanması şartıyla , enumları yararlı bir harita aracı olarak kullanırım .

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;
    }

}

Böylece yöntem by(String label), numaralandırılmamış tarafından numaralandırılmış değeri elde etmenizi sağlar. Ayrıca, 2 numara arasında haritalama icat edilebilir. 'Bire bir' varsayılan ilişkiye ek olarak '1'den çoka' veya 'çoktan çoka' deneyebilir

Sonunda enum, bir Java sınıfı. Böylece main, içinde bazı haritalama işlemleri yapmanız gerektiğinde yararlı olabilecek bir yöntem olabilir args.


0

Bir sürü const int bildirimi yapmak yerine

Hepsini 1 numarada gruplayabilirsiniz

Yani hepsi ait oldukları ortak grup tarafından organize ediliyor


0

Numaralamalar sınıf gibidir. Sınıf gibi, yöntem ve nitelikleri de vardır.

Sınıfla farklılıklar şunlardır: 1. enum sabitleri genel, statik, sondur. 2. bir enum bir nesne oluşturmak için kullanılamaz ve diğer sınıfları genişletemez. Ancak arayüzleri uygulayabilir.


0

@BradB Cevapına ek olarak:

Bu çok doğru ... Bunu söyleyen tek cevap olması garip. Yeni başlayanlar enumları keşfettiğinde, derleyici için geçerli tanımlayıcı kontrolü için bunu bir sihir numarası olarak kabul ederler. Ve kod dağıtılmış sistemlerde kullanılmak üzere tasarlandığında, bir ay sonra ... ağlarlar. Statik olmayan değerler listesi içeren numaralarla geriye doğru uyumluluğu korumak gerçek bir endişe ve acıdır. Bunun nedeni, varolan bir numaralandırmaya bir değer eklediğinizde, türünün (adının olmamasına rağmen) değişmesidir.

"Ho, bekle, aynı tip gibi görünebilir, değil mi? Sonuçta, aynı ada sahip numaralandırmalar - ve sadece başlık altındaki tamsayılar numaralandırılmıyor mu?" Ve bu nedenlerden dolayı, derleyiciniz türün kendisinin diğerinin beklediği türün bir tanımının kullanımını işaret etmeyecektir. Ama aslında, (en önemli şekillerde) farklı türlerdir. En önemlisi, farklı veri alanlarına sahiptir - tür göz önüne alındığında kabul edilebilir değerler. Bir değer ekleyerek, enum türünü etkili bir şekilde değiştirdik ve bu nedenle geriye dönük uyumluluğu bozduk.

Sonuç olarak: İstediğiniz zaman kullanın, ancak lütfen kullanılan veri alanının sonlu, zaten bilinen sabit bir küme olduğunu kontrol edin .

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.