Apa manfaat dari mengaktifkan Strings di Java 7?

19

Ketika saya mulai memprogram di Jawa, fakta bahwa pernyataan pergantian tidak mengambil string membuat saya frustrasi. Kemudian saat menggunakan Enums, saya menyadari manfaat yang Anda dapatkan dari mereka daripada membagikan nilai mentah - jenis keamanan (yang membawa refactoring lebih mudah) & juga kejelasan kepada pengembang lainnya.

Saya berjuang untuk memikirkan situasi di mana dengan SE7 sekarang saya akan memutuskan untuk menggunakan saklar dengan string sebagai input daripada Enums. Jika mereka diterapkan melalui pengaktifan seluruh string (mis. Daripada kecocokan sebagian atau regex), sepertinya tidak menawarkan alasan yang lebih sedikit untuk kode berubah.

Dan dengan alat IDE dan rasio baca-tulis dari pengkodean, saya akan jauh lebih bahagia secara otomatis menghasilkan Enum tambahan daripada membagikan nilai string.

Apa manfaatnya bagi kita sebagai programmer? Lebih sedikit boiler-plate?

Rasanya tidak seperti bahasa itu menangis untuk fitur ini. Meskipun mungkin ada case-use yang saya abaikan.

yang lain
sumber
String sudah banyak digunakan dalam pergantian pernyataan, tetapi karena orang tidak bisa menggunakannya secara langsung, mereka beralih ke workaround seperti raksasa jika pohon atau konversi ke enum. Kedua solusi membuat kode kurang dibaca. Kedua cara tersebut merupakan solusi dan mengapa menggunakan solusi jika solusi yang diterapkan secara alami menunjukkan niat programmer lebih baik.
Pieter B
@PieterB Namun bisa dibilang, sebuah Enum menambahkan nilai semantik daripada menjadi solusi meskipun, yang membawa keamanan jenis (misalnya kesalahan ketik akan ditangkap pada waktu kompilasi daripada mengarah ke bug). Hal ini juga memungkinkan kita untuk memperbaiki semua contoh string, seperti yang digunakan dalam konteks itu , tanpa memengaruhi penggunaan string lain (yang mungkin sering terjadi pada objek domain).
anotherdave

Jawaban:

12

Sejauh yang saya tahu, pertanyaannya adalah mengapa membungkus konstanta String ke enum belum dianggap cukup untuk memenuhi kebutuhan pengguna bahasa. Ini telah dibahas dalam proposal fitur resmi yang diumumkan di milis JDK 7 (proyek Coin).

Per saya membaca proposal, alternatif menggunakan enums telah diberhentikan dengan alasan bahwa itu memperkenalkan tipe mengasapi. Demi kenyamanan Anda, bagian yang relevan dari proposal dikutip di bawah ini, dengan pernyataan yang membahas enum dikutip dengan huruf tebal :

KEUNGGULAN UTAMA: Apa yang membuat proposal perubahan yang menguntungkan?

Pola pengkodean yang lebih teratur dapat digunakan untuk operasi yang dipilih berdasarkan serangkaian nilai string konstan; arti dari konstruk baru harus jelas bagi pengembang Java.

MANFAAT UTAMA: Mengapa platform lebih baik jika proposal diadopsi?

Kinerja yang berpotensi lebih baik untuk kode pengiriman berbasis string.

Kelemahan utama: Selalu ada biaya.

Beberapa peningkatan implementasi dan kompleksitas pengujian untuk kompiler.

ALTERNATIF: Dapatkah manfaat dan keuntungan didapat tanpa perubahan bahasa?

Tidak; dirantai jika-maka-selain tes untuk kesetaraan string berpotensi mahal dan memperkenalkan enum untuk konstanta switchable, satu per nilai string yang menarik, akan menambah jenis lain ke program tanpa alasan yang baik ...

agas
sumber
bagian yang berani cukup mengejutkan
Simon Bergot
1
@Simon baik bagi saya pribadi itu berbunyi sebagai memperlakukan tidak langsung, "kami akan kehilangan persaingan ke C # jika kami terus berpegang pada cara-cara pra-Java5 berurusan dengan pertimbangan seperti itu". :) Untuk contoh "cara-cara pra-Java5", lihat JDK-1223179: aktifkan string - diserahkan pada 1995 dan segera ditutup sebagai Won't Fix : "Jangan menahan napas. Tidak ada yang menyerupai ini dalam rencana kami . "
Agak
Terima kasih, sangat menarik untuk melihat alasan yang dikemukakan dalam proposal. Masih terasa salah untuk mengatakan bahwa kami memperkenalkan jenis ke program "tanpa alasan yang baik" - kami adalah programmer OO! :)
anotherdave
5
@anotherdave "berorientasi objek" membenarkan memperkenalkan tipe hanya ketika ini melayani tujuan yang bermakna. Rupanya, pendapat yang berlaku di JCP ternyata menggunakan enum sebagai pembungkus yang tidak berotak untuk konstanta String pada gilirannya tidak memenuhi syarat sebagai bermakna
nyamuk
1
Wow, saya terkejut (dalam cara yang baik) untuk melihat proposal resmi aktif melawan tipe mengasapi. Itu menyegarkan. Tipe mengasapi adalah masalah besar di Jawa.
Ben Lee
7

Selain membuat kode lebih mudah dibaca, ada potensi keuntungan kinerja relatif if/else ifdibandingkan dengan perbandingan. Apakah perubahan itu bermanfaat tergantung pada berapa banyak perbandingan yang akan Anda buat. Sakelar string akan dikeluarkan sebagai dua instruksi sakelar terpisah. Yang pertama beroperasi pada kode hash, sehingga cenderung menjadi lookupswitch, pada akhirnya menghasilkan O(log n)kompleksitas. Yang kedua selalu yang sempurna O(1) tableswitch, jadi kompleksitas gabungannya tetap O(log n). Rantai if/else ifpernyataan tunggal yang linear akan memberikan O(n)kompleksitas yang sedikit lebih buruk .

Jika Anda membandingkan lebih dari, katakanlah, tiga string, maka a switchmungkin lebih mudah dibaca dan kompak. Ini mungkin akan berkinerja lebih baik, meskipun Anda tidak mungkin melihat perbedaan kecuali Anda melakukan banyak perbandingan di jalur kode panas.

Mike Strobel
sumber
1
Namun saya lebih banyak bertanya mengapa saya menggunakan sakelar pada tali daripada sakelar pada enum. Saya akan mempertimbangkan if/elsepraktik buruk yang besar , tetapi saat ini, saya tidak akan punya banyak alasan untuk menggunakannya.
anotherdave
Tetapi kemudian Peta yang dikombinasikan dengan pola perintah bahkan akan menghasilkan lebih banyak keterbacaan dengan kompleksitas yang sama karena Anda memiliki jenis perintah tambahan
SpaceTrucker
3

Switch for string dapat digunakan ketika enumnilai Anda berasal dari luar, yaitu disimpan dalam database.

Hal penting lainnya dalam JDK 7 switchadalah bahwa itu jauh lebih perfomant daripada if-elsekonstruksi.

Dan kasus penggunaan yang bagus untuk string string cepat switchbisa JSON / XML stream parsing ketika Anda perlu membuat banyak switch pada node dan tipe atribut. Saya tidak bisa memikirkan opsi yang lebih baik untuk ini.

Andrey Chaschev
sumber
1
"Switch for string tidak tergantikan ketika nilai enum Anda berasal dari luar, yaitu disimpan dalam database.": Dapatkah Anda menguraikan ini? String dalam pernyataan switch adalah kode-keras: segera setelah string dalam database diubah, kode Anda kedaluwarsa.
Giorgio
Nah, Anda benar - enums dapat digunakan dalam kasus ini karena sifat statis Java. Ketika saya menulis ini, saya berpikir tentang Roledari perpustakaan keamanan yang biasanya disediakan sebagai kelas dan tidak dapat dimasukkan ke dalam enum. Kasus lain adalah kode Java / Groovy yang dikompilasi secara dinamis - dalam situasi ini, yang jarang terjadi, string switches mungkin merupakan opsi yang lebih baik.
Andrey Chaschev
2

Kesederhanaan

Dukungan String in Switch berguna untuk memproses data tanpa konversi ke enum atau if-elselogika. Terkadang lebih mudah untuk mengaktifkan String.

Dari proposal fitur di mailing list JDK 7 (proyek Coin) ( jawaban @gnat )

memperkenalkan enum untuk konstanta yang dapat diubah, satu nilai per string yang menarik, akan menambah tipe lain ke program tanpa alasan yang baik ...

Versi If-Else

Ini singkat, tetapi banyak if'syang sulit dibaca. Dan ini lambat.

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

Versi Enum

Enum perlu didefinisikan, ini bagus, tetapi kadang tidak diperlukan.

enum Color {RED, GREEN}

Memproses seperti biasa

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 - String dalam versi Pernyataan beralih

Kami dapat memproses tanpa mengonversi dan menentukan jenis tambahan.

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");
}
MᴀʀɪᴜsᴢS
sumber
7
Namun, ini tidak menjawab pertanyaan: mengapa Anda menggunakan string alih-alih enum di sini?
Dave Newton
0

Sebagian besar perbaikan dalam bahasa apa pun adalah untuk membuat kode lebih mudah dibaca. Saya menyukai kode yang dapat dibaca daripada mewah setiap hari.

Anda mungkin tidak percaya ini, tetapi cobalah:

public enum JettStaff {
  ADRIAN("Adrian German") {
    public String toString() {
      return name + " ([email protected])";
    }
  },
  ARJIT("Arjit Sengupta") {
    public String toString() {
      return name + " ([email protected])";
    }
  },

  // and on for the rest...

  private String name;

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

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

sumber
Saya tidak jelas tentang contoh kode Anda vs komentar Anda di atas. Apakah maksud Anda Enum sebagai contoh sesuatu yang sulit dibaca?
anotherdave
2
Ini sangat dibuat-buat; Anda berpura-pura bahwa enum tidak akan memiliki bidang email, atau bahwa ini bukan kelas.
Dave Newton
4
@ user2860598 Jika Anda mencoba menjelaskan suatu hal, gunakan contoh yang relevan. Ini juga tidak membahas konstan string dengan jari.
Dave Newton
1
@ user2860598 Jawaban yang Anda tautkan mengatakan bahwa telah ada perkenalan & bahwa sebelumnya mereka dapat "diperkirakan" dengan Enum. Maksud saya adalah bahwa penggunaan Enum tampaknya masih lebih disukai, bahkan dengan pengenalan mereka.
anotherdave
0

Enum itu bagus dan Anda harus menggunakannya daripada Strings ketika Anda memiliki kemampuan untuk melakukannya. Tetapi ada beberapa saat ketika Anda tidak bisa, misalnya ketika Anda perlu bekerja dengan beberapa objek eksternal yang berasal dari luar Jawa. Bayangkan Anda harus mengurai sesuatu. Seperti respons server, konfigurasi, file log atau yang serupa: Anda memiliki banyak opsi yang Anda cari dan tidak mungkin itu adalah enum. Jadi di Jawa <7 Anda akan terjebak dengan sekelompok

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

Anda masih dapat menggunakan enum dalam kasus ini dengan hanya mencoba mendapatkannya dengan nama dan / atau dengan memberikan rutin String-> Enum tetapi terkadang itu tidak mungkin atau tidak praktis (yaitu ketika Anda harus membuat terlalu banyak enum)

TLDR : Anda benar-benar harus menggunakan Enums ketika Anda bekerja murni dengan kode Java tetapi tidak selalu mungkin dengan objek eksternal. Saya harap penjelasan saya masuk akal.


sumber
Jika Anda sedang berurusan dengan data di luar, dan Anda sudah tahu cukup untuk mengetahui apa yang Anda butuhkan dalam Anda ifpernyataan, maka Anda harus membungkus itu pula , yang berarti Anda masih bisa menggunakan enum, atau pola perintah, dll
Dave Newton
@ DaveNewton ya, Anda masih dapat menggunakan enum tetapi seperti yang saya nyatakan dalam jawaban saya, kadang-kadang itu tidak praktis seperti dalam kasus di mana Anda akhirnya membuat lapar enum hanya untuk digunakan satu kali dalam kode Anda selama parsing.
@dimoniy Tetapi jika Anda harus membuat 100-an nilai Enum, bukankah itu berarti dengan alternatif peralihan Anda harus memiliki 100-an pernyataan kasus? Jika ada banyak variabel, saya pasti lebih suka jenis-keamanan enum.
anotherdave
0

Saya tidak setuju dengan pendapat bahwa itu kode yang lebih bersih dan mudah dibaca ketika Anda menggunakan Stringsdalam pernyataan switch dan berpikir bahwa ini adalah praktik pemrograman yang buruk. Jika Anda mengubah nilai yang Anda gunakan untuk menyimpan, Anda harus mengubahnya setiap switch atau jika-jika terjadi. Ini tidak baik karena Anda meletakkan nilai-nilai hardcoded ke setiap bir kode Anda. Apa yang akan Anda lakukan jika suatu hari Anda memutuskan untuk mengubah salah satu dari nilai-nilai ini? Cari dan ganti setiap salinannya?

Jika Anda memiliki beberapa nilai hardcoded yang Anda lakukan jika-elseif pernyataan, menggunakan nilai-nilai primitif konstan untuk mereka jauh lebih baik sebelum Java 1.5 hanya karena membawa keamanan jenis.

OK, akan ada situasi Anda akan mendapatkan nilai-nilai String (dari Permintaan HTTP, file dll.) Dan mengonversinya menjadi nilai-nilai primitif adalah suatu rasa sakit. Tapi Enums melakukan pekerjaan dengan baik pada saat ini. Karena ketika Anda ingin mengubah nilai yang Anda simpan di Enum, ubah saja ketika Anda menyatakan. Tidak perlu mengubah apa pun dalam kode Anda. (Anda tentu saja perlu mengubah nilai yang disimpan di tempat lain).

Tentu saja jika Anda hanya menerapkan kode kotor dan malas, itu sempurna. Anda tidak ingin melibatkan banyak kode Enum, tetapi dalam perangkat lunak kompleks berskala besar yang akan membunuh Anda.


sumber
-1

Jika Anda tahu informasi apa yang masuk dan itu hanya bisa dari 5 negara maka gunakan Enum. Namun jika status yang memungkinkan bisa lebih dari 9000 dan Anda hanya perlu menemukan 42, maka menggunakan sakelar lebih baik karena Anda tidak ingin mengetikkan semua status tersebut.

Sebuah Enum cenderung menjadi pilihan oleh sebagian besar di sebagian besar keadaan kecuali jika keadaan yang mungkin tidak diketahui atau ada banyak dan Anda hanya peduli sedikit.

Tapi mengapa mereka memperkenalkannya sekarang? Itu hanya perubahan yang memungkinkan kode bersih.

Dalam 1,5 mereka juga memungkinkan Anda untuk membuat badan kustom untuk Enums juga.


sumber
Tapi apakah Anda tidak hanya akan menetapkan nilai yang mungkin 8958 lainnya ke satu negara Enum?
anotherdave
@anotherdave sinilah defaultdi switchdatang untuk bermain. Saya tidak tahu bahwa Anda dapat memiliki status default dengan Enum, kecuali jika Anda membuat status default tetapi kemudian kode ini hanya membengkak sedangkan yang switchjauh lebih bersih untuk digunakan.
3
Tampaknya aneh mengatakan bahwa UNKNOWNkeadaan pada Enum adalah mengasapi, tetapi defaultkasus pada sakelar tidak.
anotherdave