foreach어쨌든 후드 아래에서 반복자를 사용합니다. 그것은 단지 구문 설탕입니다.
다음 프로그램을 고려하십시오.
import java.util.List;
import java.util.ArrayList;
public class Whatever {
private final List<Integer> list = new ArrayList<>();
public void main() {
for(Integer i : list) {
}
}
}
의와 함께 컴파일하자 javac Whatever.java,
그리고의 분해 바이트 코드를 읽어 main()사용 javap -c Whatever:
public void main();
Code:
0: aload_0
1: getfield #4 // Field list:Ljava/util/List;
4: invokeinterface #5, 1 // InterfaceMethod java/util/List.iterator:()Ljava/util/Iterator;
9: astore_1
10: aload_1
11: invokeinterface #6, 1 // InterfaceMethod java/util/Iterator.hasNext:()Z
16: ifeq 32
19: aload_1
20: invokeinterface #7, 1 // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
25: checkcast #8 // class java/lang/Integer
28: astore_2
29: goto 10
32: return
우리는 foreach다음과 같은 프로그램으로 컴파일 되는 것을 볼 수 있습니다 .
- 다음을 사용하여 반복자를 만듭니다.
List.iterator()
- If
Iterator.hasNext(): Iterator.next()루프를 호출 하고 계속합니다
에 관해서는? "이 쓸모없는 루프가 컴파일 된 코드의 밖으로 최적화되지 않는 이유를 우리는 목록 항목으로 아무것도하지 않는 것을 볼 수있다"음, 코드 당신의 반복 가능한 그런 당신을 위해 가능 .iterator()부작용이있다 또는 .hasNext()부작용 또는 의미있는 결과가있는 것입니다.
데이터베이스에서 스크롤 가능한 쿼리를 나타내는 iterable .hasNext()이 데이터베이스에 접속하거나 결과 세트의 끝에 도달하여 커서를 닫는 것과 같이 극적인 일을 할 수 있다고 쉽게 상상할 수 있습니다 .
따라서 루프 본문에서 아무 일도 일어나지 않는다는 것을 증명할 수 있지만 반복 할 때 의미 있고 결과적인 일이 발생하지 않음을 증명하는 것이 더 비쌉니다. 컴파일러는이 빈 루프 본문을 프로그램에 그대로 두어야합니다.
우리가 기대할 수있는 최선은 컴파일러 경고 일 것 입니다. 이 빈 루프 바디에 대해 경고 javac -Xlint:all Whatever.java하지 않는 것이 흥미 롭습니다 . 그러나 IntelliJ IDEA는 그렇게합니다. 필자는 Eclipse 컴파일러를 사용하도록 IntelliJ를 구성했지만 그 이유가 아닐 수도 있습니다.
