1. 프로젝트 생성

2. 패키지 만들기

3. 객체지향의 핵심
객체는 상태(객체가 생성 될 때)와 행위를 거친다. 상태는 행위를 통해서만 변경한다.
1. 추상화 연습 예제 및 해설
package ex00;
class 앨리스 {
private int 목마름; // 상태는 변경 X
public 앨리스(int 목마름) { //객체
this.목마름 = 목마름;
}
void 물마시기() { // heap에 저장되어있다. 의도를 파악하기 좋다. setter로 할 필요 없다.
목마름 = 0;
}
int 목마름확인하기(){ //getter는 꼭 필요하다
return 목마름;
}
}
public class Memo01 {
public static void main(String[] args) {
앨리스 e = new 앨리스(100); // 9번 라인에서 동적할당 (heap), main 앨리스
// 1. 값 변경(행위)
e.물마시기();
// 2. 값 확인
int 목마름 = e.목마름확인하기();
System.out.println(목마름);
}
}
‘앨리스’클래스
- ‘목마름’ 이라는 정수형 변수를 가지고 있고, ‘private’으로 선언되어 클래스 내부에서만 접근 가능하다.
- ‘앨리스(int 목마름)’ 생성자는 ‘앨리스’ 객체를 생성할 때 초기’목마름’ 값을 설정했다.
- ‘물마시기’메소드는 ‘목마름’을 0으로 설정하고 ‘앨리스’ 객체가 물을 마셔 목마름을 해소하는 동작을 의미한다.
- ‘목마름확인하기’ 메소드를 통해 ‘목마름’ 상태를 반환한다.

2진수 10진수로 변환
2진수의 각 자리수를 그 자리의 2의 제곱수와 곱한 다음, 그 결과를 모두 더하는 방식입니다. 예를 들어, 2진수
1101
을 10진수로 변환하는 방법을 설명하겠습니다.
static, heap, stack 변수 정리
1. Static 변수 (정적 변수)
- 메모리 영역: 데이터 영역 (Data Segment) 또는 BSS (Block Started by Symbol) 영역.
- 생명 주기: 프로그램이 시작될 때 할당되어 종료될 때까지 유지됩니다.
- 특징:
- 전역 변수(global variables)와 정적 변수(static variables)는 이 영역에 저장됩니다.
- 프로그램의 전체 실행 기간 동안 메모리에서 계속 유지됩니다.
- 값이 초기화되지 않으면 자동으로
0
으로 초기화됩니다. - 여러 함수 또는 클래스에 걸쳐 공유될 수 있으며, 프로그램 내에서 하나의 복사본만 존재합니다.
- 자바에서 정적 변수는 클래스 로딩 시 생성되고, 프로그램 종료 시 소멸됩니다.
2. Heap 변수 (힙 영역)
- 메모리 영역: 힙 영역.
- 생명 주기: 동적 할당(Dynamic Allocation) 시 할당되며, 프로그래머가 명시적으로 해제할 때까지 유지됩니다.
- 특징:
new
,malloc()
,calloc()
,realloc()
등을 통해 동적으로 할당된 메모리.- 메모리의 크기와 생명 주기가 유연합니다.
- 메모리 관리를 프로그래머가 직접 해야 하며, 해제를 잊어버리면 메모리 누수(memory leak)가 발생할 수 있습니다.
- 자바에서는 가비지 컬렉터(Garbage Collector)가 자동으로 사용되지 않는 메모리를 회수합니다.
- 객체나 배열 같은 크기가 가변적인 데이터들이 주로 힙에 저장됩니다.
3. Stack 변수 (스택 변수)
- 메모리 영역: 스택 영역.
- 생명 주기: 해당 변수가 선언된 블록이 끝날 때까지 유지됩니다.
- 특징:
- 함수 호출 시 할당되는 지역 변수(local variables)와 함수 인자(function arguments)가 저장됩니다.
- 함수가 호출될 때마다 스택 프레임이 생성되고, 함수가 종료되면 스택 프레임이 제거되면서 그 안의 변수들도 함께 소멸됩니다.
- 스택은 LIFO(Last In, First Out) 구조를 따르며, 자동으로 메모리가 관리됩니다.
- 스택 오버플로우(stack overflow) 위험이 있습니다. 이는 함수 호출이 너무 깊거나, 너무 큰 지역 변수를 선언할 때 발생할 수 있습니다.
- 메모리 할당이 매우 빠르고, 정적 할당된 변수가 스택에 저장됩니다.
요약
- Static 변수: 프로그램 실행 전부터 존재하며 프로그램 종료 시 소멸되는 전역적 변수. 초기화하지 않으면 기본값이 할당됩니다.
- Heap 변수: 동적 메모리 할당 영역에 저장되며, 프로그래머가 관리합니다. 객체나 가변 데이터를 저장하는 데 사용됩니다.
- Stack 변수: 함수 호출 시 생성되고, 함수 종료 시 소멸되는 지역 변수와 함수 인자. 메모리 관리가 자동으로 이루어집니다.
4. 상속과 컴퍼지션
package ex00;
abstract class Car {
// car 상태
// car 행위
abstract void run(); // 무효화
}
class tico extends Car {
//오버라이딩!! 부모의 메소드 재정의 한다.
void run() {
System.out.println("티코 달린다.");
}
}
class benz extends Car {
//오버라이딩!! 부모의 메소드 재정의 한다.
void run() {
System.out.println("벤츠 달린다.");
}
}
class Sonata extends Car { // 다형성
// Sonata 상태
// Sonata 행위
//오버라이딩!! 부모의 메소드 재정의 한다
void run() { // 재정의
System.out.println("소나타 달린다");
}
}
class Genesis extends Car { // 다형성
// Genesis 상태
// Genesis 행위
//오버라이딩!! 부모의 메소드 재정의 한다
void run() {
System.out.println("제네시스 달린다");
}
}
public class Memo02 {
static void 레이싱(Car car) {
car.run();
}
public static void main(String[] args) {
Car s1 = new Sonata(); // Sonata, Car
Car g1 = new Genesis(); // Genesis, Car
Car t1 = new tico();
Car b1 = new benz();
레이싱(t1);
레이싱(b1);
}
}
- Car’는 추상 클래스이며, ‘run’이라는 추상 메소드를 정의 하고 있다.
- 여러개의 차들은 ‘Car’를 상속받아 ‘run’ 메소드를 각각 구현 하고 있다.
- ‘Memo2’클래스는 ‘레이싱(Car car)’ ,’ Car’ 타입의 객체를 매개변수로 받아 ‘ run’ 메소드를 호출한다.
- ‘main’메소드는 각자 객체를 생성하고 ‘레이싱()’ 메소드를 통해 각각의 자동타 객체의 ‘run’ 메소드를 호출 하고 있다.
- 이 프로그램은 다형성을 통해 각각의 자동차 객체가 동일한 메소드(’run’)을 호출 할 때, 실제 객체의 타입에 맞는 동작을 수행하도록 구현된 예제다.

추상 클래스(abstract class),
추상 클래스(abstract class)는 객체 지향 프로그래밍(OOP)에서 사용되는 개념으로, 다른 클래스들이 공통적으로 가지는 속성이나 메서드를 정의하는 클래스입니다. 그러나 이 클래스 자체로는 인스턴스(객체)를 생성할 수 없으며, 반드시 이를 상속받아 구현 한 하위 클래스에서 인스턴스를 생성해야 합니다.
주요 특징:
- 추상 메서드(Abstract Method):
- 추상 클래스는 추상 메서드를 포함할 수 있습니다. 추상 메서드는 메서드의 선언만 있고, 구현은 없는 메서드입니다. 즉, 메서드의 이름, 반환형, 매개변수만 정의하고, 실제 동작 내용(구현)은 하위 클래스에서 제공해야 합니다.
- 예를 들어,
draw()
라는 추상 메서드는 "그리기"라는 동작을 의미하지만, 실제로 "어떻게 그릴지"는 하위 클래스가 결정합니다.
- 일반 메서드:
- 추상 클래스는 추상 메서드뿐만 아니라 일반 메서드도 포함할 수 있습니다. 일반 메서드는 하위 클래스에서 그대로 상속받아 사용할 수 있습니다.
- 상속을 통해 구현:
- 추상 클래스는 직접 인스턴스를 생성할 수 없습니다. 반드시 추상 클래스를 상속받은 하위 클래스에서 모든 추상 메서드를 구현한 후에 인스턴스를 생성할 수 있습니다.
- 공통된 특성과 동작 정의:
- 추상 클래스는 여러 하위 클래스가 공통적으로 가져야 할 특성과 동작을 정의합니다. 예를 들어, 다양한 종류의 도형을 그리는 프로그램에서
Shape
라는 추상 클래스를 만들고, 이 클래스를 상속받은Circle
,Rectangle
등의 하위 클래스가 각자의 방식으로draw()
메서드를 구현할 수 있습니다.
오버라이딩(Overriding)
오버라이딩(Overriding)은 객체 지향 프로그래밍에서 자식 클래스가 부모 클래스에서 상속받은 메소드를 재정의하는 기능입니다. 이 방식으로 자식 클래스는 부모 클래스의 메소드를 자신의 필요에 맞게 변경할 수 있습니다.
주요 특징:
- 메소드 재정의(Overriding): 자식 클래스에서 부모 클래스의 메소드와 동일한 이름, 매개변수, 반환 타입을 가진 메소드를 정의하면, 이 메소드는 부모 클래스의 메소드를 오버라이드합니다.
- 동적 바인딩: 메소드 호출 시, 실제 객체의 타입에 따라 호출되는 메소드가 결정됩니다. 즉, 자식 클래스의 인스턴스에서 호출된 메소드는 자식 클래스에서 정의된 메소드가 됩니다.
- 접근 제어자: 자식 클래스의 오버라이딩 메소드는 부모 클래스의 메소드보다 접근 제어가 더 제한적일 수 없습니다. 예를 들어, 부모 클래스의 메소드가
public
이라면, 자식 클래스의 메소드도public
이어야 합니다.
- 예외 처리: 자식 클래스의 오버라이딩 메소드가 던질 수 있는 예외는 부모 클래스의 메소드가 던지는 예외보다 적어야 합니다.
즉 오버라이딩을 통해 자식 클래스는 부모 클래스의 기능을 확장하거나 수정할 수 있으며, 이로 인해 코드의 재사용성과 유연성을 높일 수 있습니다.
Share article