반응형

OOP is APIE
객체 지향 프로그래밍(OOP, Object-oriented programming)
- Abstraction(추상화): 현실의 객체를 추상화해서 클래스를 구성한다.
- Polymorphism(다형성): 하나의 객체를 여러 가지 타입(형)으로 참조할 수 있다.
- Inheritance(상속): 부모 클래스의 자산을 물려받아 자식을 정의함으로 코드의 재사용이 가능하다.
- Encapsulation(데이터 은닉과 보호): 데이터를 외부에 직접 노출시키지 않고 메서드를 이용해 보호할 수 있다.
1️⃣ 객체 지향 프로그래밍
- 객체
- 주변의 많은 것들을 객체화해서 프로그래밍하는 것
- 우리 주변의 있는 모든 것으로 프로그래밍의 대상 (사물, 개념, 논리..)
- 객체 지향 프로그래밍
- 주변의 많은 것들을 객체화해서 프로그래밍하는 것
🔹 객체 지향 프로그래밍의 장점
- 블록 형태의 모듈화 된 프로그래밍
- 신뢰성 높은 프로그래밍 가능
- 추가/수정/삭제 용이
- 재사용성 높음
🔹 현실 세계 객체, 클래스, 프로그램의 객체의 관계
- 현실의 객체가 갖는 속성과 기능은 추상화(abstraction) 되어 클래스에 정의된다
- 클래스는 구체화되어 프로그램의 객체(instance, object)가 된다
- 현실의 객체는 우리가 만지고 느낄 수 있는 것
- → 실생활에 구체화 되어있는 내용
- `붕어빵 틀(설계도) = Type 규정`, `붕어빵(제품) = 객체`
- 현실 세계의 객체를 추상화한 결과가 클래스
- 상태 속성: 멤버 변수
- 기능, 행위: 멤버 메서드
- 추상화한 클래스를 구체화한 것이 객체
- 객체들(new로 생성한 것들)이 사는 곳은 메모리
- 객체와 instance의 차이: 메모리에 올라가 있냐 없냐
🔹 프로그램의 클래스와 객체
- 클래스
- 객체를 정의해 놓은 것
- 객체의 설계도, 틀
- 클래스는 직접 사용할 수 없고, 객체를 만들기 위한 틀을 제공할 뿐
- 객체
- 클래스를 데이터 타입으로 메모리에 생성되어 실제로 동작하는 것
🔹 객체 생성과 메모리
JVM의 메모리 구조 (JVM 버전에 따라 달라질 수 있음)
- meta-space
- 클래스 정보 처리
- 타입 정보
- Field 정보
- Method 정보
- 클래스 정보 처리
- stack
- 메서드들의 실행 공간
- thread 별로 별도 관리
- 메서드 호출 시마다 메서드 프레임 적용
- 메서드 프레임에 로컬변수도 쌓이는 구조
- 메서드들의 실행 공간
- heap
- 객체를 저장하기 위한 영역
- thread에 의해 공유
- 객체가 생성되고 G.C에 의해 정리됨
- 상수 풀
- 객체를 저장하기 위한 영역

통상적으로 new로 생성한 것들은 heap에 올라가고 지역 변수들은 stack에 올라감
힙과 달리 왜 스택은 아래에서부터 자랄까?
- 둘 다 아래서부터하면 두 개가 섞이니까 다르게 만든 것임(서로 영역이 겹치지 않기 위해)
- 힙은 double linked list로 만들었음
static은 공유해서 사용함
2️⃣ 변수
🔹 변수의 종류
- 타입에 따른 분류 (기본형, 참조형)
- 선언 위치에 따른 분류 (멤버 변수, 지역 변수)
| 종류 | 선언 위치 | 변수 종류 |
| 멤버 변수 | 클래스 영역 (static keyword) | 클래스 멤버 변수 |
| 클래스 영역 | 인스턴스 멤버 변수 | |
| 지역 변수 | 함수 내부 | 지역 변수 |
| 함수 선언부 | 파라미터 변수 |
🔹 클래스 멤버 변수의 특징
- 선언 위치: 클래스 {} 영역에 선언되어 `static 키워드`를 붙임
public class Person {
static String scientificName = "Homo Sapiens";
}
- 변수의 생성: 클래스 로더에 의해 클래스가 로딩될 때 heap에 클래스 별로 생성
- 개별 객체의 생성과 무관하며 모든 객체가 공유하게 됨(공유 변수라고도 함)
- 변수의 초기화: 타입 별로 default 초기화
- 변수에서의 접근: 객체 생성과 무관하게 클래스 이름(소속)으로 접근
- 객체를 생성하고 객체 이름으로 접근도 가능하나 static에 부합한 표현은 아님
Person p = new Person();
p.scientificName = "객체를 통한 변경";
Person.scientificName = "클래스를 통한 변경";
- 소멸 시점
- 클래스가 언로드될 때 G.C 발생
static 정적(변할 수 있는데 거의 변하지 않음)
지역 변수 & 파라미터 변수
- 선언 위치: 클래스 영역의 {} 이외의 모든 중괄호 안에 선어노디는 변수들
- 메서드, 생성자, 초기화 블록
- 변수의 생성: 선언된 라인이 실행될 때
- 생성 메모리 영역: stack의 메서드 프레임 내부
- 변수의 초기화: 사용하기 전 명시적 초기화 필요
- 변수에서의 접근: 외부에서는 접근이 불가하므로 소속 불필요
- 내부에서는 이름에 바로 접근
- 소멸 시점
- 선언된 영역인 {}을 벗어날 때
3️⃣ 메서드
🔹 메서드 정의
- 현실의 객체가 하는 동작을 프로그래밍화
- 어떤 작업을 수행하는 명령문의 집합
🔹 메서드 작성하는 이유
- 반복적으로 사용되는 코드의 중복 방지
- 코드의 양을 줄일 수 있고 유지 보수가 용이함
🔹 선언부
- 리턴 타입
- 메서드를 호출한 곳에서 반환되는 값의 타입으로 아무것도 리턴하지 않을 경우 void
- 결과를 받을 때 묵시적 형 변환 적용
- 리턴 타입은 하나만 적용 가능
- 메서드 이름은 수행하는 작업을 쉽게 파악하도록 의미 있는 이름 사용
- 파라미터 목록
- 메서드 호출 시점에 넘겨줘야 하는 변수들로 넘겨줄 정보가 없을 경우 생략 가능
- 파라미터 전달 시 묵시적 형 변환 적용
🔹 Variable arguments
- 메서드 선언 시 동일 타입의 인자가 몇 개 들어올지 예상할 수 없는 경우 (또는 가변적)
- 배열 타입을 선언할 수 있으나 → 메서드 호출 전 배열을 생성, 초기화해야 하는 번거로움
- …을 이용해 파라미터를 선언하면 호출 시 넘겨준 값의 개수에 따라 자동으로 배열 생성 및 초기화
🔹 구현부
- 구현부는 중괄호 내에서 처리해야 하는 내용 즉 비즈니스 로직 작성
- 마지막에는 선언된 리턴 타입에 해당하는 값을 return 문장과 함께 반환해야 함
- 값 반환 시에는 묵시적 형 변환 적용
- 리턴 타입이 void여서 반환할 값이 없을 경우 return 문장 생략 가능
- 메서드 수행 도중 return 문장을 만나거나 마지막 문장을 수행하는 경우 메서드는 종료
- 조건문을 이용해서 return 할 경우 모든 조건에서 return 필요
🔹 메서드 호출
- 메서드를 호출할 때는 메서드의 선언부에 맞춰 호출해야 함
- 메서드 이름: 반드시 동일
- 파라미터: 선언된 파라미터의 개수는 반드시 동일, 타입은 promotion 적용 가능
- 메서드 접근
- 멤버 변수와 마찬가지로 static 또는 non static 상태를 구분해서 호출
| 비고 | static member | non static member (instance member) | |
| 소속 | 클래스 | 객체 | |
| 접근 방법 | 같은 클래스 | 바로 호출 | 바로 호출 |
| 다른 클래스 | 클리스_이름.멤버_이름 | 객체 생성 후 객체_이름.멤버_이름 | |
(static: 메모리에 먼저 올라가 있어라)
🔹 class 멤버와 instance 멤버 간의 참조와 호출
- 가장 중요한 것은 호출하려는 멤버가 메모리에 있는가?
- 메모리에 있으면 호출 가능
- 메모리에 없으면 호출 불가 → 먼저 메모리에 로딩 후 사용해야 함
- static member → 언제나 메모리에 있음
- 클래스 로딩 시 자동 등록
- instance member → 객체 생성 전에는 메모리에 없음
- 객체 생성 시 모든 일반 멤버들은 메모리에 생성
- 객체 즉 레퍼런스를 통해서 접근
🔹 메서드 호출 스택
- 스택 (stack)
- First in Last out의 구조
- 메서드 호출 스택
- 각각의 메서드 호출 시마다 메서드 동작을 위한 메모리 상자를 하나씩 할당
- 상자 내부에 메서드를 위한 파라미터 변수 등 로컬 변수 구성
- A 메서드에서 새로운 메서드 B 호출 시 B 실행을 위한 메모리 상자 쌓음
- 언제나 맨 위에 있는 메모리 상자(B)만 활성화
- 이때 A 메서드는 동작이 끝나지 않고 잠시 정지된 상태
- B가 리턴하게 되면 B를 위한 상자가 제거되며 메모리 반납
- 비로소 A가 최상위가 돼서 다시 동작 재개
- 각각의 메서드 호출 시마다 메서드 동작을 위한 메모리 상자를 하나씩 할당

🔹 기본형 변수와 참조형 변수
- 메서드 호출 시 파라미터로 입력된 값을 복사해서 전달
- 자바는 call by value
🔹 메서드 오버로딩
- overloading: 동일한 기능을 수행하는 메서드의 추가 작성
- 일반적으로 메서드 이름은 기능별로 의미 있게 정함
- 동일한 기능을 여러 형태로 정의해야 한다면?
- 장점
- 기억해야 할 메서드가 감소하고 중복 코드에 대한 효율적 관리 기능
메서드 오버로딩 방법
- 메서드 이름은 동일
- 파라미터의 개수 또는 순서, 타입이 달라야 할 것
- 파라미터가 같으면 중복 선언 오류
- 리턴 타입은 의미 없음
4️⃣ 생성자
객체를 생성할 때 호출하는 메서드 비슷한 것
- new 키워드와 함께 호출하는 것 (`Person person1 = new Person()`)
- 일반 멤버 변수의 초기화나 객체 생성 시 실행돼야 하는 작업 정리
작성 규칙
- 메서드와 비슷하나 리턴 타입이 없고 이름은 클래스 이름과 동일
🔹 기본 생성자 (default constructor)
- 기본 생성자의 형태는 파라미터가 없고 구현부가 비어있는 형태
- 생성자 코드가 없으면 컴파일러가 기본 생성자 제공
🔹 파라미터가 있는 생성자
- 생성자의 목적이 일반 멤버 변수의 초기화 → 생성자 호출 시 값을 넘겨줘서 초기화
- 주의! 파라미터가 있는 생성자를 만들면 기본 생성자는 추가되지 않는다.
🔹 this.
- 참조 변수로써 객체 자신을 가리킴
- 참조변수를 통해 객체의 멤버에 접근했던 것처럼 this를 이용해 자신의 멤버에 접근 가능
- this가 작성되어 있는 클래스를 가리킨다
- 용도
- 로컬 변수와 멤버 변수의 이름이 동일할 경우 멤버 변수임을 명시적으로 나타냄
- 명시적으로 멤버임을 나타낼 경우 사용
- this는 객체에 대한 참조
- static 영역에서는 this 사용 불가
- static은 객체 생성과 무관하게 메모리에 올라가 있기 때문
- static 영역에서는 this 사용 불가
🔹 this()
- 메서드와 마찬가지로 생성자도 오버로딩 가능
- 객체 생성 시 필요한 멤버변수만 초기화 진행 → 생성자 별 코드의 중복 발생
- 한 생성자에서 다른 생성자를 호출할 때 사용
- this가 작성되어 있는 클래스의 생성자를 호출한다
- 반드시 첫 줄에서만 호출 가능
🔹 초기화 블록 (initializer)
- 생성자처럼 멤버 변수의 초기화를 목적으로 함
- {}를 이용해 내부에 실행 코드 작성
- 이름이 없으므로 별도로 호출할 수는 없으며 파라미터를 받을 수도 없음
- 초기화 블록의 종류
- 클래스 초기화 블록
- 클래스 멤버 변수의 초기화에 사용
- 클래스 로딩 시 1회 호출
- 인스턴스 초기화 블록
- 인스턴스 멤버 변수의 초기화에 사용
- 생성자 코드 실행보다 먼저 호출됨
- 객체 생성 시마다 1회 호출
- 클래스 초기화 블록
반응형