if 조건 분기
if·else·else if의 배타적 경로와 조건 순서를 이용해 회원가입 입력을 저장 또는 거절합니다.
비교식은 참과 거짓을 만들지만 실제 동작을 바꾸지는 않습니다.
if는 그 결과에 따라 실행할 문장 블록을 고릅니다.
입력 범위처럼 서로 겹치는 조건을 나열할 때는 어떤 조건을 먼저 검사했는지가 결과의 일부입니다.
조건 순서의 오류
public final class WrongBranchOrder {
public static void main(String[] args) {
int age = 700;
String result;
if (age > 0) {
result = "accepted";
} else if (age > 120) {
result = "too-old";
} else {
result = "not-positive";
}
System.out.println(result);
}
}accepted700은 age > 0을 만족하므로 첫 블록이 실행되고 나머지 else if는 검사조차 하지 않습니다.
age > 120은 양수 범위 안에 포함되므로 앞 조건이 참인 값에서는 도달할 수 없습니다.
컴파일 오류는 아니지만 업무 규칙과 다른 출력입니다.
오류 조건을 먼저 제거하거나 정상 범위를 정확히 표현합니다.
public final class AgeValidation {
public static void main(String[] args) {
int age = 700;
String result;
if (age <= 0) {
result = "not-positive";
} else if (age > 120) {
result = "too-old";
} else {
result = "accepted";
}
System.out.println(result);
}
}too-old이 사슬은 세 범위를 겹치지 않게 나눕니다.
age <= 0, age > 120, 그리고 두 조건이 모두 거짓인 1–120입니다.
위에서부터 처음 참인 블록 하나만 실행됩니다.
독립 if와 else-if
다음 두 조건은 한 값에서 모두 참일 수 있습니다.
public final class IndependentConditions {
public static void main(String[] args) {
int age = 90;
if (age >= 18) {
System.out.println("adult");
}
if (age >= 65) {
System.out.println("senior");
}
}
}adult
senior두 if는 각각 검사하므로 라벨 두 개가 필요할 때 맞습니다.
반대로 회원을 underage, adult, senior 중 하나로만 분류하려면 else if 사슬을 사용합니다.
if (age < 18) {
label = "underage";
} else if (age < 65) {
label = "adult";
} else {
label = "senior";
}두 번째 조건은 앞 조건이 거짓이라는 사실, 즉 이미 age >= 18임을 전제로 합니다.
그래서 age >= 18 && age < 65를 반복하지 않아도 됩니다.
조건 사슬은 각 행이 이전 실패 범위를 이어받는 구조입니다.
else 결합 규칙
중괄호를 생략하면 한 문장만 조건에 포함되고 else는 아직 짝이 없는 가장 가까운 if에 연결됩니다.
다음 코드는 들여쓰기와 실제 구조가 다르게 보일 수 있습니다.
public final class MisleadingIndentation {
public static void main(String[] args) {
boolean emailPresent = false;
int age = 45;
if (emailPresent)
if (age > 0)
System.out.println("accepted");
else
System.out.println("age rejected");
System.out.println("done");
}
}doneelse는 바깥 if (emailPresent)가 아니라 안쪽 if (age > 0)의 짝입니다.
이메일이 없을 때는 안쪽 조건 전체가 실행되지 않아 거절 메시지도 없습니다.
중괄호를 항상 쓰면 블록 소속이 들여쓰기와 일치합니다.
if (!emailPresent) {
System.out.println("email rejected");
} else if (age <= 0) {
System.out.println("age rejected");
} else {
System.out.println("accepted");
}짧은 한 줄이라도 이후 로그 한 줄이 추가되면 중괄호 없는 코드의 실행 범위가 쉽게 어긋납니다.
이 자습서의 조건문은 모두 중괄호를 사용합니다.
저장 가능 상태
조건 분기 자체에 집중하기 위해 이번 예제의 값은 코드에 직접 둡니다.
문자열 숫자 변환과 try/catch를 여기서 미리 사용하지 않고 ch3의 입력 검증에서 처음 설명합니다.
public class SignupDecision {
public static void main(String[] args) {
String email = "conditions@example.com";
int age = 45;
if (email.isBlank()) {
System.out.println("email is required");
} else if (age <= 0) {
System.out.println("age must be positive");
} else if (age > 120) {
System.out.println("age must be at most 120");
} else {
String label;
if (age < 18) {
label = "underage";
} else if (age < 65) {
label = "adult";
} else {
label = "senior";
}
System.out.println("saved=" + email + ":" + age + ":" + label);
}
}
}saved=conditions@example.com:45:adultage를 0, 18, 65, 121로 바꾸어 한 번씩 실행합니다.
한 실행에서는 위에서부터 처음 참인 블록 하나만 선택됩니다.
실제 사용자 입력도 같은 분기로 들어오지만, 먼저 안전하게 문자열을 숫자로 바꾸는 단계가 필요합니다.
조건 경계표
| 입력 | 첫 참 조건 | 결과 |
|---|---|---|
| 이메일 없음 | email.isBlank() | 이메일 오류 |
| 0세 | age <= 0 | 양수 오류 |
| 1세 | 앞 오류 모두 거짓 | underage 저장 |
| 18세 | age < 65 | adult 저장 |
| 65세 | 마지막 else | senior 저장 |
| 120세 | 마지막 else | senior 저장 |
| 121세 | age > 120 | 최대값 오류 |
표의 각 행이 정확히 한 결과에만 도달하는지 확인합니다.
특히 경계와 바로 이웃한 0/1, 17/18, 64/65, 120/121을 실행하면 <와 <= 차이를 찾을 수 있습니다.
이 검사를 다음 조건 훈련 절에서 자동화합니다.
연습 문제
LoginAttemptClassifier를 작성해 로그인 실패 횟수를 다음처럼 하나의 라벨로 분류하세요.
- 음수:
invalid - 0:
clean - 1–2:
allowed - 3–5:
warning - 6 이상:
locked
0, 2, 5, 6을 각각 실행해 조건 순서를 확인합니다.
해설 보기
public final class LoginAttemptClassifier {
public static void main(String[] args) {
int failedLoginCount = Integer.parseInt(args[0]);
String label;
if (failedLoginCount < 0) {
label = "invalid";
} else if (failedLoginCount == 0) {
label = "clean";
} else if (failedLoginCount <= 2) {
label = "allowed";
} else if (failedLoginCount <= 5) {
label = "warning";
} else {
label = "locked";
}
System.out.println(label);
}
}각 <= 조건은 앞 단계보다 큰 값만 받습니다.
failedLoginCount <= 5는 실제로 3–5를 뜻합니다.
넓은 failedLoginCount >= 0을 앞에 놓으면 뒤 라벨에 도달할 수 없으므로 작은 범위부터 위에서 제거합니다.