language/java

[자바프로그래밍] 04. 반복문

렁치 2026. 8. 11. 14:31

반복문은 같은 작업을 여러 번 수행하게 한다. 자바의 for·while·do~while은 C와 거의 같지만, 자바에는 라벨(label)을 이용한 분기라는 독특한 기능이 더 있다.


1. 세 가지 반복문

// for: 횟수가 정해진 반복
int sum = 0;
for (int i = 1; i <= 10; i++)   // for 안에서 변수 i 선언 가능
    sum += i;

// while: 조건이 참인 동안
int i = 1;
while (i <= 10) { System.out.println(i); i++; }

// do~while: 최소 1번은 실행
char a = 'a';
do {
    System.out.print(a);
    a = (char)(a + 1);
} while (a <= 'z');   // abc...z

for의 초기식에서 선언한 변수(int i)는 그 반복문 안에서만 유효하다는 점이 C와 다른 깔끔한 부분이다. 반복이 끝나면 변수도 사라지니, 같은 이름을 다른 반복에서 다시 써도 충돌이 없어 편했다.

조건으로 끝나는 반복은 입력을 조건식 안에 넣는 패턴을 자주 쓴다.

// 0이 입력될 때까지 합산
while ((n = scan.nextInt()) != 0) {
    sum += n;
    count++;
}

2. 분기문: break, continue, 그리고 라벨

  • break: 반복문을 즉시 빠져나온다.
  • continue: 이번 반복만 건너뛰고 다음 반복으로 간다.
for (int i = 0; i < 5; i++) {
    n = scan.nextInt();
    if (n <= 0) continue;   // 양수가 아니면 건너뜀
    sum += n;
}
라벨(label)로 바깥 반복까지 제어하기
기본적으로 break·continue는 자신을 감싼 가장 안쪽 반복문 하나에만 작용한다. 중첩 반복에서 바깥 반복까지 한 번에 빠져나가거나 건너뛰려면, 반복문 앞에 라벨을 붙여 break 라벨; / continue 라벨; 로 지정한다.
Outer: for (int i = 2; i <= 9; i++) {
    for (int j = 1; j <= 9; j++) {
        if (j == 3) continue Outer;   // 안쪽이 아니라 바깥 for의 다음 반복으로
        System.out.println(i + " * " + j + " = " + i*j);
    }
}

C에는 없는 자바의 기능으로, 깊은 중첩에서 goto 없이 깔끔하게 탈출할 수 있게 해준다. C에서 중첩 반복을 한 번에 빠져나가려 플래그 변수를 두던 게 떠올라, 라벨이 그 번거로움을 덜어준다는 걸 알았다.


3. 명령행 인자 (Command Line Argument)

main(String[] args)args는 프로그램 실행 시 콘솔에서 넘긴 값들을 담는다. 모두 문자열로 저장된다는 점이 중요하다.

public static void main(String[] args) {
    System.out.println(args[0]);   // 첫 번째 인자
}
// 실행: java Exam 자바 123 → args[0]="자바", args[1]="123"

숫자 123을 넘겨도 "123" 문자열로 들어오므로, 계산하려면 Integer.parseInt(args[1])로 변환해야 한다.


실습으로 익히기

같은 이름의 메서드를 매개변수 유무로 나눠 정의하는 오버로딩을 구구단에 적용한 예다.

static void gugudan() {                 // 인자 없음: 2~9단 전체
    for (int dan = 2; dan <= 9; dan++)
        for (int j = 1; j <= 9; j++)
            System.out.print(dan + "x" + j + "=" + (dan*j) + "\t");
}
static void gugudan(int dan) {          // 인자 있음: 특정 단만 (오버로딩)
    for (int j = 1; j <= 9; j++)
        System.out.print(dan + "x" + j + "=" + (dan*j) + "\t");
}

gugudan()gugudan(int)는 이름이 같지만 매개변수가 달라 별개의 메서드로 취급된다. "전체 출력"과 "특정 단 출력"을 같은 이름으로 자연스럽게 묶은 것이다. C++에서 본 오버로딩이 자바에서도 똑같이 통하는 걸 보니, 객체 지향 언어들이 공유하는 개념이라는 게 느껴졌다.


오늘 느낀 점

  • for 초기식의 변수가 반복 안에서만 산다는 점이 C보다 깔끔했다. 변수 수명이 범위에 묶이니 실수가 줄었다.
  • 라벨이 C의 플래그 변수 트릭을 대신해 중첩 탈출을 깔끔하게 해준다는 게 좋았다. 다만 남용하면 흐름이 꼬일 수 있어 꼭 필요할 때만 쓰기로 했다.
  • "받은 건 일단 문자열(명령행 인자)"이라는 점에서, 입력의 출처와 무관하게 변환이 필요하다는 감각을 챙겼다.

한 걸음 더

  • 자바에는 배열·컬렉션을 순회하는 향상된 for문(for-each)이 따로 있다. for (int x : arr)처럼 인덱스 없이 모든 원소를 돈다. 인덱스 실수를 줄이고 코드가 간결해져, 단순 순회에는 이쪽을 더 많이 쓴다.
  • 라벨은 강력하지만 남용하면 흐름이 복잡해져 읽기 어렵다. 그래서 "중첩이 깊고 바깥까지 한 번에 탈출해야 하는" 꼭 필요한 경우에만 쓰고, 가능하면 반복을 메서드로 분리해 return으로 빠져나가는 편이 더 깔끔할 때가 많다.
  • 명령행 인자가 모두 문자열인 건 운영체제가 프로그램에 값을 넘기는 방식이 본래 텍스트이기 때문이다. 그래서 어떤 언어든 명령행 인자는 문자열로 받아 필요하면 직접 숫자로 변환한다. 입력의 출처가 키보드든 명령행이든, "받은 건 일단 문자열"이라는 감각이 유용하다.