Java 7'de Dizeleri açmanın faydası nedir?


19

Java'da programlamaya başladığımda, switch ifadelerinin dizeleri almadığı gerçeği beni hayal kırıklığına uğrattı. Daha sonra Enums'ı kullandığımda, ham değerleri - tipi güvenliği (daha kolay yeniden düzenleme getiren) ve aynı zamanda diğer geliştiricilere açıklık getirmek yerine onlarla elde ettiğiniz faydaları fark ettim.

SE7 ile şimdi dizgelerle bir anahtarı Enums yerine girdi olarak kullanmaya karar vereceğim bir durum düşünmek için mücadele ediyorum. Tüm dizeleri (örn. Kısmi veya normal ifade eşleşmeleri yerine) açarak uygulanırsa, kodun değişmesi için daha az neden göstermez.

Ve IDE araçları ve kodlamanın okuma-yazma oranı ile, dize değerlerini iletmekten çok fazladan bir Enum üretmekten daha mutlu olurdum.

Programcı olarak bize ne fayda sağlıyorlar? Daha az kazan plakası?

Bu özellik için dil ağlıyormuş gibi gelmiyor. Belki de göz ardı ettiğim bir kullanım durumu var.


Dizeler zaten anahtar ifadelerinde çokça kullanılıyor, ancak insanlar bunları doğrudan kullanamadıkları için dev ağaçlar gibi başka çözümlere veya numaralandırmalara dönüşümlere başvurdular. Her iki geçici çözüm de kodu daha az okunabilir hale getirir. Her iki yol da geçici çözümlerdir ve yerel olarak uygulanan bir çözüm programcıların niyetlerini daha iyi gösteriyorsa neden bir geçici çözüm kullanmalısınız.
Pieter B

@PieterB Yine de, bir Enum, geçici bir çözüm olmaktan ziyade anlamsal bir değer katıyor ve bu da tür güvenliği getiriyor (örneğin, bir yazım hatası bir hataya neden olmak yerine derleme zamanında yakalanacak). Ayrıca , bu bağlamda kullanıldığı gibi , dizenin tüm örneklerini yeniden düzenlememize izin verir (bu, etki alanı nesneleriyle oldukça sık ortaya çıkabilir)
anotherdave

Yanıtlar:


12

Anlayabildiğim kadarıyla soru, String sabitlerini sıralamaya sarmanın neden dil kullanıcılarının ihtiyaçlarını karşılamaya yeterli olmadığıdır. Bu, JDK 7 (proje Coin) posta listesinde açıklanan resmi özellik teklifinde ele alındı.

Teklifi okuduğumda, enat kullanmanın alternatifi, şişkinlik türlerini tanıttığı gerekçesiyle reddedildi. Size kolaylık sağlamak için, teklifin ilgili bölümü alıntı çeteleler ele açıklamada, aşağıda alıntılanmıştır kalın :

ÖNEMLİ AVANTAJ: Teklifi olumlu bir değişiklik yapan nedir?

Bir dizi sabit dize değeri temelinde seçilen işlemler için daha düzenli kodlama desenleri kullanılabilir; yeni yapının anlamı Java geliştiricileri için açık olmalıdır.

ÖNEMLİ FAYDA: Teklif kabul edilirse platform neden daha iyi?

Dize tabanlı gönderim kodu için potansiyel olarak daha iyi performans.

BÜYÜK Dezavantaj: Her zaman bir maliyet vardır.

Bazıları derleyici için uygulama ve test karmaşıklığını artırdı.

ALTERNATİFLER: Dil değişikliği olmadan fayda ve avantajlar bir şekilde elde edilebilir mi?

Hayır; dize eşitliği için zincirlenmiş if-then-else testleri potansiyel olarak pahalıdır ve değiştirilebilen sabit değerleri için, ilgilenilen dize değeri başına bir tane olmak üzere bir enum eklemek, iyi bir neden olmaksızın bir programa başka bir tür ekleyecektir ...


cesur kısmı oldukça şaşırtıcı
Simon Bergot

1
@Simon şahsen dolaylı muamele olarak okur, "Java5 öncesi böyle düşüncelerle uğraşmaya devam edersek rekabeti C # ile kaybedeceğiz". :) "ön Java5 yolları" bir örnek için, bkz JDK-1223179: anahtarını dizeleri üzerinde - 1995 yılında sunulan ve hızlı bir şekilde kapalı Will not Fix :. Bu planlarımız arasında andıran "nefesini tut etmeyin Hiçbir şey ."
gnat

Teşekkürler, teklifte öne sürülen nedenleri görmek çok ilginç. Hala bir programa "iyi bir sebep olmadan" bir tür tanıttığımızı söylemek yanlış geliyor - biz OO programcılarıyız! :)
anotherdave

5
@anotherdave "nesne yönelimli" tanıtım türlerini sadece bunlar anlamlı bir amaca hizmet ettiğinde haklı çıkarır. Görünüşe göre, JCP'deki hakim görüş, anahtarlarda String sabitleri için beyinsiz sarmalayıcılar olarak numaralandırmaların kullanılmasının anlamlı olmadığı ortaya çıktı
gnat

1
Vay canına, resmi öneriyi aktif olarak tip şişkinliğe karşı koymak için (iyi bir şekilde) şaşırdım. Bu canlandırıcı. Tip bloat Java'da büyük bir sorundur.
Ben Lee

7

Kodu daha okunabilir hale getirmenin yanı sıra, if/else ifkarşılaştırmalara kıyasla potansiyel performans kazanımları vardır . Değişikliğin faydalı olup olmayacağı, ne kadar karşılaştırma yapacağınıza bağlıdır. Bir dize anahtarı iki ayrı anahtar talimatı olarak yayınlanacaktır. Birincisi karma kodlar üzerinde çalışır, bu yüzden lookupswitchsonuçta O(log n)karmaşıklık sağlar. İkincisi her zaman mükemmeldir O(1) tableswitch, bu nedenle birleşik karmaşıklık haladır O(log n). Tek bir doğrusal ifade zinciri if/else ifbiraz daha kötü O(n)karmaşıklık verecektir .

Örneğin, üç dizeden daha fazlasını karşılaştırıyorsanız, a switchmuhtemelen daha okunabilir ve kompakttır. Bir sıcak kod yolunda çok sayıda karşılaştırma yapmadığınız sürece bir fark fark etmeniz olası olmasa da, muhtemelen daha iyi performans gösterecektir.


1
Ben neden bir enum yerine bir dize bir anahtar kullanmak istiyorum soruyordum. Büyük bir if/elseblok kötü uygulamayı düşünürdüm , ama şu anda, bir tane kullanmak için fazla nedenim yoktu.
anotherdave

Eğer komuta ekstra türü var çünkü Ama sonra komut desen ile birlikte bir Harita hatta aynı karmaşıklık daha okunabilirliği doğuracak
SpaceTrucker

3

Dizelerin anahtarı, enumdeğerleriniz dışarıdan geldiğinde, yani bir veritabanında saklandığında kullanılabilir.

JDK 7'de dikkat çeken bir başka şey, yapılardan switchçok daha fazla parfümlü olmasıdır if-else.

Hızlı dize switchesleri için güzel bir kullanım örneği , düğüm ve öznitelik türlerinde çok fazla anahtar yapmanız gerektiğinde JSON / XML akış ayrıştırma olabilir. Bunun için daha iyi bir seçenek düşünemiyorum.


1
"Enum değerleriniz dışarıdan geldiğinde, yani bir veritabanında saklandığında dizeler için geçiş yeri değiştirilemez.": Bunu ayrıntılı olarak açıklayabilir misiniz? Switch deyimindeki dizeler sabit olarak kodlanır: veritabanındaki dizeler değişir değişmez kodunuz güncelliğini yitirir.
Giorgio

Haklısınız - enumJava'nın statik yapısı nedeniyle bu durumda kullanılabilir. Bunu yazarken Role, genellikle bir sınıf olarak sağlanan ve içine konamayan bir güvenlik kütüphanesinden bir düşünürdüm enum. Başka bir durum, dinamik olarak derlenmiş bir Java / Groovy kodudur - ancak nadir olan bu durumda dize anahtarları daha iyi bir seçenek olabilir.
Andrey Chaschev

2

Basitlik

Switch desteğindeki dize, enum veya if-elsemantığa dönüştürülmeden verileri işlemek için kullanışlıdır . Bazen String'i açmak daha kolaydır.

Gönderen JDK 7 (proje Coin) posta listesine de özellik önerisi ( @gnat cevap )

değiştirilebilir dize değeri için, her bir dize değeri başına bir enum getirilmesi, bir programa iyi bir neden olmaksızın başka bir tür ekler ...

Else sürümü

Bu kısa, ancak birçoğunu if'sokumak zor. Ve bu yavaş.

if (color.equals("red")) {
    System.out.println("Color is Red");
} else if (color.equals("green")) {
    System.out.println("Color is Green");
} else {
    System.out.println("Color not found");
}

Numaralandırma sürümü

Numaraların tanımlanması gerekir, bu iyidir, ancak bazen gerekli değildir.

enum Color {RED, GREEN}

Her zamanki gibi işleniyor

try {
    switch (Color.valueOf(color)) {
        case RED:
            System.out.println("Color is Red");
            break;
        case GREEN:
            System.out.println("Color is Green");
            break;
    }
} catch (IllegalArgumentException e) {
    System.out.println("Color not found");
}

JDK 7 - Anahtar Deyimleri sürümündeki dizeler

Ek türleri dönüştürmeden ve tanımlamadan işleyebiliriz.

switch (color) {
    case "red":
        System.out.println("Color is Red");
        break;
    case "green":
        System.out.println("Color is Green");
        break;
    default:
        System.out.println("Color not found");
}

7
Bu soruyu ele almıyor: neden burada numaralandırmalar yerine dizeler kullanasınız?
Dave Newton

0

Herhangi bir dilde yapılan en iyileştirmeler, kodun daha kolay okunmasını sağlamaktır. Ben her gün fantezi üzerinde okunabilir kod tercih.

Buna inanamayabilirsiniz ama deneyin:

public enum JettStaff {
  ADRIAN("Adrian German") {
    public String toString() {
      return name + " (dgerman@indiana.edu)";
    }
  },
  ARJIT("Arjit Sengupta") {
    public String toString() {
      return name + " (asengupt@indiana.edu)";
    }
  },

  // and on for the rest...

  private String name;

  public JettStaff(String n) { this.name = n; }
}

JettStaff x = JettStaff.SUZANNE;
System.out.println(x);

Yukarıdaki kod yorumlarınıza ve kod örneğinize açık değilim. Okuması zor bir şeyin örneği olarak Enum mu demek istediniz?
anotherdave


2
Bu çok tartışmalı; numaralandırmanın bir e-posta alanına sahip olmadığını veya bunun bir sınıf olmayacağını düşünüyorsunuz.
Dave Newton

4
@ user2860598 Bir noktaya değinmeye çalışıyorsanız, alakalı bir örnek kullanın. Aynı zamanda bir tel sabitinin yağla parmaklanmasını da ele almaz.
Dave Newton

1
@ user2860598 Bağladığınız yanıt, tanıtıldığını ve daha önce bir Enum ile "yaklaştırılabileceğini" söylüyor. Demek istediğim, Enum kullanımının tanıtımları ile bile yine de tercih edilebilir olduğuydı.
anotherdave

0

Numaralandırmalar harika ve bunu yapabilme yeteneğiniz olduğunda Dizeler yerine bunları kullanmalısınız. Ancak bazen yapamadığınız zamanlar vardır, örneğin Java'nın dışından gelen bazı harici nesnelerle çalışmanız gerektiğinde. Bir şeyi ayrıştırmanız gerektiğini düşünün. Sunucu yanıtı, yapılandırma, günlük dosyası veya benzeri bir şey gibi: aradığınız bir sürü seçeneğiniz var ve bunların numaralandırılması mümkün değil. Java <7'de bir sürü

  if (something.equals("foo")) {
    // foo processing
  } else 
  if (something.equals("bar")) {
   // bar processing
  }

Bu durumda enum'ları yalnızca isimlere göre almaya ve / veya özel String-> Enum rutini sağlayarak kullanmaya devam edebilirsiniz, ancak bazen mümkün değildir veya pratik değildir (yani çok fazla numara oluşturmanız gerektiğinde)

TLDR : Tamamen Java kodu ile çalışırken Enums'u kesinlikle kullanmalısınız, ancak harici nesnelerle her zaman mümkün değildir. Umarım açıklamam mantıklıdır.


Dış verilerle uğraşıyorsanız ve ififadelerinizde neye ihtiyacınız olduğunu yeterince iyi biliyorsanız , yine de onu tamamlamanız gerekir , bu da hala numaralandırmalar veya bir komut deseni vb. Kullanabileceğiniz anlamına gelir.
Dave Newton

@DaveNewton evet, yine de enums kullanabilirsiniz, ancak cevabımda belirttiğim gibi, bazen ayrıştırma sırasında kodunuzda sadece bir kez kullanılacak bir enumlar oluşturmuş olmanız durumunda pratik olmayabilir.

@dimoniy Fakat 100'lerce Enum değeri oluşturmak zorunda olsaydınız, bu bir anahtar alternatifiyle 100'lerin vaka ifadelerine sahip olmanız gerektiği anlamına gelmez mi? Bu kadar çok değişken varsa, kesinlikle enumların tip güvenliğini tercih ederim.
anotherdave

0

StringsAnahtar deyimlerinde kullandığınızda daha temiz ve okunabilir bir kod olduğu ve kötü bir programlama uygulaması olduğunu düşündüğüm fikrine katılmıyorum . Depolamak için kullandığınız değeri değiştirirseniz, her anahtarı veya if-ifif olayını değiştirmeniz gerekir. Kodunuzun her birine sabit kodlanmış değerler koyduğunuz için bu iyi değildir. Bir gün bu sabit kodlanmış değerlerden birini değiştirmeye karar verirseniz ne yapacaksınız? Her kopyasını ara ve değiştir?

İf-elseif deyimleriyle yaptığınız bazı sabit kodlanmış değerleriniz varsa, bunlar için sabit ilkel değerleri kullanmak Java 1.5'ten önce çok daha iyidir çünkü yalnızca tür güvenliği getirir.

Tamam, Dize değerlerini (HTTP İsteğinden, dosyalardan vb.) Alacağınız durumlar olacak ve bunları ilkel değerlere dönüştürmek acı verici bir durumdur. Ama Enumbu noktada iyi bir iş çıkarıyorum. Çünkü Enum'da sakladığınız değeri değiştirmek istediğinizde, beyan ettiğinizde değiştirin. Kodunuzda başka hiçbir şeyi değiştirmenize gerek yoktur. (Elbette başka bir yerde saklanan değerleri değiştirmeniz gerekir).

Çünkü sadece kirli ve tembel bir kod uyguluyorsanız, bu mükemmel. Çok fazla kodu kodlamak istemezsiniz Enum, ancak sizi öldürecek büyük ölçekli karmaşık bir yazılımda.


-1

Hangi bilgilerin geldiğini ve yalnızca 5 eyaletten olabileceğini biliyorsanız, bir Enum. Ancak, olası durumlar 9000'in üzerinde olabilir ve sadece 42'yi bulmanız gerekiyorsa, bir anahtarı kullanmak daha iyidir çünkü tüm bu durumları yazmak istemezsiniz.

Bir Enum, olası durumların bilinmediği veya çok fazla olmadığı ve sadece birkaçını önemsediğiniz sürece çoğu durumda çoğu kişi tarafından seçim olma eğilimindedir.

Ama neden şimdi tanıttılar? Temiz kod için izin verilen bir değişiklikti.

1.5'te ayrıca Numaralandırmalar için de özel gövdeler oluşturmanıza izin verdiler.


Ama sadece bir Enum durumuna diğer 8958 olası değerleri atamaz mıydınız?
anotherdave

burasıdır @anotherdave defaultiçinde switchplay gelir. Varsayılan bir durum Enumyapmadığınız sürece ile varsayılan bir duruma sahip olduğunu bilmiyorum ama sonra bu kod sadece şişirilmiş iken bir switchkullanmak çok daha temiz.

3
UNKNOWNBir Enum'daki bir durumun şişkin olduğunu söylemek garip görünüyor , ancak defaultbir anahtardaki bir durum değil.
anotherdave
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.