공공부하자개발 · 영어 학습 노트
자바
초급자바의 뼈대0/8 완료
  • 00개발 환경과 첫 프로그램
  • 01변수, 데이터 타입, 형변환
  • 02연산자와 제어문
  • 031차원 · 2차원 배열
  • 04클래스, 객체, 생성자, 오버로딩
  • 05접근 제어자와 캡슐화
  • 06메서드 활용 패턴 (초급)
  • 07enum, 패키지와 import, static 과 final
사이트 소개개인정보처리방침연락처
© 2026 공부하자
홈 › 초급 › 02 / 8

연산자와 제어문

섹션 7진행 0 / 8
1왜 배우는가2핵심 원리3코드 예제4응용 변형 예제5자주 하는 실수 (Tip)6연습 문제7정리‹ 이전다음 ›

3. 코드 예제

예제 1: 배송비 계산 — 연산자와 if-else

주문 금액, 회원 등급, 지역에 따라 배송비를 계산합니다. 단축 평가로 null을 방어하고, 얼리 리턴으로 중첩을 줄입니다.

java
public class ShippingFee {
    static int calculate(String grade, int amount, String region) {
        if (region == null || region.isBlank()) {
            return -1;                                  // 유효하지 않은 입력
        }
        if (grade != null && grade.equals("VIP")) {     // null 방어 후 equals
            return 0;
        }
        boolean isRemote = region.equals("제주") || region.equals("울릉");
        int base = amount >= 50_000 ? 0 : 3_000;
        int extra = isRemote ? 3_000 : 0;
        return base + extra;
    }

    public static void main(String[] args) {
        System.out.println(calculate("VIP", 10_000, "서울"));     // 출력: 0
        System.out.println(calculate("GOLD", 60_000, "서울"));    // 출력: 0
        System.out.println(calculate("GOLD", 30_000, "서울"));    // 출력: 3000
        System.out.println(calculate("GOLD", 30_000, "제주"));    // 출력: 6000
        System.out.println(calculate(null, 60_000, "제주"));      // 출력: 3000
        System.out.println(calculate("GOLD", 30_000, null));      // 출력: -1
    }
}

예제 2: 주문 상태별 처리 — switch 표현식과 패턴 매칭

옛 switch와 새 switch를 나란히 비교하고, yield와 패턴 매칭을 보여 줍니다.

java
public class OrderStatus {
    // 옛 방식: break 필수, 변수 밖에 선언
    static String legacy(String status) {
        String msg;
        switch (status) {
            case "PAID":
            case "PREPARING":
                msg = "준비 중";
                break;
            case "SHIPPED":
                msg = "배송 중";
                break;
            case "DELIVERED":
                msg = "배송 완료";
                break;
            default:
                msg = "알 수 없음";
        }
        return msg;
    }

    // 새 방식: 값을 바로 반환, fall-through 없음
    static String modern(String status) {
        return switch (status) {
            case "PAID", "PREPARING" -> "준비 중";
            case "SHIPPED" -> "배송 중";
            case "DELIVERED" -> {
                String base = "배송 완료";
                yield base + " (리뷰 작성 가능)";
            }
            default -> "알 수 없음";
        };
    }

    // 패턴 매칭: 타입과 조건으로 분기
    static String describe(Object event) {
        return switch (event) {
            case Integer qty when qty > 100 -> "대량 주문 " + qty + "개";
            case Integer qty -> "일반 주문 " + qty + "개";
            case String note -> "메모: " + note;
            case null -> "이벤트 없음";
            default -> "기타: " + event.getClass().getSimpleName();
        };
    }

    public static void main(String[] args) {
        System.out.println(legacy("PAID"));           // 출력: 준비 중
        System.out.println(modern("DELIVERED"));      // 출력: 배송 완료 (리뷰 작성 가능)
        System.out.println(modern("CANCELLED"));      // 출력: 알 수 없음
        System.out.println(describe(150));            // 출력: 대량 주문 150개
        System.out.println(describe(3));              // 출력: 일반 주문 3개
        System.out.println(describe("문 앞에 놓아주세요"));  // 출력: 메모: 문 앞에 놓아주세요
        System.out.println(describe(null));           // 출력: 이벤트 없음
        System.out.println(describe(3.5));            // 출력: 기타: Double
    }
}

예제 3: 성적 집계 — for, 향상된 for, continue

점수 배열에서 결시(-1)를 건너뛰고 평균과 최고점을 구합니다. 향상된 for로 읽고, 인덱스가 필요한 곳은 일반 for를 씁니다.

java
public class ScoreStats {
    public static void main(String[] args) {
        int[] scores = {88, -1, 92, 75, -1, 60, 99};
        int sum = 0, count = 0, max = Integer.MIN_VALUE, maxIndex = -1;

        for (int i = 0; i < scores.length; i++) {
            if (scores[i] < 0) {
                continue;                // 결시 건너뛰기
            }
            sum += scores[i];
            count++;
            if (scores[i] > max) {
                max = scores[i];
                maxIndex = i;
            }
        }

        double avg = count == 0 ? 0 : (double) sum / count;
        System.out.printf("응시 %d명, 평균 %.1f, 최고 %d점(%d번)%n", count, avg, max, maxIndex);
        // 출력: 응시 5명, 평균 82.8, 최고 99점(6번)

        // 등급 분포: 향상된 for
        int a = 0, b = 0, c = 0;
        for (int s : scores) {
            if (s < 0) continue;
            if (s >= 90) a++;
            else if (s >= 80) b++;
            else c++;
        }
        System.out.println("A=" + a + " B=" + b + " C이하=" + c);
        // 출력: A=2 B=1 C이하=2
    }
}

예제 4: 로그 파싱 — while과 break

문자열 로그를 줄 단위로 읽다가 "FATAL"을 만나면 즉시 중단합니다. 언제 끝날지 모르는 반복에는 while이 맞습니다.

java
public class LogScanner {
    public static void main(String[] args) {
        String log = """
                INFO  서버 시작
                WARN  디스크 80%
                ERROR DB 연결 재시도
                FATAL DB 연결 실패
                INFO  이 줄은 읽지 않음
                """;
        String[] lines = log.split("\n");

        int idx = 0, errorCount = 0;
        while (idx < lines.length) {
            String line = lines[idx++];
            if (line.startsWith("FATAL")) {
                System.out.println("치명적 오류 발견, 스캔 중단: " + line);
                break;
            }
            if (line.startsWith("ERROR")) {
                errorCount++;
            }
        }
        System.out.println("읽은 줄=" + idx + " ERROR=" + errorCount);
        // 출력: 치명적 오류 발견, 스캔 중단: FATAL DB 연결 실패
        // 출력: 읽은 줄=4 ERROR=1

        // do-while: 최소 1회 실행 — 재시도 로직
        int attempt = 0;
        boolean connected;
        do {
            attempt++;
            connected = attempt >= 3;      // 3번째에 성공한다고 가정
            System.out.println("연결 시도 " + attempt + (connected ? " 성공" : " 실패"));
        } while (!connected && attempt < 5);
        // 출력: 연결 시도 1 실패
        // 출력: 연결 시도 2 실패
        // 출력: 연결 시도 3 성공
    }
}

예제 5: 좌석 찾기 — 중첩 반복문과 라벨

2차원 배열에서 첫 번째 빈 좌석을 찾으면 두 반복문을 한 번에 탈출합니다.

java
public class SeatFinder {
    public static void main(String[] args) {
        boolean[][] seats = {
            {true,  true,  true},
            {true,  false, true},     // (1,1)이 빈 좌석
            {false, false, false},
        };

        int foundRow = -1, foundCol = -1;
        search:
        for (int r = 0; r < seats.length; r++) {
            for (int c = 0; c < seats[r].length; c++) {
                if (!seats[r][c]) {
                    foundRow = r;
                    foundCol = c;
                    break search;          // 바깥 for까지 탈출
                }
            }
        }
        System.out.println("첫 빈 좌석: " + foundRow + "행 " + foundCol + "열");
        // 출력: 첫 빈 좌석: 1행 1열

        // 비트 연산으로 권한 관리
        final int READ = 1, WRITE = 2, DELETE = 4;
        int perm = READ | WRITE;
        System.out.println("쓰기 가능: " + ((perm & WRITE) != 0));     // 출력: 쓰기 가능: true
        System.out.println("삭제 가능: " + ((perm & DELETE) != 0));    // 출력: 삭제 가능: false
        perm |= DELETE;
        perm &= ~WRITE;
        System.out.println(Integer.toBinaryString(perm));               // 출력: 101
    }
}

예제 직접 실행

아래 폴더를 JDK 21 로 컴파일하고 실행합니다.

cd java-src\beginner\02_control_flow
javac -encoding UTF-8 *.java && java Main
코드 예제
  • 예제 1: 배송비 계산 — 연산자와 if-else
  • 예제 2: 주문 상태별 처리 — switch 표현식과 패턴 매칭
  • 예제 3: 성적 집계 — for, 향상된 for, continue
  • 예제 4: 로그 파싱 — while과 break
  • 예제 5: 좌석 찾기 — 중첩 반복문과 라벨
이전 섹션2 핵심 원리3 / 7다음 섹션4 응용 변형 예제