Java numaralandırma - neden ad yerine toString kullanıyorsunuz


171

Enum api'ye yönteme bakarsanız name()şöyle diyor:

Bu numaralandırma sabitinin adını, tam olarak numaralandırma bildiriminde bildirildiği gibi döndürür. ToString yöntemi daha kullanıcı dostu bir ad döndürebileceğinden, çoğu programcı bu tercih yerine toString yöntemini kullanmalıdır. Bu yöntem, öncelikle doğruluğun, sürümden sürüme değişiklik göstermeyecek şekilde tam adı almaya bağlı olduğu özel durumlarda kullanılmak üzere tasarlanmıştır.

Neden kullanmak daha iyidir toString()? Yani name () zaten son olduğunda toString geçersiz kılınabilir. Bu nedenle, toString kullanırsanız ve birisi sabit kodlu bir değer döndürmek için onu geçersiz kılarsa tüm uygulamanız kapalıdır ... Ayrıca kaynaklara bakarsanız toString () yöntemi tam olarak ve yalnızca adı döndürür. Aynı şey.


4
toString()Numaralandırmanızda geçersiz kılabilirsiniz , ancak hiç kimse onu genişletemez ve geçersiz kılamaz. Numaralandırmaları genişletemezsiniz.
Erick G. Hagstrom

Yanıtlar:


200

Gerçekten, döndürülen değerle ne yapmak istediğinize bağlıdır:

  • Enum sabiti bildirmek için kullanılan tam adını almak gerekiyorsa, kullanmak gerekir name()olarak toStringoverriden olmuş olabilir
  • Numaralandırma sabitini kullanıcı dostu bir şekilde yazdırmak istiyorsanız, toStringgeçersiz kılınmış (ya da değil!)

Kafa karıştırıcı olabileceğini düşündüğümde, daha spesifik bir getXXXyöntem sağlarım, örneğin:

public enum Fields {
    LAST_NAME("Last Name"), FIRST_NAME("First Name");

    private final String fieldDescription;

    private Fields(String value) {
        fieldDescription = value;
    }

    public String getFieldDescription() {
        return fieldDescription;
    }
}

1
Bu kabul edilebilir. Enum bir temel sınıf olmasına izin verirlerse, işler daha kolay olurdu.
ralphgabb

55

Kullanın name()Eğer bir karşılaştırma yapmak veya kodunda bazı dahili kullanım için kodlanmış değeri kullanmak istediğinizde.

toString()Bir kullanıcıya bilgi sunmak istediğinizde kullanın (günlüğe bakan bir geliştirici dahil). Kodunuza asla toString()belirli bir değer verme konusunda güvenmeyin . Asla belirli bir dizeye karşı test etmeyin. Birisi toString()dönüşü doğru değiştirdiğinde kodunuz bozulursa , zaten kırılmış demektir.

Javadoc'tan (vurgu mayın):

Nesnenin dize olarak temsilini döndürür. Genel olarak, toString yöntemi bu nesneyi "metinsel olarak" temsil eden bir dize döndürür . Sonuç, bir kişinin okuması kolay, kısa ve bilgilendirici bir sunum olmalıdır . Tüm alt sınıfların bu yöntemi geçersiz kılması önerilir.


23

name()"yerleşik" bir yöntemdir enum. Nihaidir ve uygulamasını değiştiremezsiniz. Enum sabitinin adını yazıldığı gibi döndürür, örneğin büyük harf, boşluk bırakmadan vb.

Karşılaştır MOBILE_PHONE_NUMBERve Mobile phone number. Hangi sürüm daha okunabilir? İkincisine inanıyorum. Bu farktır: name()her zaman geri döner MOBILE_PHONE_NUMBER, toString()geri dönmek geçersiz olabilir Mobile phone number.


16
Bu doğru değil!! toString () Mobile phone numberyalnızca bu tür bir değeri döndürmek için geçersiz kıldığınızda döner . Aksi takdirde geri dönecekMOBILE_PHONE_NUMBER
spauny

2
@spayny, geçersiz kılmanız gerektiği açık toString(). Yakalama name(), son olduğu için geçersiz kılınamaz.
AlexR

13
Eğer dahil etmek gerekebilir @AlexR cevap sizin yukarıdaki yorum% 100 doğru yapmak
artfullyContrived

5
Yorumlarınızı okuyana kadar benim için açık olmadığı için @artfullyContrived ile katılıyorum.
martinatime

13

Çoğu insan javadoc'un tavsiyelerini körü körüne takip ederken, toString () 'den gerçekten kaçınmak istediğiniz çok özel durumlar vardır. Örneğin, Java kodumda enums kullanıyorum, ancak bir veritabanına serileştirilmeleri ve tekrar geri dönmeleri gerekiyor. Eğer toString () kullandıysam, teknik olarak diğerlerinin işaret ettiği gibi geçersiz kılınan davranışı almaya maruz kalırdım.

Buna ek olarak, veritabanından serileştirme de yapılabilir, örneğin, bu her zaman Java'da çalışmalıdır:

MyEnum taco = MyEnum.valueOf(MyEnum.TACO.name());

Ancak bu garanti edilmez:

MyEnum taco = MyEnum.valueOf(MyEnum.TACO.toString());

Bu arada, Javadoc'un açıkça "çoğu programcı olmalı" demesini çok garip buluyorum. Bir enumun toString'inde çok az kullanım durumu buluyorum, eğer insanlar bunu "kolay bir ad" için kullanıyorlarsa, çoğu durumda i18n ile daha uyumlu bir şey kullanmaları gerektiği için açıkça kötü bir kullanım durumu name () yöntemini kullanın.


2
Cevapladığınız için teşekkürler. Bu soruyu sorduğumdan beri neredeyse 5 yıl oldu ve henüz bir numaralandırma için toString () yöntemini kullanmadım! Enum'u tam olarak tanımladığınız şey için kullandığım zamanların% 99'u: numaralandırmaların veritabanına / veritabanından serileştirilmesi ve serileştirilmesi.
spauny

5

Name () ve toString () 'in farklı olması mantıklı olduğunda pratik bir örnek, tek değerli tanımlamanın bir singletonu tanımlamak için kullanıldığı bir kalıptır. İlk başta şaşırtıcı görünüyor ama çok mantıklı:

enum SingletonComponent {
    INSTANCE(/*..configuration...*/);

    /* ...behavior... */

    @Override
    String toString() {
      return "SingletonComponent"; // better than default "INSTANCE"
    }
}

Böyle bir durumda:

SingletonComponent myComponent = SingletonComponent.INSTANCE;
assertThat(myComponent.name()).isEqualTo("INSTANCE"); // blah
assertThat(myComponent.toString()).isEqualTo("SingletonComponent"); // better

Evet, haklısın ... iyi bir örnek
Guava'nın

4

name () kelimenin tam anlamıyla enum'un java kodundaki metin adıdır. Bu, aslında java kodunuzda görünebilen dizelerle sınırlı olduğu, ancak istenen dizelerin hepsinin kodda ifade edilemeyeceği anlamına gelir. Örneğin, bir sayı ile başlayan bir dizeye ihtiyacınız olabilir. name () bu dizeyi sizin için hiçbir zaman elde edemez.


-1

Aşağıdaki kod gibi bir şey de kullanabilirsiniz. Lombok'u, alıcılar ve yapıcı için bazı kazan kodlarını yazmaktan kaçınmak için kullandım.

@AllArgsConstructor
@Getter
public enum RetroDeviceStatus {
    DELIVERED(0,"Delivered"),
    ACCEPTED(1, "Accepted"),
    REJECTED(2, "Rejected"),
    REPAIRED(3, "Repaired");

    private final Integer value;
    private final String stringValue;

    @Override
    public String toString() {
        return this.stringValue;
    }
}
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.