본문 바로가기
Backend/JAVA

향상된 for문

by Dev_Mook 2024. 10. 30.

개요

향상된 for문Java 5(JDK 1.5) 버전에서 추가된 기능이에요.

향상된 for문이 추가되기 전과 후의 소스코드를 비교하면서 어떤 점이 바뀌었는지 알아보도록 할게요.

JDK 5.0 Documentation을 참고하여 작성한 글입니다.

전통적인 for문

먼저 Java 5(JDK 1.5) 이전에 for문이 어떻게 사용되었는지 알아볼까요?

1 void cancelAll(Collection<TimerTask> c) {
2     // 1. Documentation에 나온 for문
3     for(Iterator<TimerTask> i = c.iterator(); i.hasNext();) {
4         i.next().cancel();
5     }
6 
7     // 2. 개발자들이 많이 작성하는 for문 방식
8     for(int i=0; i < c.size(); i++) [
9         TimerTask timerTask = c.get(i);
10        timerTask.cancel();
11    }
12 }



for문을 사용하기 위해 i라는 변수를 만들어 초기화를 해줘야 해요.

첫 번째 예시처럼 Iterator를 이용해서 데이터를 꺼내거나,

두 번째 예시처럼 인덱스(Index)를 이용해서 데이터를 꺼내야하죠!

그런데 개발자가 변수 이름을 잘못 입력한다면 어떻게 될까요?

3 ~ 5번 줄에 있는 소스코드를 보면 i라는 변수가 3번 쓰였어요.

초기화할 때 한번, i.hasNext()와 i.next()를 할 때 각각 한 번씩!

그리고 8 ~ 11번 줄에도 i라는 변수가 4번 쓰였어요.

만약 개발자들이 i.hasNext()를 k.hasNext()로, i.next()를 k.next()로 잘못 입력한다면?

아니면 9번째 줄에서 c.get(k)로 잘못 입력한다면?

다행히 개발하는 과정에서 k라는 변수를 찾지 못하기 때문에 에러가 발생할거에요.(Compile Error)

하지만 8 ~ 11번 줄에 작성된 소스코드가 아래와 같이 작성된다면 어떤 결과가 나올지 한 번 생각해볼까요?

1    // 편의상 변경된 반복문 소스코드만 작성했습니다.
2    for(int k=4; k < 100; k++) {
3        for(int i=0; i < c.size(); i++) {
4            TimerTask timerTask = c.get(i);
5            timerTask.cancel();
6        }
7    }



자! 이제 개발자가 "c.get(i)"c.get(k)로 잘못 입력했다고 가정해봅시다!

이제 어떤 문제가 발생할까요?

첫 번째 문제는 개발자가 의도한 timerTask의 값이 아닌 다른 데이터가 꺼내진다는 거에요.

변수명을 i로 잘 입력했다면 최초의 timerTask 값은 c.get(0)의 값이 될거에요.

하지만 변수명을 k로 잘못 입력했으니 최초의 timerTask 값은 c.get(4)의 값이 나올겁니다!

두 번째 문제는 값을 꺼낼 수 있는 범위를 넘어설 수 있다는 거에요.

c.size()의 값이 10이라고 가정해볼게요.

그럼 c.get(0)부터 c.get(9)까지는 정상적으로 값을 꺼낼 수 있어요.

하지만 k는 0부터 99까지의 숫자를 사용할 수 있기 때문에 c.get(99)까지 값을 꺼내려고 할 거에요.

c.size()보다 k의 범위가 더 크기때문에 값을 꺼낼 수 있는 범위를 넘어서게 되죠.

이 때 프로그램은 IndexOutOfBoundsException이라는 오류를 발생하게 됩니다.

  • 참고로 k가 10만 되어도 이 오류가 발생하고 프로그램은 동작을 멈추게 되요.

그럼 소스코드를 작성할 때 변수 사용을 최소화하면 오류 발생 가능성도 줄어들지 않을까요?

이런 생각을 바탕으로 태어난 기능이 바로 향상된 for문이랍니다.

향상된 for문이 추가된 이후

향상된 for문은 어떻게 작성되는지 먼저 볼게요.

1 void cancelAll(Collection<TimerTask> c) {
2     // 향상된 for문 사용
3     for(TimerTask timerTask : c) {
4         timerTask.cancel();
5     }
6 }



어떤가요? 소스코드가 정말 간결하지 않나요?

향상된 for문에서 콜론(:)은 in이라고 읽는다고 해요.

  • 즉, 위에 코드를 설명할 때에는 "for each TimerTask in c"라고 읽으면 됩니다.

향상된 for문을 이용하면 변수 선언 횟수가 확실히 줄어들어요.

그만큼 효율적으로 개발할 수 있다는 의미에요.

다만, 소스코드가 실행할 때에는 컴파일러가 이전의 for문으로 변환합니다.

결국 for문의 작성 방식이 개발자 친화적으로 바뀐 것일 뿐!

실제로 동작하는 방식은 동일해요.

그래도 Collections뿐만 아니라 배열도 향상된 for문을 활용하여 데이터를 조작할 수 있으니

안정적인 소스코드 구현을 위해 향상된 for문을 사용해봅시다!

향상된 for문의 단점

향상된 for문이 등장하면서 소스코드가 간결해지고 오류 발생 가능성도 줄어들었어요.

하지만 언제나 장점이 있으면 단점도 있는 법!

Index 0 1 2 3 4 5 6 7
저장된 값 Apple Banana Orange Watermelon Melon Pineapple Strawberry Tomato


위에 작성된 표에서 Index가 홀수인 데이터만 꺼내고 싶을 때에는 어떻게 할까요?

그리고 몇 번째 방에 어떤 과일이 있는지 알려주고 싶을 때에는 어떻게 작성해야 할까요?

    // 위에 작성된 표는 fruits라는 리스트 변수에 저장되었다고 가정하겠습니다.
    for(int i=0; i<8; i++) {
        if(i % 2 == 1) {
            System.out.println(i + "번 째 방에는 과일 " + fruits.get(i) + "이(가) 들어있습니다.");
        }
    }



이 때에는 전통적인 방식의 for문으로 작성해야 되요.

향상된 for문은 index 값을 알려주지 않기 때문이죠.

그래도 굳이 향상된 for문으로 작성하고 싶다면 아래처럼 작성할 수는 있어요.

    int i = 0;
    for(String f : fruits) {
        if(i % 2 == 1) {
            System.out.println(i + "번 째 방에는 과일 " + f + "이(가) 들어있습니다.");
        }
        i++;    // i의 값을 증가시켜줍니다.
    }



출처 및 참고

'Backend > JAVA' 카테고리의 다른 글

Autoboxing과 Unboxing  (1) 2024.10.31
Generics  (0) 2024.10.29