익명의 내부 클래스로 너무 멀어지면 문제가 있습니다.
2009/05/27 16:35 1,602 DemoApp2$1.class
2009/05/27 16:35 1,976 DemoApp2$10.class
2009/05/27 16:35 1,919 DemoApp2$11.class
2009/05/27 16:35 2,404 DemoApp2$12.class
2009/05/27 16:35 1,197 DemoApp2$13.class
/* snip */
2009/05/27 16:35 1,953 DemoApp2$30.class
2009/05/27 16:35 1,910 DemoApp2$31.class
2009/05/27 16:35 2,007 DemoApp2$32.class
2009/05/27 16:35 926 DemoApp2$33$1$1.class
2009/05/27 16:35 4,104 DemoApp2$33$1.class
2009/05/27 16:35 2,849 DemoApp2$33.class
2009/05/27 16:35 926 DemoApp2$34$1$1.class
2009/05/27 16:35 4,234 DemoApp2$34$1.class
2009/05/27 16:35 2,849 DemoApp2$34.class
/* snip */
2009/05/27 16:35 614 DemoApp2$40.class
2009/05/27 16:35 2,344 DemoApp2$5.class
2009/05/27 16:35 1,551 DemoApp2$6.class
2009/05/27 16:35 1,604 DemoApp2$7.class
2009/05/27 16:35 1,809 DemoApp2$8.class
2009/05/27 16:35 2,022 DemoApp2$9.class
이들은 간단한 응용 프로그램을 만들 때 생성되었으며 많은 양의 익명 내부 클래스를 사용했습니다. 각 클래스는 별도의 class
파일 로 컴파일됩니다 .
이미 언급했듯이 "이중 괄호 초기화"는 인스턴스 초기화 블록이있는 익명의 내부 클래스입니다. 이는 일반적으로 단일 객체를 만들기 위해 모든 "초기화"에 대해 새 클래스가 만들어 짐을 의미합니다.
Java Virtual Machine은 클래스를 사용할 때 해당 클래스를 모두 읽어야하므로 바이트 코드 검증 프로세스 등에서 시간이 걸릴 수 있습니다 . 모든 class
파일 을 저장하기 위해 필요한 디스크 공간이 증가한 것은 말할 것도 없습니다 .
이중 괄호 초기화를 사용할 때 약간의 오버 헤드가있는 것처럼 보이므로 너무 지나치게 선을 긋는 것은 좋은 생각이 아닙니다. 그러나 Eddie가 의견에서 언급했듯이 그 영향을 절대적으로 확신하는 것은 불가능합니다.
참고로 이중 괄호 초기화는 다음과 같습니다.
List<String> list = new ArrayList<String>() {{
add("Hello");
add("World!");
}};
Java의 "숨겨진"기능처럼 보이지만 다음과 같이 다시 작성되었습니다.
List<String> list = new ArrayList<String>() {
// Instance initialization block
{
add("Hello");
add("World!");
}
};
따라서 기본적으로 익명의 내부 클래스의 일부인 인스턴스 초기화 블록 입니다 .
Project Coin 에 대한 Joshua Bloch의 Collection Literals 제안 은 다음과 같습니다.
List<Integer> intList = [1, 2, 3, 4];
Set<String> strSet = {"Apple", "Banana", "Cactus"};
Map<String, Integer> truthMap = { "answer" : 42 };
슬프게도, 그것은 그것의 방법을하지 않았다 도 자바 7이나 8로 무기한 보류했다.
실험
여기에 내가 테스트 한 간단한 실험이다 - 메이크업 1000 개 ArrayList
요소와의 "Hello"
와 "World!"
비아 그들에 추가 add
하는 방법, 두 가지 방법을 사용하여이 :
방법 1 : 이중 브레이스 초기화
List<String> l = new ArrayList<String>() {{
add("Hello");
add("World!");
}};
방법 2 : 인스턴스화 ArrayList
및add
List<String> l = new ArrayList<String>();
l.add("Hello");
l.add("World!");
Java 소스 파일을 작성하여 두 가지 방법으로 1000 개의 초기화를 수행하는 간단한 프로그램을 만들었습니다.
시험 1 :
class Test1 {
public static void main(String[] s) {
long st = System.currentTimeMillis();
List<String> l0 = new ArrayList<String>() {{
add("Hello");
add("World!");
}};
List<String> l1 = new ArrayList<String>() {{
add("Hello");
add("World!");
}};
/* snip */
List<String> l999 = new ArrayList<String>() {{
add("Hello");
add("World!");
}};
System.out.println(System.currentTimeMillis() - st);
}
}
시험 2 :
class Test2 {
public static void main(String[] s) {
long st = System.currentTimeMillis();
List<String> l0 = new ArrayList<String>();
l0.add("Hello");
l0.add("World!");
List<String> l1 = new ArrayList<String>();
l1.add("Hello");
l1.add("World!");
/* snip */
List<String> l999 = new ArrayList<String>();
l999.add("Hello");
l999.add("World!");
System.out.println(System.currentTimeMillis() - st);
}
}
1000 ArrayList
초 및 1000 개의 익명 내부 클래스 확장 을 초기화하는 데 소요되는 시간 ArrayList
은을 사용하여 확인 System.currentTimeMillis
되므로 타이머의 해상도가 매우 높지 않습니다. 내 Windows 시스템에서 해상도는 약 15-16 밀리 초입니다.
두 테스트 중 10 회 실행 결과는 다음과 같습니다.
Test1 Times (ms) Test2 Times (ms)
---------------- ----------------
187 0
203 0
203 0
188 0
188 0
187 0
203 0
188 0
188 0
203 0
알 수 있듯이, 이중 브레이스 초기화는 눈에 띄는 실행 시간이 약 190ms입니다.
한편, ArrayList
초기화 실행 시간은 0ms로 나타났다. 물론 타이머 해상도를 고려해야하지만 15ms 미만일 수 있습니다.
따라서 두 방법의 실행 시간에 눈에 띄는 차이가있는 것으로 보입니다. 두 가지 초기화 방법에는 실제로 약간의 오버 헤드가있는 것으로 보입니다.
그리고 이중 중괄호 초기화 테스트 프로그램 .class
을 컴파일하여 1000 개의 파일이 생성되었습니다 Test1
.
flavors
을 수HashSet
있지만, 슬프게도 그것은 익명의 서브 클래스입니다.