# Double Braces Notation um Collections zu initialisieren



## maki (17. Apr 2009)

Bin gerade darüber gestolpert und wollte es mal hier reinstellen: Double Brace Initialization

Damit sind "einfachere" Initialisierungen von zB. Collections möglich:

```
public class Test {
	
	public static void main(String[] args) {
		List<String> list = new ArrayList<String>()  {{
			add("first");
			add("second");			
		}};
		
		for (String string : list) {
			System.out.println(string);
		}
	}

}
```

Man sollte vorsichtig damit umgehen, denn es wird eine anonyme innere Klasse erzeugt, was einerseits die Verwendung für final Klassen unmöglich macht, andererseits Probleme bei der equals Methode verursachen kann.


----------



## Ebenius (17. Apr 2009)

Das ist ja hochgradig ekelig, dass es dafür einen Namen gibt der auch noch so irreführend ist. Hier handelt es sich um einen Initializer einer anonymen Klasse. Sowas ist durchaus gerechtfertigt; das obige Beispiel ist allerdings genau ein Fall in dem man keine Ableitung möchte.

Jetzt werd ich wieder das ganze Wochenende lang Albträume haben.

Ebenius


----------



## maki (17. Apr 2009)

> Jetzt werd ich wieder das ganze Wochenende lang Albträume haben.


LOL ich schmeiss mich weg...

Dachte mir schon dass es einen Grund gibt warum es ein unbekanntes Feature ist... wir hatten hier mal Fragen ob man Collections nicht einfacher initialisieren kann, bin mir aber nicht sicher ob es nciht beim alten "nein" bleiben sollte.


----------



## SlaterB (17. Apr 2009)

und ist nicht mal besonders einfach, eine Zeile pro Element..

lieber
        List<String> list = new ArrayList<String>();
        Collections.addAll(list, "first", "second");


----------



## Ebenius (17. Apr 2009)

maki hat gesagt.:


> Dachte mir schon dass es einen Grund gibt warum es ein unbekanntes Feature ist...


Ich benutze Initializers gelegentlich bei anonymen Ableitungen. Zum Beispiel in so einem Fall: 
	
	
	
	





```
toolBar.add(new AbstractAction("ABC") {
  {
    // Initialize tool tip
    putValue(SHORT_DESCRIPTION, "Click here and be surprised");
  }

  @Override
  public void actionPerformed(ActionEvent e) {
    System.out.println("Booooooo!");
  }
});
```

Man sollte aber nicht *wegen des Initializers* eine Ableitung erzeugen. Sowas rächt sich -- besonders mit Collections -- auch ganz flink, wenn Serialisierung ins Spiel kommt.



maki hat gesagt.:


> wir hatten hier mal Fragen ob man Collections nicht einfacher initialisieren kann, bin mir aber nicht sicher ob es nciht beim alten "nein" bleiben sollte.


Es sollte! Wo ist denn obiger Quelltext einfacher als: 
	
	
	
	





```
List<String> list = new ArrayList<String>(2);
add("first");
add("second");
```
Das obige Beispiel (mit Initializer) erzeugt mehr Aufwand zu Laufzeit (eine Ableitung mehr, tieferer Stack bei der Initialisierung), mehr Speicherbedarf (zusätzliches .class-File), mehr Zeilen (wenn man vernünftig formatiert), mehr Verwirrung.

Ebenius


----------



## Ebenius (17. Apr 2009)

SlaterB hat gesagt.:


> ```
> List<String> list = new ArrayList<String>();
> Collections.addAll(list, "first", "second");
> ```


Kannte ich noch gar nicht. Hab leider immer noch zu viel Java 1.4-Quelltext vor den Augen.

Es dankt Ebenius


----------



## 0x7F800000 (17. Apr 2009)

@Ebenius:


Ebenius hat gesagt.:


> ```
> Collections.addAll(Collection<T> c, T... t);
> ```
> Kannte ich noch gar nicht. Hab leider immer noch zu viel Java 1.4-Quelltext vor den Augen.


Das ist zwar etwas besser als nichts, erlöst aber einen nicht vom problem, dass man eine temporäre variable anlegen muss, und nicht direkt eine Liste erzeugen kann, um sie als argument in irgeneiner methode zu verwenden. Da ist Arrays.asList(T... t) schon praktischer...

@maki:
sowas hätte ich von dir nicht erwartet^^ 
Obwohl... ich interpretiere diesen Beitrag nicht als Vorschlag einer Alternative, sondern als Warnung nach dem Motto "Know Your Enemy", dann ist alles in Ordnung 

...wobei ich sagen muss: ganz unelegant ist der vorschlag in der tat nicht :reflect:


----------



## 0x7F800000 (17. Apr 2009)

wie wär's denn mit sowas?

```
import java.util.*;

public class _ {
	
	//zum füllen der collections
	public static <T,C extends Collection<T>> C addAll(C c, T... t){
		for(T e:t) c.add(e);
		return c;
	}
	
	//zum befüllen der maps
	public static class MapFiller<K,V,M extends Map<K,V>>{
		private M map;
		public MapFiller(M m){
			map=m;
		}
		public MapFiller<K,V,M> put(K key, V value){
			map.put(key,value);
			return this;
		}
		public M endFill(){
			return map;
		}
	}
	
	public static <K,V,M extends Map<K,V>> MapFiller<K,V,M> beginFill(M m){
		return new MapFiller<K,V,M>(m);
	}
	
	public static void main(String[] args){
		
		//ist direkt als Argument einsetzbar, ohne hilfsvariablen
		System.out.println(addAll(new LinkedList<String>(),"a","b","c"));
		
		//ist typsicher, es geht keine information über den konkreten collection typ verloren
		LinkedList<String> list=addAll(new LinkedList<String>(),"a","b","c");

		//etwas umständlicher für maps:
		System.out.println(
			beginFill(new HashMap<Integer,String>())
				.put(2,"zwei")
				.put(3,"drei")
				.put(4,"vier")
				.put(7,"sieben")
			.endFill()
		);
		
		//hier geht auch keine information über typ verloren:
		HashMap<Integer,String> m=beginFill(new HashMap<Integer,String>())
			.put(2,"zwei")
			.put(3,"drei")
			.put(4,"vier")
			.put(7,"sieben")
		.endFill();
	}
}
```
Es erspart einem die Notwendigkeit, sich für temporäre Variablen irgendwelche Namen auszudenken, und durch diese ganzen Manipulationen verliert man nirgends was.


----------



## SchonWiederFred (17. Apr 2009)

Falls es eine unveränderliche Liste sein soll:

```
List<String> list = Arrays.asList("first", "second");
```
ansonsten:

```
List<String> list = new ArrayList<String>(Arrays.asList("first", "second"));
```


----------



## maki (17. Apr 2009)

@SlaterB
Ok, deine Variante ist besser 

@Ebenius
Ok, speziell das Argument mit der Serialisierung ist ein Totschlagargument, hatte ich nicht bedacht.

@Andrey
naja, nicht unbedingt ein Vorschlag oder Warnung, mehr als Diskussionsgrundlage, habe sie heute auch zum ersten mal bewusst so wahrgenommen.

Könnte mich irren, aber ich denke das die Expectations mit JMock so aufgebaut werden, wobei dass bei diesem Anwendungsfall nicht nur vertretbar ist, sonern eine gue Sache.
Aber eben nicht für initialisierungen.


----------

