Apa itu Double Brace Initialization ?

Double brace initialization adalah sebuah cara untuk membuat object sekaligus menginisialisasi nilainya di bahasa Java.

Biasanya digunakan untuk membuat dan menginisialisasi objek Collection seperti List, Map, Set, Queue, dll. Sebelum Java 9, belum ada fungsi bawaan dari Java melakukan create dan inisiasi Collection secara langsung. Persoalan ini diangkat di JDK Enhancement Proposal (JEP) 186.

Istilah Double brace initialization sendiri tidak dikenal dalam spesifikasi bahasa Java nya sendiri. Akan tetapi karena bentuk dan format penulisannya yang terdiri dari dua kurung kurawal buka dan dua kurung kurawal tutup, maka terkenal lah cara ini dengan nama Double Brace Initialization

Contohnya seperti apa ?

Misalnya : membuat dan menginisiasi sebuah List of Integer, terdiri dari angka 1 dan 2.

  • cara 1 (Double Brace Initialization)
 List<Integer> integerList = new ArrayList<>() {{
     add(1);
     add(2);
 }};
 System.out.println(integerList);

Cara lain yang biasanya kita lakukan adalah :

  • cara 2
Lis<Integer> integerList = new ArrayList<>();
integerList.add(1);
integerList.add(2);
System.out.println(integerList);

Keduanya pertama kali akan membuat objek List of Integer, kemudian menginisiasi nilainya dengan angka 1 dan 2.

Cuma cara 1 sepertinya lebih sederhana, dengan hanya menggunakan satu baris perintah tanpa terputus. Membuat dan menginisiasi objek dilakukan dalam satu kelompok perintah yang sama.

Cara 2 adalah cara umum dimana perintah membuat objek berada di baris yang berbeda dengan perintah inisiasi nilainya.

Kedua sintaks diatas akan menghasilkan output yang sama, yaitu :

[1, 2]

Akan tetapi membuat dan menginisiasi objek dengan cara Double Brace Initialization ini tidak disarankan, karena banyak kekurangannya untuk sesuatu yang tidak perlu-perlu amat.

Coba kita lihat apa yang dilakukan oleh Double Brace Initialization ini ?

 List<Integer> integerList = new ArrayList<>() {{
     add(1);
     add(2);
 }};
 System.out.println(integerList);

new ArrayList<>() { {} }

Kurung kurawal pertama artinya akan membuat Anonymous Inner Class di dalam file ini. Artinya kita membuat sebuah subclass dari ArrayList dalam bentuk anonymous.


new ArrayList<>() { {} }

Kurung kurawal kedua merupakan blok inisiasi, yang isi didalamnya akan dieksekusi sebelum constructor class diluarnya dieksekusi. Jadi perintah yang ada di dalam blok inisiasi akan selalu dieksekusi setiap membuat sebuah instance objek Anynomous Inner Class berupa ArrayList diatas.

Didalam blok inisiasi tersebut kita bisa memanggil fungsi/method dari class tersebut, termasuk fungsi/method dari parent class nya dan juga fungsi di class luar nya / outer class.

Dalam kasus diatas, kita memanggil fungsi add dari ArrayList.

Lalu dimana masalahnya ?

Double Brace Initialization mempunyai masalah di beberapa hal, yaitu :


  1. Mengambil jatah di heap memory dan ukuran file

Anonymous inner class yang dibuat oleh Double Brace Initialization ini merupakan class baru, yang menempel ke class dimana codenya itu berada, misalnya class File1$1.class, dimana File1 adalah nama file dimana anonymous Double Brace Initialization ini berada, sementara 1.class adalah penomoran/penamaan anonymous inner class nya tersebut.

Seperti halnya class lain, maka anonymous inner class ini juga diload dan diverifikasi oleh ClassLoader di waktu aplikasi Java dijalankan. Hal ini juga menambah waktu startup dan ukuran file waktu diload oleh ClassLoader.


  1. Bisa jadi susah untuk dilakukan Gargage Collecting, sehingga bisa menyebabkan memory leak.

Anonymous inner class yang dibuat oleh Double Brace Initialization ini sebenarnya memiliki hidden reference ke class diluarnya , misalnya class File1 diatas. Dan seringkali di dalam anonymous inner class tersebut memanfaatkan fungsi dari class diluarnya tanpa membutuhkan instansiasi method static. Akibatnya class diluarnya tersebut akan selalu direference selama Anynomous Inner Class tersebut hidup.

Contoh :

public class File1 {

    public int hello(String word) {
        return ...; // Implementation
    }

    public Map<String, Integer> helloAnynomous() {
        return new HashMap<String, Integer>() {{
            put("first", hello("a"));
            put("two", hello("an"));
            put("three", hello("the"));
        }};
    }
}

fungsi hello bisa direferensi dari Anynomous Inner Class yang didefinisikan oleh method helloAnynomous().

Selama Anynomous Inner Class itu hidup, maka class File1 tidak bisa di garbage collecting, karena masih diacu oleh Anonymous Inner Class, walaupun ditempat lain tidak diacu lagi.

Dan hal ini membuat potensi memory leak atau kekurangan memory karena tidak bisa di garbage collecting

Solusinya bagaimana ?

Persoalan ini sudah banyak direquest dan diimplementasikan di Java 9. Diimplementasikan dengan JDK Enhancement Proposal (JEP) 269


  • Menggunakan Map.of , List.of, Set.of

Contoh :

List<String> list1 = List.of("first", "two", "three", "four");
Set<String> set1 = Set.of("first", "two", "three", "four");
Map<String, String> map1 = Map.of("first", "1", "two", "2", "three", "3");

System.out.println(list1);
System.out.println(set1);
System.out.println(map1);

hasilnya :

[first, two, three, four]
[three, four, first, two]
{three=3, four=4, first=1, two=2}

  • Menggunakan Map.ofEntries

Contoh :

Map<String, String> map2 = Map.ofEntries(
    new AbstractMap.SimpleEntry<>("one", "1"),
    new AbstractMap.SimpleEntry<>("two", "2"),
    new AbstractMap.SimpleEntry<>("three", "3"),
    new AbstractMap.SimpleEntry<>("four", "4"));

System.out.println(map2);

hasilnya :

{three=3, four=4, first=1, two=2}