참고
@Test public void whenInitializeSetWithDoubleBraces_containsElements() { Set<String> countries = new HashSet<String>() { { add("India"); add("USSR"); add("USA"); } }; assertTrue(countries.contains("India")); }
- 위와 같이 객체를 초기화하면서 생성을 하는 방법을 Double Brace Initialization 이라고 함
- 명시된 클래스로부터 익명 클래스를 만들고(outer braces), 초기화하는 로직(inner braces)을 한번에 적는 것을 의미.
장점
- 라인 수가 줄어서 간단해 보임. 코드가 읽기에 좋음
- 초기화와 생성이 한번에 됨
단점
- 애매모호하고 잘 알려진 초기화 방법이 아님
- 사용할 때 마다 extra class를 생성함. 익명 클래스 방식으로 생성이 되기 때문(아래와 같이 클래스 생성을 계속하게 되면 ClassLoader의 입장에서 부담이 됨)
Test$1$1$1.class Test$1$1$2.class Test$1$1.class Test$1.class Test.class
- final 클래스에 대해서는 적용이 불가능함. 왜냐면 익명 클래스 방식은 그 클래스를 extend하는 형식으로 객체 생성하니까
public class App{ public static void main( String[] args ) { HashMap<String, String> a = new HashMap<>(); a.put("a", "a"); HashMap<String, String> b = new HashMap<>(){{ put("b", "b"); }}; System.out.println(a.getClass()); // class java.util.HashMap System.out.println(b.getClass()); // class org.prgms.App$1 } }
- 위의 코드의 결과를 살펴보면 Double Brace Initialization으로 생성된 객체의 클래스는 App 클래스에 대한 참조를 가지고 있음(reference to their enclosing instance)
- enclosing 클래스가 매우 큰 클래스라면, 오랫동안 가지고 있을 수 있으니 메모리 누수가 됨
- Serializing을 할 때 문제가 생길 수 있음
- garbage collection에서도 문제 생김
대안
Stream Factory Methods
@Test public void whenInitializeUnmodifiableSetWithDoubleBrace_containsElements() { Set<String> countries = Stream.of("India", "USSR", "USA") .collect(collectingAndThen(toSet(), Collections::unmodifiableSet)); assertTrue(countries.contains("India")); }
Java 9 Collections Factory Methods
List<String> list = List.of("India", "USSR", "USA"); Set<String> set = Set.of("India", "USSR", "USA");