switch 식과 삼항 연산
닫힌 선택지를 switch 문·switch 식으로 분리하고 두 값 중 하나를 고르는 경우에만 삼항 연산자를 사용합니다.
if는 범위와 서로 다른 조건식을 다루기 좋지만 하나의 명령 문자열이나 메뉴 번호를 반복 비교하면 대상이 묻힙니다.
switch는 같은 값의 여러 후보를 한곳에 모읍니다.
Java의 전통적인 콜론형 switch 문은 break가 없으면 다음 case로 흐르고, 화살표 switch 식은 분기마다 결과 값을 만들 수 있습니다.
switch 관통 실행
public final class SwitchFallThrough {
public static void main(String[] args) {
int menu = 1;
switch (menu) {
case 1:
System.out.println("record");
case 2:
System.out.println("runtime");
case 0:
System.out.println("quit");
default:
System.out.println("unknown");
}
}
}record
runtime
quit
unknowncase 1에서 시작한 뒤 switch 블록 끝까지 순서대로 실행됐습니다.
case는 다음 case에 도착했다고 자동으로 멈추지 않습니다.
의도적인 fall-through로 여러 후보가 같은 코드를 공유할 수도 있지만, 누락인지 의도인지 구분하기 어렵습니다.
콜론형 문을 유지한다면 각 경로에서 break로 switch를 빠져나옵니다.
public final class SwitchStatement {
public static void main(String[] args) {
int menu = 1;
switch (menu) {
case 1:
System.out.println("record");
break;
case 2:
System.out.println("runtime");
break;
case 0:
System.out.println("quit");
break;
default:
System.out.println("unknown");
}
}
}break는 가장 가까운 switch 문을 끝내고 그 다음 문장으로 이동합니다.
반복문의 break와 이름은 같지만 빠져나가는 대상은 현재 감싸고 있는 switch입니다.
switch 표현식
public final class CommandLabel {
public static void main(String[] args) {
String command = args.length == 0 ? "help" : args[0];
String label = switch (command) {
case "env" -> "toolchain report";
case "runtime" -> "runtime report";
case "paths" -> "workspace report";
case "record" -> "record a session";
case "help" -> "show usage";
default -> "unknown command";
};
System.out.println(label);
}
}record a sessionswitch (command) 전체가 String 값을 만들고 마지막 세미콜론에서 대입 문장이 끝납니다.
화살표 오른쪽 분기는 다음 case로 흘러가지 않습니다.
label을 먼저 빈 값으로 초기화한 뒤 각 case에서 다시 대입할 필요도 없습니다.
여러 문장을 실행한 뒤 값을 내놓으려면 블록과 yield를 사용합니다.
public final class SwitchYield {
public static void main(String[] args) {
int minutes = 75;
String description = switch (minutes / 60) {
case 0 -> "under one hour";
case 1 -> {
int remainder = minutes % 60;
System.out.println("remainder=" + remainder);
yield "one hour range";
}
default -> "two hours or more";
};
System.out.println(description);
}
}remainder=15
one hour rangeyield는 switch 식의 해당 분기 결과를 제공합니다.
메서드를 끝내는 return과 다릅니다.
모든 가능한 분기가 호환되는 타입의 값을 만들어야 하므로 결과 누락을 컴파일러가 찾을 수 있습니다.
범위 조건과 if
switch의 후보는 같은 선택 값에 대한 닫힌 목록일 때 가장 잘 읽힙니다.
minutes < 30, minutes <= 60처럼 범위를 순서대로 제거하는 조건은 if/else if가 직접적입니다.
반대로 command.equals("env"), command.equals("runtime")을 반복하는 코드는 switch가 비교 대상을 한 번만 보여 줍니다.
| 문제 | 우선할 표현 | 이유 |
|---|---|---|
| 1–600분 범위 검증 | if | 서로 다른 비교식과 순서가 핵심 |
| 명령 문자열 선택 | switch 식 | 같은 값의 후보 목록 |
| 메뉴별 여러 문장 실행 | 화살표 switch 문 | fall-through 없이 블록 실행 |
| 두 라벨 중 하나 선택 | 삼항 연산자 | 결과가 정확히 두 값 |
삼항 연산자의 범위
public final class TernaryLabel {
public static void main(String[] args) {
int minutes = 45;
boolean completed = minutes >= 60;
String status = completed ? "complete" : "in-progress";
System.out.println(status);
}
}조건이 참이면 ?와 : 사이 값을, 거짓이면 : 뒤 값을 선택합니다.
삼항 연산자도 값 하나를 만드는 식이므로 변수 초기화나 메서드 인자에 사용할 수 있습니다.
세 단계 이상을 중첩하면 조건과 결과의 짝이 빠르게 흐려집니다.
String label = minutes < 30 ? "short"
: minutes < 60 ? "focused"
: "long";문법상 동작하지만 분기 순서와 범위를 검토하기는 if/else if가 쉽습니다.
“참과 거짓에 각각 짧은 값 하나”라는 형태를 벗어나면 조건문이나 switch 식으로 풀어냅니다.
출력이나 상태 변경을 삼항 연산자의 두 분기에 넣지 않습니다.
명령 라우팅과 상태 라벨
CLI의 바깥 switch는 어떤 기능을 호출할지 고르고, record 안의 if는 입력 범위를 검증하며, 삼항 연산자는 완료 라벨 두 개 중 하나를 고릅니다.
서로 다른 판단을 한 표현에 몰지 않습니다.
public final class RecordRouting {
public static void main(String[] args) {
if (args.length == 0) {
System.out.println("command required");
return;
}
switch (args[0]) {
case "record" -> record(args);
case "help" -> System.out.println("record <topic> <actual> <target>");
default -> System.out.println("unknown command: " + args[0]);
}
}
private static void record(String[] args) {
if (args.length != 4) {
System.out.println("record requires topic, actual, target");
return;
}
String topic = args[1];
int actual = Integer.parseInt(args[2]);
int target = Integer.parseInt(args[3]);
if (actual <= 0 || target <= 0) {
System.out.println("minutes must be positive");
return;
}
String status = actual >= target ? "complete" : "in-progress";
System.out.println(topic + ":" + actual + ":" + status);
}
}> java -cp out RecordRouting record switch 70 60
switch:70:complete
> java -cp out RecordRouting help
record <topic> <actual> <target>연습 문제
FormatSelector를 작성하세요.
첫 인자는 plain, compact, debug 중 하나이며 switch 식으로 라벨을 만듭니다.
둘째 인자 분이 60 이상이면 삼항 연산자로 long, 아니면 short를 선택합니다.
알 수 없는 형식은 unsupported를 출력합니다.
해설 보기
public final class FormatSelector {
public static void main(String[] args) {
String format = args[0];
int minutes = Integer.parseInt(args[1]);
String formatLabel = switch (format) {
case "plain" -> "text";
case "compact" -> "one-line";
case "debug" -> "diagnostic";
default -> "unsupported";
};
String durationLabel = minutes >= 60 ? "long" : "short";
System.out.println(formatLabel + ":" + durationLabel);
}
}java -cp out FormatSelector debug 75는 diagnostic:long을 출력합니다.
형식 후보는 switch에, 연속적인 시간 범위의 두 결과는 비교와 삼항 연산자에 남아 판단의 종류가 분리됩니다.