☕Java/☕입문편

[Java 10강] 객체지향 기초 심화 - 생성자, this, static, 접근 제어자

itstory(Booho) 2025. 2. 24. 22:58
728x90

2024.12.10 - [☕Java/☕입문편] - [Java 7강] 클래스와 객체 개념

 

[Java 7강] 클래스와 객체 개념

자바 프로그래밍에서 클래스와 객체는 핵심 개념입니다. 이 글에서는 클래스와 객체의 개념, 그리고 이를 활용한 프로그램 작성 방법을 알아보겠습니다.1. 클래스와 객체란?클래스(Class): 데이터

boohoday.com

 

객체지향 프로그래밍 복습

객체지향 프로그래밍(Object-Oriented Programming, OOP)은 자바의 핵심 개념으로, 프로그램을 객체 단위로 설계하고 구현하는 방식을 의미한다. 이를 이해하면 코드의 재사용성과 유지보수성이 높아지고, 대규모 프로젝트에서도 구조적인 개발이 가능해진다.

클래스와 객체의 개념

자바(Java)에서 클래스(Class)와 객체(Object)는 객체지향 프로그래밍(OOP)의 핵심 개념이다. 클래스를 활용하면 코드의 재사용성이 높아지고, 프로그램을 더 체계적으로 관리할 수 있다.

1. 클래스(Class)란?

클래스는 객체를 생성하기 위한 설계도(blueprint)와 같은 역할을 한다. 클래스 내부에는 필드(멤버 변수)와 메서드(동작)가 포함된다.

 

클래스 선언 예제:

class Car {
    String model; // 멤버 변수 (필드)
    int year;

    void displayInfo() { // 메서드
        System.out.println("모델: " + model + ", 연식: " + year);
    }
}

이 클래스는 자동차의 속성(모델명, 연식)과 동작(정보 출력)을 포함하고 있다.

2. 객체(Object)란?

객체는 클래스를 기반으로 생성된 실제 인스턴스(instance)를 의미한다. 하나의 클래스에서 여러 개의 객체를 생성할 수 있다.

객체 생성 예제:

public class Main {
    public static void main(String[] args) {
        Car myCar = new Car(); // 객체 생성
        myCar.model = "Tesla Model S";
        myCar.year = 2023;
        myCar.displayInfo();
    }
}

이 코드에서는 Car 클래스를 기반으로 myCar라는 객체를 생성하고, 해당 객체의 속성을 설정한 후 정보를 출력하고 있다.

3. 클래스와 객체의 관계

  • 클래스: 객체를 만들기 위한 설계도
  • 객체: 클래스에 정의된 내용을 실제 메모리에 할당한 실체
  • 여러 개의 객체 생성 가능: 동일한 클래스를 기반으로 여러 개의 객체를 생성할 수 있다.

예제:

Car car1 = new Car();
Car car2 = new Car();

위 코드에서 car1과 car2는 같은 Car 클래스를 기반으로 생성된 서로 다른 객체이다.

4. 클래스의 주요 구성 요소

클래스는 다음과 같은 요소로 구성된다.

 

구성 요소  설명
필드(Field) 클래스 내부에 선언된 변수(속성)
생성자(Constructor) 객체 생성 시 호출되는 특별한 메서드
메서드(Method) 객체의 동작(기능)을 정의
접근 제어자 public, private, protected 등을 사용하여 접근 범위 지정

5. 객체의 메모리 구조

객체가 생성되면 힙(Heap) 메모리에 저장되며, 참조 변수는 스택(Stack) 메모리에 위치한다.

Car car = new Car();

이 코드를 실행하면 new Car();에 의해 힙 메모리에 객체가 생성되고, car 변수는 해당 객체의 주소를 저장한다.

6. 클래스와 객체의 활용

객체를 사용하면 프로그램을 더욱 구조적으로 만들 수 있으며, 코드를 재사용할 수 있다. 또한 유지보수가 쉬워지며, 대규모 프로젝트에서도 체계적인 개발이 가능해진다.

 

객체 생성과 메모리 할당

자바(Java)에서 객체는 프로그램 실행 중에 동적으로 메모리에 할당되며, 객체의 저장 위치에 따라 다양한 메모리 구조를 가지게 된다. 이를 이해하면 프로그램의 성능 최적화 및 메모리 관리에 유용하다.

1. 객체 생성 과정

객체를 생성하면 JVM(Java Virtual Machine)은 다음과 같은 단계를 거친다.

  1. new 키워드를 사용하여 객체 생성 요청
  2. 힙(Heap) 메모리에 객체 메모리 공간 할당
  3. 생성자(Constructor) 호출하여 객체 초기화
  4. 객체의 주소(참조값)를 스택(Stack) 메모리에 저장

2. 객체 생성 예제

class Person {
    String name;
    int age;
}

public class Main {
    public static void main(String[] args) {
        Person p1 = new Person(); // 객체 생성
        p1.name = "Alice";
        p1.age = 25;

        Person p2 = new Person(); // 또 다른 객체 생성
        p2.name = "Bob";
        p2.age = 30;
    }
}

위 코드에서 new Person();을 실행하면, **힙 메모리(Heap Area)**에 새로운 객체가 생성된다. p1과 p2는 각기 다른 객체를 참조하는 변수다.

3. JVM 메모리 구조

자바의 객체는 다음과 같은 메모리 구조에 의해 관리된다.

 

메모리 영역 설명
메서드 영역(Method Area) 클래스 정보, static 변수, 상수 저장
힙 영역(Heap Area) new 키워드로 생성된 객체 저장
스택 영역(Stack Area) 지역 변수와 참조 변수 저장
PC 레지스터(Program Counter Register) 현재 실행 중인 명령어 주소 저장
네이티브 메서드 스택(Native Method Stack) C/C++ 등 네이티브 코드 실행 시 사용

4. 힙 메모리와 가비지 컬렉션(GC)

자바에서는 개발자가 명시적으로 메모리를 해제하지 않아도, **가비지 컬렉터(Garbage Collector, GC)**가 사용되지 않는 객체를 자동으로 정리한다.

예제 코드:

class Test {
    int value;
}

public class Main {
    public static void main(String[] args) {
        Test t1 = new Test();
        t1 = null; // t1이 가비지 컬렉션 대상이 됨
        System.gc(); // GC 요청 (실행 여부는 JVM이 결정)
    }
}

위 코드에서 t1 = null;이 실행되면, Test 객체는 더 이상 참조되지 않으므로 가비지 컬렉션 대상이 된다.

5. 객체 참조와 메모리 관리

객체 참조를 어떻게 관리하느냐에 따라 메모리 사용 방식이 달라진다.

  • 강한 참조(Strong Reference): 일반적인 객체 참조 방식이며, 명시적으로 null이 될 때까지 메모리에서 해제되지 않는다.
  • 약한 참조(Weak Reference): WeakReference를 활용하면 GC가 메모리가 부족할 때 해당 객체를 우선 제거할 수 있다.
  • Soft Reference: 메모리가 부족하지 않은 한 객체를 유지하지만, 필요 시 GC에 의해 제거될 수 있다.
  • Phantom Reference: 객체가 메모리에서 제거되기 전에 특정 작업을 수행할 수 있도록 지원한다.

메서드와 멤버 변수

자바에서 메서드(Method)와 멤버 변수(Field)는 클래스의 중요한 구성 요소로, 객체의 속성과 동작을 정의한다. 이를 이해하면 객체지향 프로그래밍을 보다 효과적으로 활용할 수 있다.

1. 멤버 변수(Field)

멤버 변수(필드)는 클래스 내부에서 선언되는 변수로, 객체의 속성을 나타낸다.

멤버 변수 예제:

class Car {
    String model; // 문자열로 저장되는 자동차 모델명
    int year; // 자동차의 제작 연도
}

위 코드에서 model과 year는 Car 클래스의 멤버 변수이며, 각각 자동차의 모델명과 제작 연도를 저장한다.

1.1 인스턴스 변수 vs. 클래스 변수 (Static 변수)

  • 인스턴스 변수: 각 객체마다 개별적으로 저장됨 (new 키워드로 생성 시 메모리에 할당됨)
  • 클래스 변수 (Static 변수): 클래스에 속하며, 모든 객체가 공유함 (static 키워드를 사용)

예제:

class Car {
    String model; // 인스턴스 변수
    static int totalCars = 0; // 클래스 변수
    
    Car(String model) {
        this.model = model;
        totalCars++; // 모든 객체가 공유하는 변수 증가
    }
}

2. 메서드(Method)

메서드는 클래스 내부에서 정의된 함수로, 객체의 동작을 담당한다.

메서드 예제:

class Car {
    String model;
    int year;
    
    void displayInfo() { // 메서드 선언
        System.out.println("모델: " + model + ", 연식: " + year);
    }
}

위 코드에서 displayInfo() 메서드는 자동차의 모델과 연식을 출력하는 역할을 한다.

2.1 메서드의 매개변수와 반환값

메서드는 매개변수를 받을 수도 있고, 특정 값을 반환할 수도 있다.

예제:

class Calculator {
    int add(int a, int b) { // 두 정수를 받아 합을 반환
        return a + b;
    }
}

2.2 메서드 오버로딩 (Method Overloading)

같은 이름의 메서드를 매개변수의 개수나 타입을 다르게 정의할 수 있다.

예제:

class MathUtils {
    int multiply(int a, int b) {
        return a * b;
    }
    
    double multiply(double a, double b) { // 같은 이름의 메서드이지만 매개변수 타입이 다름
        return a * b;
    }
}

3. 접근 제어자 (Access Modifiers)

자바의 클래스, 변수, 메서드는 접근 제어자를 사용하여 접근 범위를 지정할 수 있다.

 

접근 제어자  설명
public 모든 클래스에서 접근 가능
private 해당 클래스 내부에서만 접근 가능
protected 같은 패키지 또는 상속받은 클래스에서 접근 가능
default 같은 패키지 내에서만 접근 가능

 

예제:

class Person {
    private String name; // 외부에서 직접 접근 불가능
    
    public void setName(String name) {
        this.name = name; // Setter 메서드 사용
    }
    
    public String getName() {
        return name; // Getter 메서드 사용
    }
}

위 코드에서 name 변수는 private으로 설정되어 있어 직접 접근할 수 없고, setName()과 getName() 메서드를 통해 접근해야 한다.

메서드와 멤버 변수

자바에서 메서드(Method)와 멤버 변수(Field)는 클래스의 중요한 구성 요소로, 객체의 속성과 동작을 정의한다. 이를 이해하면 객체지향 프로그래밍을 보다 효과적으로 활용할 수 있다.

1. 멤버 변수(Field)

멤버 변수(필드)는 클래스 내부에서 선언되는 변수로, 객체의 속성을 나타낸다.

멤버 변수 예제:

class Car {
    String model; // 문자열로 저장되는 자동차 모델명
    int year; // 자동차의 제작 연도
}

위 코드에서 model과 year는 Car 클래스의 멤버 변수이며, 각각 자동차의 모델명과 제작 연도를 저장한다.

1.1 인스턴스 변수 vs. 클래스 변수 (Static 변수)

  • 인스턴스 변수: 각 객체마다 개별적으로 저장됨 (new 키워드로 생성 시 메모리에 할당됨)
  • 클래스 변수 (Static 변수): 클래스에 속하며, 모든 객체가 공유함 (static 키워드를 사용)

예제:

class Car {
    String model; // 인스턴스 변수
    static int totalCars = 0; // 클래스 변수
    
    Car(String model) {
        this.model = model;
        totalCars++; // 모든 객체가 공유하는 변수 증가
    }
}

2. 메서드(Method)

메서드는 클래스 내부에서 정의된 함수로, 객체의 동작을 담당한다.

메서드 예제:

class Car {
    String model;
    int year;
    
    void displayInfo() { // 메서드 선언
        System.out.println("모델: " + model + ", 연식: " + year);
    }
}

위 코드에서 displayInfo() 메서드는 자동차의 모델과 연식을 출력하는 역할을 한다.

반응형

2.1 메서드의 매개변수와 반환값

메서드는 매개변수를 받을 수도 있고, 특정 값을 반환할 수도 있다.

예제:

class Calculator {
    int add(int a, int b) { // 두 정수를 받아 합을 반환
        return a + b;
    }
}

2.2 메서드 오버로딩 (Method Overloading)

같은 이름의 메서드를 매개변수의 개수나 타입을 다르게 정의할 수 있다.

예제:

class MathUtils {
    int multiply(int a, int b) {
        return a * b;
    }
    
    double multiply(double a, double b) { // 같은 이름의 메서드이지만 매개변수 타입이 다름
        return a * b;
    }
}

3. 접근 제어자 (Access Modifiers)

자바의 클래스, 변수, 메서드는 접근 제어자를 사용하여 접근 범위를 지정할 수 있다.

접근 제어자 설명

public 모든 클래스에서 접근 가능
private 해당 클래스 내부에서만 접근 가능
protected 같은 패키지 또는 상속받은 클래스에서 접근 가능
default 같은 패키지 내에서만 접근 가능

예제:

class Person {
    private String name; // 외부에서 직접 접근 불가능
    
    public void setName(String name) {
        this.name = name; // Setter 메서드 사용
    }
    
    public String getName() {
        return name; // Getter 메서드 사용
    }
}

위 코드에서 name 변수는 private으로 설정되어 있어 직접 접근할 수 없고, setName()과 getName() 메서드를 통해 접근해야 한다.

4. 객체지향 프로그래밍의 주요 원칙

객체지향 프로그래밍(OOP)에는 4가지 핵심 원칙이 있다.

  1. 캡슐화(Encapsulation): 데이터 보호를 위해 변수는 private으로 선언하고, public 메서드를 통해 접근한다.
  2. 상속(Inheritance): 기존 클래스를 확장하여 새로운 클래스를 만들고, 코드의 재사용성을 높인다.
  3. 다형성(Polymorphism): 같은 인터페이스나 상위 클래스를 공유하면서 다양한 기능을 구현할 수 있다.
  4. 추상화(Abstraction): 객체의 핵심적인 특성만 모델링하여 불필요한 부분을 숨긴다.

5. 객체지향 프로그래밍의 장점

  • 코드의 재사용성 증가: 클래스를 만들어 여러 객체에서 활용 가능
  • 유지보수 용이: 코드의 구조가 명확하여 수정이 쉬움
  • 대규모 프로젝트에 적합: 모듈화된 개발이 가능하여 팀 단위의 개발에 용이함

6. 객체지향 프로그래밍 활용 예제

객체지향 프로그래밍을 활용한 실제 예제를 살펴보자. 다음 코드는 자동차 클래스를 만들고 여러 개의 객체를 생성하여 정보를 출력하는 예제다.

예제 코드:

class Car {
    String model;
    int year;

    // 생성자를 사용하여 객체 초기화
    Car(String model, int year) {
        this.model = model;
        this.year = year;
    }

    void displayInfo() {
        System.out.println("모델: " + model + ", 연식: " + year);
    }
}

public class Main {
    public static void main(String[] args) {
        Car car1 = new Car("Tesla Model S", 2023);
        Car car2 = new Car("BMW X5", 2022);

        car1.displayInfo();
        car2.displayInfo();
    }
}

위 코드에서 Car 클래스는 생성자를 통해 객체를 초기화하며, displayInfo 메서드를 통해 정보를 출력한다. 이를 통해 객체지향 프로그래밍의 개념을 더욱 효과적으로 이해할 수 있다.

 

728x90
반응형