Java에서 코드의 실행 흐름을 원하는 대로 조작하려면 분기 구문을 정확히 이해해야 한다. 이번 글에서는 반복문 탈출, 반복 건너뛰기, 메서드 종료, 예외 발생까지 다루는 핵심 분기 요소들을 살펴본다.
break: 즉시 빠져나가기
가장 단순하면서도 강력한 분기 구문이다. 현재 진행 중인 반복문이나 switch 구문을 즉시 종료하고 다음 문장으로 이동한다.
반복문에서의 활용
public class LoopEscape {
public static void main(String[] args) {
int threshold = 7;
for (int idx = 1; idx <= 100; idx++) {
if (idx == threshold) {
break;
}
System.out.println("현재 값: " + idx);
}
System.out.println("반복문 외부로 탈출 완료");
}
}
변수 idx가 7이 되는 순간 반복문을 완전히 빠져나간다. 따라서 1부터 6까지만 출력된다.
switch 구문에서의 활용
public class MenuSelector {
public static void main(String[] args) {
int selection = 2;
String description;
switch (selection) {
case 1:
description = "사용자 관리";
break;
case 2:
description = "주문 내역";
break;
case 3:
description = "설정 변경";
break;
default:
description = "알 수 없는 메뉴";
}
System.out.println(description);
}
}
break를 생략하면 fall-through 현상이 발생하여 의도치 않은 case가 연속 실행될 수 있다.
continue: 현재 회차만 건너뛰기
반복문 전체를 종료하지 않고, 현재 반복 회차만 중단하고 다음 회차로 진행한다.
public class OddPrinter {
public static void main(String[] args) {
for (int num = 1; num <= 20; num++) {
if (num % 2 == 0) {
continue;
}
System.out.println("홀수 발견: " + num);
}
}
}
짝수일 때 continue가 실행되면 그 아래의 System.out.println은 수행되지 않고 다음 num으로 넘어간다.
return: 메서드 실행 즉시 종료
메서드의 몸체를 빠져나가며, 필요시 호출부로 값을 전달한다.
값을 반환하는 경우
public class Calculator {
public static void main(String[] args) {
int product = multiply(4, 6);
System.out.println("곱셈 결과: " + product);
}
static int multiply(int factorA, int factorB) {
return factorA * factorB;
}
}
반환 타입이 void인 경우
public class Logger {
public static void main(String[] args) {
logIfValid(null);
logIfValid("정상적인 로그 메시지");
}
static void logIfValid(String content) {
if (content == null || content.isBlank()) {
return;
}
System.out.println("[LOG] " + content);
}
}
조건 미충족 시 메서드 후반부의 로직을 실행하지 않고 바로 종료할 수 있다.
throw: 예외를 의도적으로 발생시키기
프로그램이 정상적인 흐름을 벗어나는 상황을 명시적으로 표현할 때 사용한다.
public class SafeDivider {
public static void main(String[] args) {
try {
double quotient = computeQuotient(15.0, 0.0);
System.out.println("나눗셈 결과: " + quotient);
} catch (IllegalArgumentException ex) {
System.err.println("오류 발생 - " + ex.getMessage());
}
}
static double computeQuotient(double numerator, double denominator) {
if (denominator == 0.0) {
throw new IllegalArgumentException("분모는 0이 될 수 없음");
}
return numerator / denominator;
}
}
try-catch-finally: 예외 처리의 안전망
예외가 발생할 가능성이 있는 코드를 보호하고, 자원 해제 등 필수 후처리를 보장한다.
public class ResourceHandler {
public static void main(String[] args) {
java.util.Scanner reader = null;
try {
reader = new java.util.Scanner(System.in);
System.out.print("정수 입력: ");
int value = Integer.parseInt(reader.nextLine());
System.out.println("입력값의 제곱: " + (value * value));
} catch (NumberFormatException nfe) {
System.out.println("숫자 형식이 아닙니다.");
} finally {
if (reader != null) {
reader.close();
System.out.println("Scanner 자원 해제 완료");
}
}
}
}
assert: 개발 단계 조건 검증
프로덕션 환경에서는 비활성화되는 검증 구문으로, 개발 중 불변식(invariant)을 확인하는 용도로 쓰인다.
public class AssertionDemo {
public static void main(String[] args) {
int minimumAge = 18;
int userAge = 15;
assert userAge >= minimumAge : "미성년자는 접근할 수 없습니다.";
System.out.println("접근 허용");
}
}
VM 옵션 -ea(enable assertions)를 추가해야 활성화되며, 위 예시는 AssertionError를 발생시킨다.
각 구문의 적절한 선택 기준
| 구문 | 적용 상황 | 영향 범위 |
|---|---|---|
break | 반복 조건이 충족되어 더 이상 진행할 필요 없을 때 | 현재 반복문 또는 switch |
continue | 현재 데이터만 건너뛰고 나머지는 정상 처리할 때 | 현재 반복 회차 |
return | 메서드의 목적이 달성되었거나 조건 미충족 시 | 현재 메서드 |
throw | 비즈니스 규칙 위이나 시스템 예외 발생 시 | 호출 스택을 따라 예외 처리기로 |
assert | 개발 중 내부 논리 검증 | 프로그램 전체(조건부) |