공공부하자개발 · 영어 학습 노트
자바
중급객체지향과 코어 라이브러리0/9 완료
  • 01상속, 다형성, 오버라이딩
  • 02추상 클래스 vs 인터페이스
  • 03예외 처리
  • 04java.lang 심화
  • 05컬렉션 프레임워크 딥다이브
  • 06메서드 활용 패턴 (중급)
  • 07Object 메서드와 비교
  • 08java.time 실무 날짜 계산
  • 09HTTP 와 JSON 기초
사이트 소개개인정보처리방침연락처
© 2026 공부하자
홈 › 중급 › 06 / 9

메서드 활용 패턴 (중급)

섹션 6진행 0 / 9
1왜 배우는가2핵심 원리3패턴 모음4자주 하는 실수 (Tip)5연습 문제6정리‹ 이전다음 ›

5. 연습 문제

문제 1

Temperature 불변 클래스를 작성하세요. private 생성자와 정적 팩토리 celsius(double), fahrenheit(double)(내부적으로 섭씨로 변환 저장), with-메서드 plus(double deltaC), 그리고 equals/hashCode/toString/compareTo를 구현하세요. toString은 "23.5°C" 형식입니다.

정답 보기
java
import java.util.Objects;
import java.util.TreeSet;
import java.util.List;

public final class Temperature implements Comparable<Temperature> {
    private final double celsius;

    private Temperature(double celsius) { this.celsius = celsius; }

    public static Temperature celsius(double c) { return new Temperature(c); }
    public static Temperature fahrenheit(double f) { return new Temperature((f - 32) * 5 / 9); }

    public Temperature plus(double deltaC) { return new Temperature(celsius + deltaC); }

    @Override public boolean equals(Object o) {
        return o instanceof Temperature t && Double.compare(celsius, t.celsius) == 0;
    }
    @Override public int hashCode() { return Objects.hash(celsius); }
    @Override public String toString() { return String.format("%.1f°C", celsius); }
    @Override public int compareTo(Temperature o) { return Double.compare(celsius, o.celsius); }

    public static void main(String[] args) {
        Temperature a = Temperature.celsius(20);
        Temperature b = Temperature.fahrenheit(68);
        System.out.println(a.equals(b));                       // 출력: true
        System.out.println(a.plus(3.5));                       // 출력: 23.5°C
        System.out.println(a);                                 // 출력: 20.0°C  (원본 불변)
        TreeSet<Temperature> set = new TreeSet<>(List.of(Temperature.celsius(30), a, b));
        System.out.println(set);                               // 출력: [20.0°C, 30.0°C]
    }
}

문제 2

HttpRequest 빌더를 작성하세요. 필수: url. 선택: method(기본 "GET"), 헤더 여러 개(header(k, v) 반복 호출), body(기본 null). build()는 method가 "GET"인데 body가 있으면 IllegalStateException을 던집니다. 완성된 객체는 불변이며 headers()는 수정 불가 Map을 반환해야 합니다.

정답 보기
java
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.Map;

public final class HttpRequest {
    private final String url, method, body;
    private final Map<String, String> headers;

    private HttpRequest(Builder b) {
        this.url = b.url;
        this.method = b.method;
        this.body = b.body;
        this.headers = Collections.unmodifiableMap(new LinkedHashMap<>(b.headers));   // 복사 + 불변
    }

    public static Builder builder(String url) { return new Builder(url); }
    public Map<String, String> headers() { return headers; }

    public static class Builder {
        private final String url;
        private String method = "GET";
        private String body = null;
        private final Map<String, String> headers = new LinkedHashMap<>();

        private Builder(String url) {
            if (url == null || url.isBlank()) throw new IllegalArgumentException("url 필수");
            this.url = url;
        }
        public Builder method(String m) { this.method = m; return this; }
        public Builder header(String k, String v) { headers.put(k, v); return this; }
        public Builder body(String b) { this.body = b; return this; }
        public HttpRequest build() {
            if (method.equals("GET") && body != null) throw new IllegalStateException("GET은 body 불가");
            return new HttpRequest(this);
        }
    }

    @Override public String toString() {
        return method + " " + url + " " + headers + (body == null ? "" : " body=" + body);
    }

    public static void main(String[] args) {
        HttpRequest r = HttpRequest.builder("https://api.shop.com/orders")
                .method("POST").header("Accept", "json").header("Auth", "t0k3n").body("{}").build();
        System.out.println(r);       // 출력: POST https://api.shop.com/orders {Accept=json, Auth=t0k3n} body={}
        try {
            r.headers().put("X", "y");
        } catch (UnsupportedOperationException e) {
            System.out.println("헤더 수정 불가");     // 출력: 헤더 수정 불가
        }
        try {
            HttpRequest.builder("https://x").body("{}").build();
        } catch (IllegalStateException e) {
            System.out.println(e.getMessage());       // 출력: GET은 body 불가
        }
    }
}

문제 3

Inventory 클래스에 Optional<Integer> stockOf(String sku)와 Result<Integer> take(String sku, int qty)를 작성하세요. take는 없는 SKU면 Fail("없는 상품"), 재고 부족이면 Fail("재고 부족"), 성공하면 남은 수량을 Ok로 돌려줍니다. 본문의 Result 타입을 그대로 쓰세요.

정답 보기
java
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;

public class Inventory {
    private final Map<String, Integer> stock = new HashMap<>();

    public Inventory put(String sku, int qty) { stock.put(sku, qty); return this; }

    public Optional<Integer> stockOf(String sku) {
        return Optional.ofNullable(stock.get(sku));
    }

    public Result<Integer> take(String sku, int qty) {
        Integer cur = stock.get(sku);
        if (cur == null) return Result.fail("없는 상품");
        if (cur < qty) return Result.fail("재고 부족");
        stock.put(sku, cur - qty);
        return Result.ok(cur - qty);
    }

    static String show(Result<Integer> r) {
        return switch (r) {
            case Result.Ok<Integer> ok -> "OK 남은 " + ok.value();
            case Result.Fail<Integer> f -> "FAIL " + f.reason();
        };
    }

    public static void main(String[] args) {
        Inventory inv = new Inventory().put("A1", 5);
        System.out.println(inv.stockOf("A1").orElse(0));     // 출력: 5
        System.out.println(inv.stockOf("Z9").orElse(0));     // 출력: 0
        System.out.println(show(inv.take("A1", 3)));         // 출력: OK 남은 2
        System.out.println(show(inv.take("A1", 3)));         // 출력: FAIL 재고 부족
        System.out.println(show(inv.take("Z9", 1)));         // 출력: FAIL 없는 상품
    }
}
연습 문제
  • 문제 1
  • 문제 2
  • 문제 3
이전 섹션4 자주 하는 실수 (Tip)5 / 6다음 섹션6 정리