Apa itu sintaks inisialisasi Double Brace ( {{ ... }}
) di Java?
java
initialization
double-brace-initialize
sgokhales
sumber
sumber
Jawaban:
Inisialisasi penguat ganda menciptakan kelas anonim yang berasal dari kelas yang ditentukan ( kurung luar ), dan menyediakan blok penginisialisasi dalam kelas tersebut ( kurung dalam ). misalnya
Perhatikan bahwa efek menggunakan inisialisasi penjepit ganda ini adalah Anda membuat kelas dalam anonim. Kelas yang dibuat memiliki
this
pointer implisit ke kelas luar sekitarnya. Meskipun biasanya tidak menjadi masalah, itu dapat menyebabkan kesedihan dalam beberapa keadaan misalnya ketika membuat cerita bersambung atau mengumpulkan sampah, dan ada baiknya menyadari hal ini.sumber
Setiap kali seseorang menggunakan inisialisasi penjepit ganda, anak kucing terbunuh.
Terlepas dari sintaks yang agak tidak biasa dan tidak benar-benar idiomatis (rasa bisa diperdebatkan, tentu saja), Anda tidak perlu menciptakan dua masalah signifikan dalam aplikasi Anda, yang baru-baru ini saya blogging tentang lebih detail di sini .
1. Anda membuat terlalu banyak kelas anonim
Setiap kali Anda menggunakan inisialisasi brace ganda, kelas baru dibuat. Misalnya contoh ini:
... akan menghasilkan kelas-kelas ini:
Itu sedikit overhead untuk classloader Anda - gratis! Tentu saja tidak akan memakan banyak waktu inisialisasi jika Anda melakukannya sekali. Tetapi jika Anda melakukan ini 20'000 kali di seluruh aplikasi perusahaan Anda ... semua itu menumpuk memori hanya untuk sedikit "sintaks gula"?
2. Anda berpotensi membuat kebocoran memori!
Jika Anda mengambil kode di atas dan mengembalikan peta itu dari suatu metode, penelepon dari metode itu mungkin secara tidak curiga berpegangan pada sumber daya yang sangat berat yang tidak dapat dikumpulkan dari sampah. Perhatikan contoh berikut:
Yang dikembalikan
Map
sekarang akan berisi referensi ke instance terlampirReallyHeavyObject
. Anda mungkin tidak ingin mengambil risiko itu:Gambar dari http://blog.jooq.org/2014/12/08/dont-be-clever-the-double-curly-braces-anti-pattern/
3. Anda dapat berpura-pura bahwa Jawa memiliki peta literal
Untuk menjawab pertanyaan Anda yang sebenarnya, orang-orang telah menggunakan sintaks ini untuk berpura-pura bahwa Java memiliki sesuatu seperti peta literal, mirip dengan liter array yang ada:
Beberapa orang mungkin merasa ini merangsang secara sintaksis.
sumber
{{...}}
dan dinyatakan sebagaistatic
bidang, seharusnya tidak ada kebocoran memori yang mungkin, hanya satu kelas anonim dan tidak ada referensi instance terlampir, bukan?Map.of()
untuk tujuan itu, jadi itu akan menjadi solusi yang lebih baikReallyHeavyObject
. Juga, kelas dalam anonim menangkap semua variabel lokal yang digunakan dalam tubuh kelas, jadi jika Anda menggunakan tidak hanya konstanta untuk menginisialisasi koleksi atau peta dengan pola ini, instance kelas dalam akan menangkap semuanya dan terus referensi mereka bahkan ketika sebenarnya dihapus dari koleksi atau peta. Jadi jika demikian, contoh-contoh ini tidak hanya membutuhkan dua kali memori yang diperlukan untuk referensi, tetapi memiliki kebocoran memori lain dalam hal itu.Sebagai contoh:
Bagaimana itu bekerja
Penjepit pertama menciptakan Kelas Batin Anonim baru. Kelas-kelas dalam ini mampu mengakses perilaku kelas induknya. Jadi, dalam kasus kami, kami sebenarnya membuat subkelas dari kelas HashSet, sehingga kelas dalam ini mampu menggunakan metode put ().
Dan set kedua kawat gigi tidak lain adalah inisialisasi instance. Jika Anda mengingatkan konsep inti Java maka Anda dapat dengan mudah mengaitkan blok initializer contoh dengan initializers statis karena kurung mirip seperti struct. Satu-satunya perbedaan adalah bahwa penginisialisasi statis ditambahkan dengan kata kunci statis, dan dijalankan hanya sekali; tidak peduli berapa banyak objek yang Anda buat.
lebih
sumber
Untuk aplikasi menyenangkan inisialisasi penjepit ganda, lihat di sini Array Dwemthy di Jawa .
Kutipan
Dan sekarang, bersiaplah untuk
BattleOfGrottoOfSausageSmells
dan ... daging tebal!sumber
Saya pikir penting untuk menekankan bahwa tidak ada yang namanya "inisialisasi Brace Ganda" di Jawa . Situs web Oracle tidak memiliki istilah ini. Dalam contoh ini ada dua fitur yang digunakan bersama: kelas anonim dan blok penginisialisasi. Sepertinya blok penginisialisasi lama telah dilupakan oleh pengembang dan menyebabkan beberapa kebingungan dalam topik ini. Kutipan dari Oracle docs :
Blok inisialisasi untuk variabel contoh terlihat seperti blok inisialisasi statis, tetapi tanpa kata kunci statis:
sumber
1- Tidak ada yang namanya kawat gigi ganda:
Saya ingin menunjukkan bahwa tidak ada yang namanya inisialisasi kawat gigi ganda . Hanya ada blok inisialisasi tradisional satu penyangga normal. Blok kawat gigi kedua tidak ada hubungannya dengan inisialisasi. Jawaban mengatakan bahwa kedua kawat gigi menginisialisasi sesuatu, tetapi tidak seperti itu.
2- Ini bukan hanya tentang kelas anonim tetapi semua kelas:
Hampir semua jawaban berbicara bahwa itu adalah hal yang digunakan saat membuat kelas batin anonim. Saya pikir orang-orang yang membaca jawaban-jawaban itu akan mendapatkan kesan bahwa ini hanya digunakan ketika membuat kelas batin anonim. Tetapi digunakan di semua kelas. Membaca jawaban-jawaban itu sepertinya adalah beberapa fitur khusus baru yang didedikasikan untuk kelas anonim dan saya pikir itu menyesatkan.
3 - Tujuannya adalah tentang menempatkan braket satu sama lain, bukan konsep baru:
Lebih jauh, pertanyaan ini berbicara tentang situasi ketika braket pembuka kedua tepat setelah braket pembuka pertama. Ketika digunakan di kelas normal biasanya ada beberapa kode antara dua kawat gigi, tetapi sama sekali hal yang sama. Jadi itu masalah menempatkan kurung. Jadi saya pikir kita tidak boleh mengatakan bahwa ini adalah hal baru yang menarik, karena ini adalah hal yang kita semua tahu, tetapi hanya ditulis dengan beberapa kode di antara kurung. Kita seharusnya tidak membuat konsep baru yang disebut "inisialisasi penjepit ganda".
4- Membuat kelas anonim bersarang tidak ada hubungannya dengan dua kawat gigi:
Saya tidak setuju dengan argumen bahwa Anda membuat terlalu banyak kelas anonim. Anda tidak membuatnya karena blok inisialisasi, tetapi hanya karena Anda membuatnya. Mereka akan dibuat bahkan jika Anda tidak menggunakan inisialisasi dua kawat gigi sehingga masalah-masalah itu akan terjadi bahkan tanpa inisialisasi ... Inisialisasi bukanlah faktor yang menciptakan objek yang diinisialisasi.
sumber
Untuk menghindari semua efek negatif dari inisialisasi penjepit ganda, seperti:
lakukan hal-hal selanjutnya:
Contoh:
Pemakaian:
Keuntungan:
Kekurangan:
Dan, sebagai hasilnya, kami memiliki pola java builder paling sederhana.
Lihat semua sampel di github: java-sf-builder-simple-example
sumber
Ini - di antara kegunaan lain - jalan pintas untuk menginisialisasi koleksi. Belajarlah lagi ...
sumber
Apakah maksudmu seperti ini?
ini merupakan inisialisasi daftar array dalam waktu pembuatan (retas)
sumber
Anda bisa meletakkan beberapa pernyataan Java sebagai loop untuk menginisialisasi koleksi:
Tapi kasus ini memengaruhi kinerja, periksa diskusi ini
sumber
Seperti yang ditunjukkan oleh @Lukas Eder inisialisasi kawat gigi ganda koleksi harus dihindari.
Itu menciptakan kelas batin anonim, dan karena semua kelas internal tetap referensi ke instance induk, ia dapat - dan 99% kemungkinan akan - mencegah pengumpulan sampah jika objek pengumpulan ini dirujuk oleh lebih banyak objek daripada hanya yang mendeklarasikan.
Java 9 telah memperkenalkan metode kenyamanan
List.of
,Set.of
danMap.of
, yang harus digunakan sebagai gantinya. Mereka lebih cepat dan lebih efisien daripada penginisialisasi double-brace.sumber
Penjepit pertama membuat Kelas Anonim baru dan set penjepit kedua menciptakan inisialisasi instance seperti blok statis.
Seperti yang telah ditunjukkan orang lain, itu tidak aman untuk digunakan.
Namun, Anda selalu dapat menggunakan alternatif ini untuk menginisialisasi koleksi.
sumber
Ini akan tampak sama dengan kata kunci dengan begitu populer di flash dan vbscript. Ini adalah metode untuk mengubah apa yang
this
ada dan tidak lebih.sumber
this
ada. Sintaks hanya membuat kelas anonim (jadi referensi apa punthis
akan merujuk ke objek dari kelas anonim baru), dan kemudian menggunakan blok{...}
penginisialisasi untuk menginisialisasi instance yang baru dibuat.