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

클래스, 객체, 생성자, 오버로딩

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

3. 코드 예제

예제 1: Person — 필드, 생성자, this, toString

회원 정보를 표현하는 가장 기본적인 클래스입니다. 생성자 체이닝과 this의 두 용도를 보여 줍니다.

java
public class Person {
    String name;
    int age;
    String email;

    Person(String name, int age, String email) {
        this.name = name;          // this.name = 필드, name = 매개변수
        this.age = age;
        this.email = email;
    }

    Person(String name, int age) {
        this(name, age, "unknown@example.com");    // 3개짜리 생성자에 위임
    }

    boolean isAdult() {
        return age >= 19;
    }

    Person birthday() {            // 자기 자신 반환 → 체이닝 가능
        this.age++;
        return this;
    }

    @Override
    public String toString() {
        return name + "(" + age + ", " + email + ")";
    }

    public static void main(String[] args) {
        Person p1 = new Person("김민수", 18, "kim@shop.com");
        Person p2 = new Person("이서연", 30);

        System.out.println(p1);                 // 출력: 김민수(18, kim@shop.com)
        System.out.println(p2);                 // 출력: 이서연(30, unknown@example.com)
        System.out.println(p1.isAdult());       // 출력: false
        p1.birthday().birthday();               // 체이닝: 두 살 증가
        System.out.println(p1.age + " " + p1.isAdult());   // 출력: 20 true

        Person alias = p1;                      // 주소 복사
        alias.name = "김민수(수정)";
        System.out.println(p1.name);            // 출력: 김민수(수정)  — 같은 객체
    }
}

예제 2: Calculator — 메서드 오버로딩

같은 이름 add가 매개변수에 따라 다르게 동작합니다. 자동 형변환에 의한 선택도 확인합니다.

java
public class Calculator {
    int add(int a, int b) {
        System.out.print("[int,int] ");
        return a + b;
    }

    double add(double a, double b) {
        System.out.print("[double,double] ");
        return a + b;
    }

    int add(int a, int b, int c) {
        System.out.print("[int,int,int] ");
        return a + b + c;
    }

    String add(String a, String b) {
        System.out.print("[String,String] ");
        return a + b;
    }

    long add(long a, long b) {
        System.out.print("[long,long] ");
        return a + b;
    }

    // 반환 타입만 다른 오버로딩은 불가:
    // double add(int a, int b) { ... }  → 컴파일 오류: method already defined

    public static void main(String[] args) {
        Calculator c = new Calculator();
        System.out.println(c.add(1, 2));            // 출력: [int,int] 3
        System.out.println(c.add(1.5, 2.5));        // 출력: [double,double] 4.0
        System.out.println(c.add(1, 2, 3));         // 출력: [int,int,int] 6
        System.out.println(c.add("1", "2"));        // 출력: [String,String] 12
        System.out.println(c.add(1L, 2L));          // 출력: [long,long] 3
        System.out.println(c.add(1, 2L));           // 출력: [long,long] 3   (int→long 승격)
        System.out.println(c.add(1, 2.0));          // 출력: [double,double] 3.0 (int→double 승격)
    }
}

예제 3: 주문 카운터 — static vs 인스턴스

static 카운터로 총 주문 수와 다음 ID를 관리하고, static 유틸 메서드로 검증합니다.

java
public class OrderCounter {
    static int totalOrders = 0;             // 모든 주문이 공유
    static final double TAX_RATE = 0.1;     // 상수

    long id;                                // 주문마다 다름
    String customer;
    int amount;

    OrderCounter(String customer, int amount) {
        if (!isValidAmount(amount)) {
            throw new IllegalArgumentException("금액은 양수여야 합니다: " + amount);
        }
        totalOrders++;                      // 공유 카운터 증가
        this.id = totalOrders;              // 그 값을 내 ID로
        this.customer = customer;
        this.amount = amount;
    }

    static boolean isValidAmount(int amount) {      // 객체 없이 호출 가능
        return amount > 0;
        // return this.amount > 0;  → 컴파일 오류: static에서 this 불가
    }

    double amountWithTax() {                        // 인스턴스 메서드: this.amount 사용
        return amount * (1 + TAX_RATE);             // static 상수 접근은 OK
    }

    public static void main(String[] args) {
        System.out.println(OrderCounter.isValidAmount(-5));    // 출력: false
        System.out.println("생성 전 총주문: " + OrderCounter.totalOrders);   // 출력: 생성 전 총주문: 0

        OrderCounter a = new OrderCounter("Kim", 10000);
        OrderCounter b = new OrderCounter("Lee", 25000);
        OrderCounter c = new OrderCounter("Park", 3000);

        System.out.println(a.id + " " + b.id + " " + c.id);   // 출력: 1 2 3
        System.out.println("총주문: " + OrderCounter.totalOrders);   // 출력: 총주문: 3
        System.out.println(b.amountWithTax());                 // 출력: 27500.0

        try {
            new OrderCounter("Bad", 0);
        } catch (IllegalArgumentException e) {
            System.out.println(e.getMessage());                // 출력: 금액은 양수여야 합니다: 0
        }
        System.out.println("총주문: " + OrderCounter.totalOrders);   // 출력: 총주문: 3 (실패는 안 셈)
    }
}

예제 4: Call by Value 실험

원시 타입, 참조의 필드 변경, 참조 재대입 세 가지를 한 번에 비교합니다.

java
public class CallByValueDemo {
    static class Wallet {
        int balance;
        Wallet(int balance) { this.balance = balance; }
    }

    static void addTen(int x) {
        x += 10;
        System.out.println("  메서드 안 x=" + x);
    }

    static void deposit(Wallet w, int amount) {
        w.balance += amount;                    // 같은 객체의 필드 변경 → 반영
    }

    static void replace(Wallet w) {
        w = new Wallet(999_999);                // 복사본 w만 새 객체를 가리킴
        System.out.println("  메서드 안 balance=" + w.balance);
    }

    static void swap(Wallet a, Wallet b) {      // 자바에서는 이런 swap이 불가능
        Wallet tmp = a;
        a = b;
        b = tmp;
    }

    public static void main(String[] args) {
        int n = 5;
        addTen(n);                              // 출력:   메서드 안 x=15
        System.out.println("원시 타입 후: " + n);           // 출력: 원시 타입 후: 5

        Wallet w = new Wallet(100);
        deposit(w, 50);
        System.out.println("필드 변경 후: " + w.balance);    // 출력: 필드 변경 후: 150

        replace(w);                             // 출력:   메서드 안 balance=999999
        System.out.println("재대입 후: " + w.balance);      // 출력: 재대입 후: 150

        Wallet x = new Wallet(1), y = new Wallet(2);
        swap(x, y);
        System.out.println("swap 후: " + x.balance + " " + y.balance);   // 출력: swap 후: 1 2
    }
}

예제 5: 재고 관리 — 객체 배열과 메서드 조합

Product 객체를 배열로 관리하며, 객체 배열의 칸이 null일 수 있음과 객체 간 협력을 보여 줍니다.

java
public class Inventory {
    static class Product {
        String code;
        String name;
        int stock;
        int price;

        Product(String code, String name, int stock, int price) {
            this.code = code; this.name = name; this.stock = stock; this.price = price;
        }

        boolean take(int qty) {
            if (qty > stock) return false;
            stock -= qty;
            return true;
        }

        int value() { return stock * price; }

        @Override
        public String toString() { return code + " " + name + " x" + stock; }
    }

    Product[] items = new Product[10];      // null 10칸
    int count = 0;

    void add(Product p) {
        if (count == items.length) {
            System.out.println("창고 가득 참");
            return;
        }
        items[count++] = p;
    }

    Product find(String code) {
        for (int i = 0; i < count; i++) {          // count까지만 (그 뒤는 null)
            if (items[i].code.equals(code)) return items[i];
        }
        return null;
    }

    long totalValue() {
        long sum = 0;
        for (int i = 0; i < count; i++) sum += items[i].value();
        return sum;
    }

    public static void main(String[] args) {
        Inventory inv = new Inventory();
        inv.add(new Product("A1", "노트북", 5, 1_200_000));
        inv.add(new Product("B2", "마우스", 40, 25_000));
        inv.add(new Product("C3", "모니터", 8, 350_000));

        System.out.println("총 재고 가치: " + inv.totalValue());     // 출력: 총 재고 가치: 9800000

        Product p = inv.find("B2");
        System.out.println(p.take(15) + " → " + p);      // 출력: true → B2 마우스 x25
        System.out.println(p.take(30) + " → " + p);      // 출력: false → B2 마우스 x25

        Product missing = inv.find("Z9");
        System.out.println(missing == null ? "없는 상품" : missing.toString());   // 출력: 없는 상품
    }
}

예제 직접 실행

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

cd java-src\beginner\04_class_object
javac -encoding UTF-8 *.java && java Main
코드 예제
  • 예제 1: Person — 필드, 생성자, this, toString
  • 예제 2: Calculator — 메서드 오버로딩
  • 예제 3: 주문 카운터 — static vs 인스턴스
  • 예제 4: Call by Value 실험
  • 예제 5: 재고 관리 — 객체 배열과 메서드 조합
이전 섹션2 핵심 원리3 / 7다음 섹션4 응용 변형 예제