Dizelerin numaralarını oluşturmanın en iyi yolu?


364

Sahip olmanın en iyi yolu nedir enumBir dizenin bir dizi dizeyi temsil ?

Bunu denedim:

enum Strings{
   STRING_ONE("ONE"), STRING_TWO("TWO")
}

Daha sonra bunları nasıl kullanabilirim Strings?

Yanıtlar:


605

Ne yapmak istediğini bilmiyorum, ama aslında örnek kodunu bu şekilde tercüme ettim ....

package test;

/**
 * @author The Elite Gentleman
 *
 */
public enum Strings {
    STRING_ONE("ONE"),
    STRING_TWO("TWO")
    ;

    private final String text;

    /**
     * @param text
     */
    Strings(final String text) {
        this.text = text;
    }

    /* (non-Javadoc)
     * @see java.lang.Enum#toString()
     */
    @Override
    public String toString() {
        return text;
    }
}

Alternatif olarak, için bir alıcı yöntemi oluşturabilirsiniz text.

Şimdi yapabilirsin Strings.STRING_ONE.toString();


3
Derleyici gereksinimi olup olmadığını bilmiyorum, ama private String textnihai olmalı.
Jonathan

7
@ Tomás Narros Evet, son olarak bildirdiğinizde bir değer vermediğiniz sürece yapıcıda yine de atayabilirsiniz.
Jonathan

28
Elit Gentleman Bir enum sabitinin değerinin çalışma sırasında değişmesi kötü olurdu, bu yüzden gerekli olmasa bile finalen iyisi olurdu.
Jonathan

8
O numaralamalar unutmayın inşa edilemez newyapıcı olarak private. Esasen, nesne oluşturulması yasaktır ve finalbu durumda gerçekten gerekli değildir.
Buhake Sindi

6
@BuhakeSindi: bu doğru, ama yanlışlıkla bir setText(String)numaralandırma koymak için meyilli olabilir ve bu cehennem açığa :) finaltür belge derleyici desteği ile sabit olduğunu niyetinizi. Eğer Stringsabitleri kullanacak olsaydınız, bunu beyan etmezdiniz public static String, değil mi?
TWiStErRob

104

Numaralandırma için Özel Dize Değerleri

dan http://javahowto.blogspot.com/2006/10/custom-string-values-for-enum.html

Java enum için varsayılan dize değeri, yüz değeri veya öğe adıdır. Ancak, toString () yöntemini geçersiz kılarak dize değerini özelleştirebilirsiniz. Örneğin,

public enum MyType {
  ONE {
      public String toString() {
          return "this is one";
      }
  },

  TWO {
      public String toString() {
          return "this is two";
      }
  }
}

Aşağıdaki test kodunu çalıştırmak bunu üretecektir:

public class EnumTest {
  public static void main(String[] args) {
      System.out.println(MyType.ONE);
      System.out.println(MyType.TWO);
  }
}


this is one
this is two

16
Bu, bunu yapmanın etkili bir yolu değildir . Bu numaralandırma her değer için yeni bir özel sınıf oluşturur. Yukarıdaki örnekte, aşağıdaki göreceksiniz binEnumTest $ MyType.class EnumTest $ MyType $ 1.sınıf EnumTest $ MyType $ 2.Sınıf yukarı katacak: dizine gerçek çabuk. Enum yapıcısına değerler ileterek beklenen cevap olarak yapmak en iyisidir. Aslında geçersiz kılmaya katılmıyorum toString(); getKey()Geçersiz kılma toString()enum başka bir kullanıcı tarafından beklenmedik olabilir gibi açık bir alıcı kullanmak daha iyi olduğuna inanıyorum .
Matt Quigley

@MattQuigley ile tamamen aynı fikirde. Bunu yapmak, kullanıcıları kullanılmaması gereken şeyler için toString kullanmaya teşvik eder. Bir etikete ihtiyacınız varsa, bir etiket özelliği eklemeyi tercih edersiniz
Sebastien Lorber

Ayrıca, muhtemelen bir noktada gerekli olacak başka bir yol (bir dizeden enum nesnesine) dolaşmanın bir yolu yoktur.
Adrian Smith

toString'in geçersiz kılınması valueOf () öğesini etkilemez, değil mi?
Dmitriusan

69

name()Yöntemini kullanın :

public class Main {
    public static void main(String[] args) throws Exception {
        System.out.println(Strings.ONE.name());
    }
}

enum Strings {
    ONE, TWO, THREE
}

verim ONE.


17
Evet, ama Strings.STRING_ONE.name()"ONE" değil "STRING_ONE" veriyor. Bu sadece iyi bir cevap değil. Geçerli bir Java tanımlayıcısı vb
Mark Peters

2
@ Mark, doğru, herhangi bir karakteri işleyemez. OP sadece tek bir karakter istiyorsa, bu çözüm The Elite Gentleman önerisinden daha basittir. Ama aslında: karakter aralığı geçerli bir Java tanımlayıcısının sahip olabileceği karakterleri aşarsa, bu bir hareketsizdir. İyi bir nokta.
Bart Kiers

Toumtring () ile göstermek istediklerinden farklı bir numaralandırma için dahili bir adlandırma kuralına sahip olmak çok mantıklıdır (özellikle bir kullanıcı çıktıyı görürse), bu yüzden OP'nin oldukça fazla olduğunu düşünmüyorum aramak.
Michael McGowan

17
Sonuç, name()bir gizleme programından etkilenebilir. Bir süre önce benzer bir sorunla karşılaştım. Örneğin, Proguard ile bu sorunu çözmeniz gerekir. Bkz. Sayım Sınıflarını İşleme
noisecapella

Bu mükemmel. Var_name, var_superlong_but_not_toooooo_long_name, even etc gibi değerlerle çalışır (tripple noktaları olmadan)

18

Numaralandırma adını istediğiniz dizeyle aynı olacak şekilde ayarlayın veya daha genel olarak rasgele öznitelikleri numaralandırma değerlerinizle ilişkilendirebilirsiniz:

enum Strings {
   STRING_ONE("ONE"), STRING_TWO("TWO");
   private final String stringValue;
   Strings(final String s) { stringValue = s; }
   public String toString() { return stringValue; }
   // further methods, attributes, etc.
}

Sabitleri en üstte, yöntemleri / öznitelikleri en altta tutmak önemlidir.


Ve ayrıca özel bir kurucuya sahip olmak .
Buhake Sindi

1
enum yapıcıları varsayılan olarak özeldir ve erişim değiştirici gerektirmez. Ancak genel olarak erişim değiştiriciler hakkında iyi bir nokta, bunları özniteliğe ve erişimciye eklemek için kodumu güncelledim.
Adrian Smith

15

"Onları Dizeler olarak kullan" ile ne demek istediğinize bağlı olarak, burada bir numaralandırma kullanmak istemeyebilirsiniz. Çoğu durumda, The Elite Gentleman tarafından önerilen çözüm, bunları toString yöntemleriyle kullanmanıza izin verecektir, örneğin System.out.println(STRING_ONE)veya içinde String s = "Hello "+STRING_TWO, ancak gerçekten Dizelere (örneğin STRING_ONE.toLowerCase()) ihtiyacınız olduğunda , bunları sabit olarak tanımlamayı tercih edebilirsiniz:

public interface Strings{
  public static final String STRING_ONE = "ONE";
  public static final String STRING_TWO = "TWO";      
}

5
aslında ben kaçınmaya çalışıyorum budur ...!
Dori

Aslında, toLowerCase()benim çözümümü de istiyorlarsa, gidebilirler Strings.STRING_TWO.toString().toLowerCase().
Buhake Sindi

Tabii, ama ben bunları yorumladığım gibi dizeler olarak kullanmıyor. Rrackham bu kullanımı gerektirmediği için, elbette önerilen numaralandırma çözümünü kullanması gerekir.
hd42

6
Yapıcı ile interfacebir finalsınıf yerine kullanmamalısınız private. Cesareti kırılmış bir uygulamadır.
Aleks N.

1
mils, enums kullanarak çözümler bir anahtar da iyi çalışır. Bu çözümü yalnızca Dizeler doğrudan gerekliyse öneririm.
hd42

8

Enum dizesi için bunu kullanabilirsiniz

public enum EnumTest {
    NAME_ONE("Name 1"),
    NAME_TWO("Name 2");

    private final String name;

    /**
     * @param name
     */
    private EnumTest(final String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }
}

Ve ana yöntemden çağrı

public class Test {
    public static void main (String args[]){
        System.out.println(EnumTest.NAME_ONE.getName());
        System.out.println(EnumTest.NAME_TWO.getName());
    }
}

5

Eğer varsa yok kullanmak istediğiniz Kurucular ve bir olmasını istediğiniz özel isim yöntemi için, onu bu deneyin:

public enum MyType {
  ONE {
      public String getDescription() {
          return "this is one";
      }
  },    
  TWO {
      public String getDescription() {
          return "this is two";
      }
  };

  public abstract String getDescription();
}

Bunun en hızlı çözüm olduğundan şüpheleniyorum . Final değişkenlerini kullanmaya gerek yoktur .


ancak bununla birlikte, soran kişinin ONE'u aramak veya sabit olarak erişmek istediği getDescription () öğesini çağırmanız gerekir.
kinsley kajiva

Bunu tercih ederim. Daha fazla bilgi kabul etmesi gerekirse ne olacak? Bu çözümle korumalı soyut yöntemler ekleyin ve üstesinden gelin. Daha fazla toString () yöntemini geçersiz kılmaya gerek yok. Temiz ve en iyi cevap olarak kabul edilebilir.
Arundev

0

Varsayılan değerlerle alın ve ayarlayın.

public enum Status {

    STATUS_A("Status A"),  STATUS_B("Status B"),

    private String status;

    Status(String status) {
        this.status = status;
    }

    public String getStatus() {
        return status;
    }
}
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.