본문 바로가기
Tutorial/Java

자바 클래스와 객체: 개념과 활용

by CLJ 2024. 6. 17.

자바는 전 세계적으로 널리 사용되는 프로그래밍 언어 중 하나로, 다양한 애플리케이션 개발에 활용되고 있습니다. 자바의 핵심 개념 중 하나는 객체 지향 프로그래밍(OOP)이며, 이를 이해하는 것은 자바를 효과적으로 사용하기 위한 필수적인 단계입니다. 이 글에서는 자바의 클래스와 객체의 기본 개념부터 이들의 상호작용에 이르기까지 자세히 살펴보겠습니다.

 

목차

 

1. 클래스 (Class)

 

클래스 정의

 

 클래스는 객체 지향 프로그래밍(OOP)에서 객체를 생성하기 위한 설계도(청사진)입니다. 클래스는 객체의 상태를 나타내는 필드(변수)와 객체의 행동을 나타내는 메서드(함수)를 포함합니다. 클래스는 현실 세계의 개념을 프로그래밍 세계에 반영하여, 코드의 재사용성과 유지보수성을 높이는 데 기여합니다.

 

 선언

 자바에서 클래스를 선언하는 기본 문법은 다음과 같습니다:

public class 클래스이름 {
    // 필드 (Field)
    // 메서드 (Method)
}

 

클래스의 선언은 class 키워드를 사용하며, 클래스 이름은 대문자로 시작하는 명사형으로 짓는 것이 일반적입니다. 클래스 중괄호 안에는 필드와 메서드가 포함됩니다.

 

구성 요소

 

클래스는 주로 필드, 메서드, 생성자로 구성됩니다. 각 구성 요소의 역할과 예제를 살펴보겠습니다.

 

필드 (Field)

 필드는 클래스의 속성을 나타내는 변수입니다. 필드는 객체의 상태를 저장합니다. 예를 들어, 자동차 클래스의 필드는 색상, 모델, 속도 등이 될 수 있습니다.

public class Car {
    String color;  // 색상
    String model;  // 모델
    int speed;     // 속도
}

 

메서드 (Method)

 메서드는 클래스의 행동을 정의하는 함수입니다. 메서드는 객체의 동작을 수행하며, 객체의 필드 값을 읽거나 변경할 수 있습니다. 예를 들어, 자동차 클래스의 메서드는 가속, 감속, 정지 등이 될 수 있습니다.
 

public class Car {
    // 필드
    String color;
    String model;
    int speed;

    // 메서드
    public void accelerate() {
        speed += 10;  // 속도를 10 증가
    }

    public void brake() {
        speed -= 10;  // 속도를 10 감소
    }
}

 

생성자 (Constructor)

 생성자는 객체가 생성될 때 호출되는 특별한 메서드로, 객체의 초기 상태를 설정합니다. 생성자의 이름은 클래스 이름과 동일해야 하며, 반환 타입이 없습니다.
 

public class Car {
    String color;
    String model;
    int speed;

    // 생성자
    public Car(String color, String model, int speed) {
        this.color = color;
        this.model = model;
        this.speed = speed;
    }
}

 

생성자는 클래스의 인스턴스를 만들 때 초기값을 설정하는 데 사용됩니다. 위 예제에서는 color, model, speed 필드를 초기화합니다.

 

사용 예제

 

다음은 위에서 정의한 Car 클래스를 사용하여 객체를 생성하고, 그 필드와 메서드를 사용하는 예제입니다:

public class Main {
    public static void main(String[] args) {
        // Car 객체 생성
        Car myCar = new Car("Red", "Tesla Model S", 0);
        
        // 객체의 필드 값을 출력
        System.out.println("Car color: " + myCar.color);
        System.out.println("Car model: " + myCar.model);
        System.out.println("Car speed: " + myCar.speed);
        
        // 메서드를 호출하여 객체의 상태 변경
        myCar.accelerate();
        
        // 변경된 객체의 필드 값을 출력
        System.out.println("Car speed after acceleration: " + myCar.speed);
    }
}

 

이 예제에서 myCar 객체는 Car 클래스의 인스턴스입니다. 생성자를 통해 초기화된 후, myCar의 필드 값을 출력하고, accelerate 메서드를 호출하여 속도를 증가시킵니다. 이후 변경된 속도를 출력합니다.

 
클래스는 코드의 재사용성을 높이고, 복잡한 시스템을 보다 구조적이고 이해하기 쉽게 만듭니다. 클래스의 설계를 통해 객체 지향 프로그래밍의 이점을 최대한 활용할 수 있으며, 이를 통해 유지보수성과 확장성이 뛰어난 프로그램을 작성할 수 있습니다.
 

2. 객체 (Object)

 

객체의 정의

 객체는 클래스로부터 생성된 실체로, 클래스의 인스턴스라고도 합니다. 객체는 클래스에 정의된 필드(속성)와 메서드(동작)를 가지며, 이들을 통해 구체적인 데이터를 저장하고 특정 기능을 수행합니다. 객체 지향 프로그래밍에서 객체는 현실 세계의 개체를 추상화한 것입니다.

 

 

객체 생성

 

객체는 new 키워드를 사용하여 생성됩니다. 객체를 생성할 때 클래스의 생성자가 호출되어 객체의 초기 상태를 설정합니다. 다음은 객체를 생성하는 예제입니다:

 

Car myCar = new Car("Red", "Tesla Model S", 0);

 

이 코드는 Car 클래스의 새로운 객체를 생성하고, 이를 myCar라는 참조 변수에 할당합니다. 생성자는 color, model, speed 필드를 초기화합니다.

 

객체 사용

 

객체의 필드와 메서드에 접근하기 위해 점(.) 연산자를 사용합니다. 이를 통해 객체의 상태를 읽거나 변경하고, 객체의 동작을 수행할 수 있습니다. 다음은 객체를 사용하는 예제입니다:

 

System.out.println(myCar.color); // 객체의 color 필드 값을 출력
myCar.accelerate(); // 객체의 accelerate 메서드를 호출
System.out.println(myCar.speed); // 객체의 speed 필드 값을 출력

 

객체 출력 예제 코드

 객체를 생성하고, 필드와 메서드를 사용하여 데이터를 출력하는 예제 코드를 살펴보겠습니다:

public class Main {
    public static void main(String[] args) {
        // Car 객체를 생성하고 참조 변수 myCar에 할당
        Car myCar = new Car("Red", "Tesla Model S", 0);
        
        // 객체의 필드 값을 출력
        System.out.println("Car color: " + myCar.color);
        System.out.println("Car model: " + myCar.model);
        System.out.println("Car speed: " + myCar.speed);
        
        // 메서드를 호출하여 객체의 상태 변경
        myCar.accelerate();
        
        // 변경된 객체의 필드 값을 출력
        System.out.println("Car speed after acceleration: " + myCar.speed);
    }
}

 

이 예제에서는 myCar라는 Car 객체를 생성하고, 초기 속성을 설정합니다. System.out.println 메서드를 사용하여 myCar의 필드 값을 출력하고, accelerate 메서드를 호출하여 객체의 속도를 증가시킨 후 다시 출력합니다.

 

객체의 상태와 행동

 객체는 두 가지 주요 특징을 가집니다: 상태와 행동입니다.

  • 상태 (State): 객체의 상태는 필드(Field)에 저장된 값들로 구성됩니다. 예를 들어, myCar 객체의 상태는 색상, 모델, 속도 등의 필드 값으로 정의됩니다.
  • 행동 (Behavior): 객체의 행동은 메서드(Method)로 정의됩니다. 메서드는 객체의 상태를 읽거나 변경하고, 객체가 수행할 수 있는 동작을 나타냅니다. 예를 들어, myCar 객체의 행동은 accelerate, brake 등의 메서드로 정의됩니다.

 

객체의 복제 (Cloning)

 

객체 지향 프로그래밍에서는 객체를 복제(clone)할 수 있습니다. 자바에서 객체를 복제하려면 Cloneable 인터페이스를 구현하고, clone 메서드를 재정의해야 합니다. 다음은 객체 복제의 예제입니다:

 

public class Car implements Cloneable {
    String color;
    String model;
    int speed;

    public Car(String color, String model, int speed) {
        this.color = color;
        this.model = model;
        this.speed = speed;
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}

public class Main {
    public static void main(String[] args) {
        try {
            Car originalCar = new Car("Red", "Tesla Model S", 0);
            Car clonedCar = (Car) originalCar.clone();
            System.out.println("Original car color: " + originalCar.color);
            System.out.println("Cloned car color: " + clonedCar.color);
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
    }
}

 

이 예제에서 Car 클래스는 Cloneable 인터페이스를 구현하고, clone 메서드를 재정의합니다. originalCar 객체를 복제하여 clonedCar 객체를 생성한 후, 두 객체의 상태를 출력합니다.

 

객체의 생명주기 (Object Lifecycle)

 

객체는 생성부터 소멸까지 일정한 생명주기를 갖습니다. 객체의 생명주기는 다음과 같은 단계로 구성됩니다:

 

1. 객체의 생성 (Creation)

 

객체의 생명주기는 객체가 생성될 때 시작됩니다. 객체는 new 키워드를 사용하여 생성되며, 생성자는 객체의 초기 상태를 설정합니다. 예를 들어, 아래 코드는 Car 객체를 생성하는 과정입니다.

 

Car myCar = new Car("Red", "Tesla Model S", 0);

 

이 코드에서는 new Car("Red", "Tesla Model S", 0);를 호출하여 Car 클래스의 새로운 인스턴스를 생성하고, myCar 참조 변수가 이 인스턴스를 가리킵니다.

 

2. 객체의 사용 (Usage)

 

생성된 객체는 참조 변수를 통해 접근하고 사용할 수 있습니다. 객체의 필드에 접근하거나 메서드를 호출하여 객체의 상태를 읽거나 변경할 수 있습니다. 다음은 객체를 사용하는 예제입니다. 이 예제에서는 myCar 객체의 필드 값을 출력하고, accelerate 메서드를 호출하여 객체의 상태를 변경한 후 다시 출력합니다.

System.out.println(myCar.color); // 객체의 color 필드 값을 출력
myCar.accelerate(); // 객체의 accelerate 메서드를 호출
System.out.println(myCar.speed); // 객체의 speed 필드 값을 출력

 

3. 객체의 소멸 (Destruction)

 
객체의 생명주기의 마지막 단계는 소멸입니다. 자바는 가비지 컬렉션(Garbage Collection)이라는 자동 메모리 관리 기법을 사용합니다. 객체가 더 이상 참조되지 않을 때, 가비지 컬렉터가 해당 객체를 메모리에서 해제합니다. 다음은 객체가 소멸되는 과정을 설명합니다:

  • 객체가 더 이상 프로그램에서 사용되지 않고, 참조하는 변수가 없을 때, 즉 객체에 대한 참조가 모두 제거되었을 때 가비지 컬렉터는 이 객체를 가비지로 간주합니다.
  • 가비지 컬렉터는 주기적으로 힙 메모리를 검사하여 더 이상 사용되지 않는 객체를 찾아내고, 이 객체들을 메모리에서 해제합니다.


가비지 컬렉션의 과정

자바의 가비지 컬렉션은 일반적으로 다음과 같은 단계를 거칩니다:

  1. 마킹 (Marking): 가비지 컬렉터는 힙 메모리를 스캔하여 각 객체가 여전히 참조되고 있는지 확인합니다. 참조되고 있는 객체는 '마크'하고, 그렇지 않은 객체는 가비지로 간주합니다.
  2. 삭제 (Deletion): 마킹 단계에서 가비지로 간주된 객체를 힙 메모리에서 삭제합니다.
  3. 압축 (Compaction): 삭제된 객체로 인해 힙 메모리에 조각이 생기면, 이 조각을 제거하여 메모리를 효율적으로 사용하기 위해 남은 객체들을 힙 메모리의 한쪽으로 모읍니다.

 

가비지 컬렉션의 예제

 다음은 객체가 가비지 컬렉션에 의해 소멸되는 예제입니다:

public class Main {
    public static void main(String[] args) {
        Car myCar = new Car("Red", "Tesla Model S", 0);
        myCar = null; // myCar에 대한 참조를 제거하여 가비지 컬렉션 대상이 되도록 함
        
        // 강제로 가비지 컬렉션을 실행 요청 (꼭 필요하지는 않음)
        System.gc();
    }
}

 

이 예제에서는 myCar 참조 변수를 null로 설정하여 Car 객체에 대한 참조를 제거합니다. 이제 이 객체는 가비지 컬렉션의 대상이 됩니다. System.gc() 메서드를 호출하여 가비지 컬렉션을 요청할 수 있지만, 이는 선택사항이며 자바 가상 머신(JVM)이 가비지 컬렉션을 언제 실행할지는 보장되지 않습니다.

 
객체의 생명주기는 생성, 사용, 소멸의 단계를 거칩니다. 자바의 가비지 컬렉터는 더 이상 사용되지 않는 객체를 자동으로 메모리에서 해제하여 메모리 누수를 방지하고, 효율적인 메모리 관리를 가능하게 합니다. 객체의 생명주기를 이해하면 보다 안정적이고 효율적인 프로그램을 작성할 수 있습니다.
 
 

3. 클래스와 객체의 상호작용

 

참조 변수 (Reference Variable)

 
자바에서 객체는 클래스로부터 생성되며, 이 객체는 메모리 상에 존재하게 됩니다. 객체를 사용하기 위해서는 이 객체를 가리키는 참조 변수가 필요합니다. 참조 변수는 객체의 메모리 주소를 저장하고, 이를 통해 객체에 접근하고 조작할 수 있습니다.
 

참조 변수의 개념

 참조 변수는 특정 객체를 참조(Reference)하기 위한 변수입니다. 이는 객체가 저장된 메모리 위치를 가리키며, 이 변수를 통해 객체의 필드와 메서드에 접근할 수 있습니다. 예를 들어, 다음 코드를 보겠습니다.
 

Car myCar = new Car("Red", "Tesla Model S", 0);

 

여기서 myCarCar 클래스의 객체를 참조하는 변수입니다. new Car("Red", "Tesla Model S", 0);는 새로운 Car 객체를 생성하고, myCar는 이 객체를 가리킵니다.

 

참조 변수를 통한 객체 접근

 

참조 변수를 사용하여 객체의 필드와 메서드에 접근할 수 있습니다. 이를 통해 객체의 상태를 읽거나 변경하고, 객체의 동작을 수행할 수 있습니다. 예를 들어, myCar 참조 변수를 사용하여 Car 객체의 필드와 메서드에 접근하는 방법을 살펴보겠습니다:

System.out.println(myCar.color); // 객체의 color 필드에 접근하여 출력
myCar.accelerate(); // 객체의 accelerate 메서드를 호출
System.out.println(myCar.speed); // 객체의 speed 필드에 접근하여 출력

 

이 코드는 myCar 참조 변수를 통해 Car 객체의 colorspeed 필드에 접근하고, accelerate 메서드를 호출하는 예제입니다.

 

참조 변수의 중요성

 참조 변수는 객체 지향 프로그래밍에서 매우 중요한 역할을 합니다. 참조 변수를 통해 다음과 같은 작업을 수행할 수 있습니다:

  • 객체의 속성(필드)에 접근하고 값을 읽거나 수정할 수 있습니다.
  • 객체의 동작(메서드)을 호출하여 특정 기능을 수행할 수 있습니다.
  • 여러 참조 변수가 동일한 객체를 가리킬 수 있으며, 이를 통해 객체를 공유하고 협력할 수 있습니다.

 

예제 코드

 아래는 참조 변수를 사용하여 객체를 생성하고 조작하는 예제 코드입니다.

public class Main {
    public static void main(String[] args) {
        // Car 객체를 생성하고 참조 변수 myCar에 할당
        Car myCar = new Car("Red", "Tesla Model S", 0);
        
        // 객체의 필드 값을 출력
        System.out.println("Car color: " + myCar.color);
        System.out.println("Car model: " + myCar.model);
        System.out.println("Car speed: " + myCar.speed);
        
        // 메서드를 호출하여 객체의 상태 변경
        myCar.accelerate();
        
        // 변경된 객체의 필드 값을 출력
        System.out.println("Car speed after acceleration: " + myCar.speed);
    }
}

 

이 예제에서 myCarCar 객체를 참조하는 변수입니다. myCar를 통해 객체의 필드에 접근하고 값을 출력하며, accelerate 메서드를 호출하여 객체의 상태를 변경한 후 다시 값을 출력합니다. 이를 통해 참조 변수를 사용하여 객체를 어떻게 조작할 수 있는지 알 수 있습니다.

 
 

요약

 
이 글에서는 자바의 기본 개념인 클래스와 객체에 대해 다루었습니다. 클래스는 객체를 생성하기 위한 설계도로, 필드와 메서드를 포함하여 객체의 상태와 행동을 정의합니다. 객체는 클래스로부터 생성된 실체로, 필드와 메서드를 통해 구체적인 데이터를 저장하고 특정 기능을 수행합니다. 클래스를 통해 객체를 생성하고, 참조 변수를 사용하여 객체의 필드와 메서드에 접근할 수 있습니다. 또한, 객체의 복제와 생명주기에 대해 설명하였으며, 객체가 더 이상 필요하지 않을 때 자바의 가비지 컬렉터가 메모리를 회수하는 과정도 다루었습니다. 객체 지향 프로그래밍의 핵심인 클래스와 객체의 개념을 이해하고, 이를 바탕으로 효율적이고 유지보수성이 높은 코드를 작성하는 방법을 배웠습니다.

 

2024.06.16 - [Java] - 자바의 연산자: 산술, 비교, 논리 연산자 이해하기

 

자바의 연산자: 산술, 비교, 논리 연산자 이해하기

프로그래밍 언어에서 연산자는 변수와 값에 대한 연산을 수행하는 데 사용되는 기호입니다. 연산자는 코드 내에서 다양한 작업을 수행하는 데 필수적인 요소로, 산술 연산자부터 비교 연산자,

it-learner.tistory.com