[Java] 객체지향 프로그래밍

Sangho Han·2025년 2월 4일
2

☕️ Java

목록 보기
15/17
post-thumbnail

📝 정리

1. 객체지향 프로그래밍

OOP is A P.I.E

  • Abstraction : 추상화
  • Polymorphism : 다형성
  • Inheritance : 상속
  • Encapsulation : 데이터 은닉과 보호

객체지향 프로그래밍이란?

  • OOP : Object Oriented Programming
  • 객체
    • 주체가 아닌, 주체가 활용하는 것
    • 우리 주변에 있는 모든 것으로, 프로그래밍의 대상이 된다. (ex. 사물, 개념, 논리 ..)
  • 객체지향 프로그래밍
    • 주변의 많은 것들을 객체화를 한 후 프로그래밍을 진행하는 것이다.

    “그렇다면 객체지향은 객체를 많이 만드는 것을 선호하는 것일까?”

    그렇지는 않다. 객체를 너무 많이 만들게 되면 코드가 복잡해지고 유지보수가 어려워질 수가 있다. 또한 메모리 사용량이 증가하고, 객체 간 의존성이 증가하게 되어 결합도가 올라갈 수 있다.
    그렇기에 객체를 무작정 많이 만드는 것이 아니라 객체 간의 관계를 잘 설계하는 것이 중요하다. OOP의 핵심은 객체 개수가 아닌, 객체 간의 역할협력이기 때문이다.

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

  • 신뢰성이 높은 프로그램을 할 수 있다.
  • 유연하고 유지보수에 용이하다.
  • 재사용성이 높다.

2. Class vs Object

현실 세계의 객체, 클래스, 프로그램 객체(Instance, Object)간 관계성

  • 현실 세계의 객체가 갖는 속성과 기능은 추상화 되어 클래스에 정의된다.
  • 이러한 클래스가 구체화 되어 프로그램의 객체(Instance, Object)가 된다.
  • 클래스는 설계도, 객체는 그러한 설계도를 통해 나온 제품이라고 이해할 수 있다.
    • 클래스는 직접 사용할 수 있는 것이 아니다. 그저 객체를 만들기 위한 틀을 제공할 뿐이다.

JVM의 메모리 구조

  • 자바 프로그램이 실행될 때, JVM(Java Virtual Machine)은 메모리를 효율적으로 관리하고 실행할 수 있도록 특정한 메모리 구조를 사용한다.
  • JVM 메모리는 크게 5가지 영역으로 나뉜다. (위 3개만 부가 설명)

JVM 메모리 구조

구분설명
1. 메서드 영역(Method Area, 클래스 영역)클래스(정적 데이터), 인터페이스, 메서드 코드, 상수 풀 등이 저장됨
2. 힙(Heap)객체(인스턴스)와 배열이 저장됨
3. 스택(Stack)메서드 호출 시 지역 변수, 매개변수, 리턴 값 등이 저장됨
4. PC 레지스터(PC Register)현재 실행 중인 JVM 명령어의 주소를 저장
5. 네이티브 메서드 스택(Native Method Stack)C/C++ 같은 네이티브 코드 실행 시 사용

1. 메서드(Method) 영역 (클래스 영역)

  • JVM이 로드한 클래스의 메타정보(클래스명, 변수, 메서드 정보 등)를 저장하는 영역이다.
  • static 변수, 상수 final , 인터페이스 메서드, 클래스의 메서드 코드 등이 들어간다.
  • 프로그램이 종료될 때까지 유지되는 데이터들이 저장된다. (JVM이 종료될 때 해제)
public class Movie {
    static String category = "Film";  // 메서드 영역에 저장 (static 변수)
}

2. 힙(Heap) 영역

  • 객체(Instance), 배열이 저장되는 공간으로 가비지 컬렉터의 관리 대상이다.
  • new 키워드로 생성한 모든 객체가 여기에 저장된다.
  • 프로그램이 실행 중인 동안 동적으로 메모리를 할당받는다.
Movie m1 = new Movie();  // Heap 영역에 저장

3. 스택(Stack) 영역

  • 메서드 호출 시 생성되는 지역 변수, 매개변수, 리턴 값이 저장된다.
  • 각 메서드마다 "스택 프레임"이 생성되고, 메서드가 종료되면 자동으로 제거된다.
  • 힙과 다르게 자동으로 메모리가 해제된다.
public void printMovie(String title) {
    int duration = 120;  // Stack 영역에 저장
}

JVM 메모리 활용 예제

public class MemoryExample {
    static String category = "Film";  // 메서드 영역 (Method Area)

    public static void main(String[] args) {
        int x = 10;  // 스택 (Stack)
        Movie m1 = new Movie();  // 힙 (Heap)
    }
}

3. 변수

자바 변수의 종류와 특징

변수 종류선언 위치특징
인스턴스 변수 (Instance Variable)클래스 내, 메서드 외부객체 생성 시 초기화, 객체가 참조되지 않으면 가비지 컬렉션 대상
클래스 변수 (Static Variable)클래스 내, static 키워드 사용프로그램 시작 시 초기화, 모든 객체가 공유, 클래스가 메모리에 로드될 때 초기화
지역 변수 (Local Variable)메서드, 생성자, 초기화 블록 내부메서드 호출 시 생성, 메서드 종료 시 소멸, 초기화 필요가

가. 인스턴스 변수 (Instance Variable)

  • 선언 위치
    • 클래스 내부, 메서드 외부
  • 특징
    • 객체가 생성될 때 함께 생성된다. 즉, new 키워드로 객체를 만들 때이다.
    • 각 객체마다 독립적인 값을 가진다.
    • 초기화하지 않으면 기본값으로 설정이 된다. (ex. 숫자는 0, 참조형은 null)
    • 가비지 컬렉션에 의해 메모리에서 해제된다.
public class Car {
    String color;  // 인스턴스 변수
    int speed;     // 인스턴스 변수
}

나. 클래스 변수 (Static Variable)

  • 선언 위치
    • 클래스 내부이며, static 키워드를 사용한다.
  • 특징
    • 클래스 로딩 시 한 번만 메모리에 할당된다.
    • 모든 객체가 공유하는 변수이다. (객체와 상관없이 클래스 자체에 속하기 때문)
    • 클래스명으로 직접 접근이 가능하다. ( ex. ClassName.variable)
    • 프로그램 종료 시까지 메모리에 존재한다.
    • 주로 상수나 공용 데이터를 저장할 때 사용한다.
public class Car {
    static int totalCars;  // 클래스 변수 (모든 Car 객체가 공유)

    public Car() {
        totalCars++;  // 객체 생성 시마다 증가
    }
}

다. 지역 변수 (Local Variable)

  • 선언 위치
    • 메서드, 생성자, 초기화 블록 내부이다.
  • 특징
    • 메서드 실행 시 생성, 종료 시 소멸한다. (스택 메모리 사용)
    • 반드시 초기화 후 사용해야 한다. (컴파일 에러 방지)
    • 다른 메서드나 클래스에서 직접 접근이 불가하다.
    • 메모리 관리가 쉽다. (메서드 끝나면 자동 해제되기 때문)
public void drive() {
    int distance = 100;  // 지역 변수
    System.out.println("Driving " + distance + " km");
}

4. 메서드

  • 현실의 객체가 하는 동작을 프로그래밍화 한 것이다.
    • 어떤 작업을 수행하는 명령문의 집합이다.
  • 메서드를 만듦으로써 반복적으로 사용되는 코드의 중복 방지를 할 수 있다.
  • 리턴 타입은 하나만 적용 가능하다.
  • 결과 및 파라미터 전달 시에는 묵시적 형변환이 적용된다.

Variable Arguments

  • 동일 타입의 인자가 몇 개 들어올지 예상할 수 없거나, 가변적일 때 활용한다.
public void addAll(int... nums) {
	int sum = 0;
	for (int num : nums) {
		sum += num;
	}
}

Class 멤버와 Instance 멤버 간의 참조와 호출

  • static member는 항상 메모리에 있기 때문에, 클래스명.멤버명 으로 다른 클래스에서도 어디서든 호출이 가능하다.
  • 그러나 instance member는 객체를 생성하기 전에는 메모리에 없기 때문에, 우선 객체를 생성한 후에 객체(=레퍼런스)를 통해 접근할 수 있다.

메서드 호출 스택

  • 메서드 호출 스택 Call Stack 은, FILO 구조후입선출 방식으로 동작한다. 그 이유는 아래와 같다.
    1. 재귀 호출과 메서드 실행 흐름을 자연스럽게 관리하기 위함이다. 만약 먼저 호출된 메서드가 먼저 종료된다면, 이후 메서드가 정상적으로 작동하지 않을 가능성이 발생한다.

    2. 스택 구조는 메서드 실행이 끝나면 자동으로 메모리를 해제할 수 있다. 때문에 필요하지 않은 메서드의 지역 변수를 빠르게 제거할 수 있어 메모리 누수를 방지한다.

      → FIFO 구조인 힙 메모리를 사용하기 때문에, 큐에서 꺼내 메모리 호출을 한다고 해도 GC가 메모리를 해제해주어야 한다.

      스택(Stack) 메모리힙(Heap) 메모리
      사용 대상메서드 호출, 지역 변수, 매개변수실행 중 유지되어야 하는 객체
      메모리 해제 방식메서드 종료 시 자동 해제GC(가비지 컬렉터)가 해제
      속도빠름 (메모리 접근 속도 높음)상대적으로 느림 (GC가 필요)
      데이터 크기고정 크기 (메서드 실행 중 유지)동적으로 변경 가능
      대표적인 구조스택(Stack)큐(Queue), 리스트(List), 트리(Tree) 등
    3. 멀티스레드 환경에서의 안정적인 실행을 위함이다. 각 스레드는 자신만의 스레드를 갖고 있기 때문에 독립적인 실행이 가능하다.

메서드 오버로딩

  • 동일한 기능을 수행하는 메서드를 추가 작성하는 것으로, 동일한 기능이지만 형태가 조금씩 다른 경우에 활용할 수 있다.
  • 메서드 이름은 동일해야 하며, 파라미터의 개수 or 순서 or 타입이 달라야만 오류가 발생하지 않는다.

5. 생성자

생성자란?

  • 객체가 생성될 때 자동으로 호출되는 특수한 메서드이다.
  • 주된 역할은 객체의 초기화(=필드 값 설정)이며 클래스명과 동일한 이름을 가지고 반환값이 없다.
  • 생성자 또한 메서드와 같이 오버로딩이 가능하다.

기본 생성자

  • 매개변수(=파라미터)가 없는 생성자이다.
  • 클래스에 명시적으로 정의하지 않으면, 컴파일러가 자동으로 기본 생성자를 추가한다.

파라미터 생성자

  • 기본 생성자가 없는 경우, 파라미터 생성자를 정의하면 반드시 값을 전달해야만 객체를 생성할 수 있다.

💡 느낀 점 및 배운 점

  1. JVM의 메모리구조에 대해 학습할 수 있었다. 특히, 스택과 힙 메모리 영역의 차이점에 대해 더 잘 알 수 있었다.

  2. 변수의 종류와 차이점을 확실히 알게 되었다.

  3. 메서드 호출 스택은 LIFO 구조, 즉 스택 방식이라는 사실을 알게 되었다. 또한 그 이유에 대해서도 탐구하며 납득할 수 있었다.

  4. 기본 생성자와 생성자가 없을 시 컴파일러가 자동으로 기본 생성자를 추가한다는 사실을 알 수 있었다.

profile
안녕하세요. 비즈니스를 이해하는 백엔드 개발자, 한상호입니다.

0개의 댓글