을 바이트 코드의 차이는 javap -c
입니다.
public static void test(java.lang.String);
Code:
0: aload_0
1: ldC#16; //String ;
3: invokevirtual #18; //Method java/lang/String.split:(Ljava/lang/String;)[Ljava/lang/String;
6: astore_1
7: aload_1
8: dup
9: astore 5
11: arraylength
12: istore 4
14: iconst_0
15: istore_3
16: goto 27
19: aload 5
21: iload_3
22: aaload
23: astore_2
24: iinc 3, 1
27: iload_3
28: iload 4
30: if_icmplt 19
33: return
}
둘째 : 이클립스 컴파일러로 컴파일 (소스 코드에서 지역 변수와) 첫 번째 버전이 제공
public static void test(java.lang.String);
Code:
0: aload_0
1: ldC#16; //String ;
3: invokevirtual #18; //Method java/lang/String.split:(Ljava/lang/String;)[Ljava/lang/String;
6: dup
7: astore 4
9: arraylength
10: istore_3
11: iconst_0
12: istore_2
13: goto 24
16: aload 4
18: iload_2
19: aaload
20: astore_1
21: iinc 2, 1
24: iload_2
25: iload_3
26: if_icmplt 16
29: return
}
당신이이 글을 읽을 수 있다면 당신은 (볼 수 있듯이), 첫 번째 변형은 추가 로컬 변수 슬롯 (처음에는 astore_1
/aload_1
)을 사용합니다.그러나 (a) 바이트 코드가 해석 되더라도 오버 헤드는 무시할 수 있습니다 (참조를 복사하는 것입니다). 그리고 (b) JIT 컴파일러는 미리 정적 바이트 코드 최적화를 수행했는지 여부에 상관없이 최적화 할 수 있습니다. : 지역 변수 (1)는 이후에 사용되지 않습니다.
소스 코드의 로컬 변수는 주로 중간 결과를 명확하게하고 재사용 할 수 있도록 사용됩니다. 기본적으로 명시적인 지역 변수가없는 두 번째 변형은 split
의 결과를 사용자의 메서드에서 (또는 루프 내에서 직접) 다시 사용할 수 없도록하는 반면 코드에서 로컬 변수의 이름을 지정할 수는 있습니다. 내가 컴파일러가 똑똑하면 충분히 가 분할을 할 궁금 코드의 두 번째 파이스 동전으로
한 번만
은
당신의 두 가지 방법 사이의 유일한 차이는에서 지역 변수의 명시 적 선언이다 소스 코드. 두 경우
,
for (String f: flags.split(";")) { }
은 문법적 (즉 제외하고는하지도 않는다 로컬 변수가 액세스)에 상당 :
이 표기법
- ,
_hidden_i
은 참고하기 int _hidden_i = 0;
for (String[] _hidden_arr=flags.split(";"); _hidden_i<_hidden_arr.length; _hidden_i++){
String f = _hidden_arr[_hidden_i];
// some stuff
}
점한다는 것이다 노출되지 않으므로 무언가를 _hidden_arr[_hidden_i]
에 할당 할 수 없습니다.
- 순진한 소스 - 바이트 코드 컴파일러조차도
_hidden_arr
과 _hidden_i
이 결코 다시 사용되지 않을 것이므로 더 이상 사용하기 위해 복사하지 않습니다. 근본적으로 달라졌을 것이다 무엇
는이었을 것입니다 :
for (var i = 0; i < flags.split(";").length; i++) {
String f = flags.split(";")[i];
}
for(;;)
표기법에서, 첫 번째 부분은 항상 한 번 실행됩니다. 두 번째 표현식은 루프 블록에 들어가기 전에 항상 실행됩니다 (실행 여부를 테스트하기 위해). 마지막은 루프 블록을 실행 한 후에 항상 실행됩니다 (break
이 사용되지 않는 한).
일반적으로 두 번째 부분에 무거운 할 수있는 메서드 호출은 피하고 싶습니다. 특히 항상 같은 결과가 나오는 경우가 많습니다.
왜 스스로 간단한 벤치 마크를 실행하지 않습니까? 동일한 문자열을 n 번 (n이 충분히 큰) n 번 실행하고 관심있는 모든 시간이나 메모리 사용량을 실행하십시오. – pintxo
시간을 측정하는 벤치 마크에 대해 생각했습니다. 그러나 Java가 내 프로그래밍 기술을 향상시키는 것에 대한 지식을 더 많이 습득하기 때문에 질문을하는 것이 더 나은 선택이라고 생각했습니다. 또한 다른 사람들도 같은 질문을 할 수 있습니다. –
두 버전을 모두 디버깅 할 수 있습니다. _back stage_가 어떻게되는지 알아내는 것입니다. –