프로그래밍 공방

[Java의 정석] Chapter 6. 객체지향 프로그래밍 1 본문

개발/Java

[Java의 정석] Chapter 6. 객체지향 프로그래밍 1

hyosupsong 2021. 1. 3. 22:36

객체지향언어

실제 세계는 사물(객체)로 이루어져 있으며, 발생하는 모든 사건들은 사물간의 상호작용이라는 개념

객체지향언어의 특징

- 코드의 재사용성이 높다
- 코드의 관리가 용이하다 (유지보수가 용이하다)
- 신뢰성이 높은 프로그래밍을 가능하게 한다

클래스, 객체, 인스턴스

클래스 : 객체를 정의 해놓은것 / 데이터와 함수의 결합
객체 : 클래스에 정의되어 있는 내용대로 메모리에 생성된 것
인스턴스 : 클래스로부터 만들어진 객체
인스턴스화 : 클래스를 객체로 만드는 과정

객체와 인스턴스의 차이? 동일한 의미이지만 객체가 조금 더 포괄적인 개념이다.

객체의 구성요소

객체 - 속성(데이터, 멤버변수) / 기능(함수, 메서드)

인스턴스의 생성과 사용

1
2
3
4
public static void main(String[] args) {
    클래스명 변수명;            // 객체를 참조하기 위한 참조변수
    변수명 = new 클래스명();    // 객체를 생성 후, 객체의 주소를 참조변수에 저장
}
cs

인스턴스는 참조변수를 통해서만 다룰 수 있으며, 참조변수의 타입은 인스턴스 타입과 일치해야 한다.

클래스

변수의 종류

인스턴스 변수

독립적인 저장 공간을 가지므로 서로 다른 값을 가질 수 있다.
* 인스턴스마다 고유한 상태를 유지해야 하는 경우 사용

클래스 변수

static을 붙여서 나타낸다. / 모든 인스턴스의 클래스 변수가 공통된 저장공간(변수)를 공유한다.

지역 변수

메서드 내에서만 사용가능하며 메서드가 종료되면 소멸된다.

메서드

어떤 작업을 하기위한 명령문의 집합 (코드의 양도 줄일 수 있고 코드를 한곳에서 관리하면 되서 유지보수가 편하다)

메서드 정리

- 하나의 메서드는 한가지 기능만 수행하도록 작성하는것이 좋다.
- 반복적으로 수행되어야 하는 여러 문장을 하나의 메서드로 정의해두면 좋다.
- 관련된 여러 문장을 하나의 메서드로 만들어 놓는것이 좋다.

리턴 타입 함수 이름( 타입 변수명, 타입 변수명, ...) { // 선언부

                                                                   // 구현부

}

return 문

메서드가 정상적으로 종료되는 경우

- 메서드의 {} 블럭 내의 마지막 문장까지 수행한 경우
- 메서드의 {} 블럭 내의 문장을 수행 중 return 문을 만났을 때

반환값이 없는 경우 return;
반환값이 있는 경우 return 반환값;

* 반환값이 있는 경우, 메서드의 선언부에 정의된 반환타입과 일치하거나 반환 타입으로 자동형변환이 가능한 것이여야 한다.

JVM의 메모리 구조

응용 프로그램이 실행되면 JVM은 시스템으로부터 프로그램을 수행하는데 필요한 메모리를 할당받고 JVM은 이 메모리를 용도에 따라 여러 영역으로 나눠 관리한다.

메서드 영역

프로그램 실행중 어떤 클래스가 사용되면 JVM은 해당 클래스의 클래스 파일(*.class)를 읽어서 분석하고 클래스에 대한 정보(클래스 데이터)를 이곳에 저장한다. 이 때, 그 클래스의 클래스 변수도 이 영역에 함께 생성된다.

힙(Heap)

인스턴스가 생성되는 공간, 프로그램 실행 중 생성되는 인스턴스는 모두 이곳에 생성된다. 즉, 인스턴스 변수들이 생성되는 공간이다.

호출 스택

호출 스택은 메서드의 작업에 필요한 메모리 공간을 제공한다. 메서드가 호출되면, 호출 스택에 호출된 메서드를 위한 메모리가 할당되며 이 메모리는 메서드가 작업을 수행하는 동안 지역 변수(매개 변수 포함)들과 연산의 중간결과들을 저장하는데 사용된다. 그리고 메서드가 작업을 마치면 할당되었던 메모리 공간은 반환되어 지워진다.

* 메서드 내에서 메서드가 호출되면 스택처럼 쌓인다.(호출 스택의 제일 위에 있는 메서드가 실행중인 메서드이다)

기본형 매개변수, 참조형 매개변수의 값 복사

기본형 : 기본형의 값이 복사된다
참조형 : 인스턴스의 주소가 복사된다

클래스 메서드와 인스턴스 메서드

클래스 메서드

메서드 앞에 static이 붙는다
클래스 이름.메서드 이름으로 호출할 수 있다
메서드 중에 인스턴스 변수와 관계없는 메서드를 클래스 메서드(static 메서드)로 생성한다

인스턴스 메서드

객체를 생성해야만 메서드를 호출할 수 있다
인스턴스 변수와 관련된 작업을 하는(인스턴스 변수를 필수로 하는) 메서드

클래스, 인스턴스의 정리

1. 클래스를 설계할 때, 멤버변수 등 모든 인스턴스에 공통적으로 사용해야 하는것에 static을 붙인다.
2. 클래스 변수는 인스턴스를 생성하지 않아도 사용할 수 있다.
3. 클래스 메서드는 인스턴스 변수를 사용할 수 없다.
4. 메서드 내에서 인스턴스 변수를 사용하지 않는다면, static을 붙이는 것을 고려한다.

클래스 멤버와 인스턴스 멤버간의 참조자 호출

인스턴스 멤버가 존재하는 시점에 클래스 멤버는 항상 존재하지만, 클래스 멤버가 조재하는 시점에 인스턴스 멤버가 존재할 수도 있고 존재하지 않을 수도 있다(클래스 멤버가 인스턴스 멤버를 참조 or 호출하는 경우)

메서드 오버로딩

한 클래스 내에 같은 이름의 메서드를 여러개 정의하는 것

오버로딩의 성립 조건

1. 메서드 이름이 같아야 한다.
2. 매개변수의 개수 또는 타입이 달라야 한다.
3. 매개변수는 같고 리턴 타입이 다른 경우는 오버로딩이 성립되지 않는다.

생성자

인스턴스가 생성될 때 호출되는 인스턴스 초기화 메서드 (클래스 내에 선언, 리턴값이 없다 void도 붙지 않는다)

1
2
3
4
5
6
7
8
9
10
11
class Song {
 
    Song() {
        //...
    }
 
    Song(String name, int k) {
        //...
    }
 
}
cs

* 연산자 new가 인스턴스를 생성하는 것이지 생성자가 인스턴스를 생성하는 것은 아니다

인스턴스 생성 과정

Song song = new Song( );

1. 연산자 new에 의해 메모리(heap)에 Song 클래스의 인스턴스가 생성된다.
2. 생성자 Song( )이 호출되어 수행된다.
3. 연산자 new의 결과로 생성된 Song 인스턴스의 주소가 반환되어 song에 저장된다.

기본 생성자(Default Constructor)

모든 클래스는 반드시 하나 이상의 생성자가 정의되어 있어야 한다.

만약 아무 생성자도 생성하지 않으면 컴파일러에서 제공하는 기본 생성자를 사용한다.

컴파일 할때, 소스파일(*.java)의 클래스에 생성자가 하나도 정의되지 않은 경우 컴파일러는 자동으로 아래와 같은 기본 생성자를 추가하여 컴파일된다

Song( ) { }

만약 하나라도 정의한 생성자가 있다면 기본 생성자는 추가되지 않는다

this, this( )

아래 두 조건을 만족하면 생성자간에도 서로 호출이 가능하다

- 생성자의 이름 대신 this를 사용한다
- 한 생성자에서 다른 생성자를 호출할 때는 반드시 첫 줄에서만 호출이 가능하다

1
2
3
4
5
6
7
8
9
10
11
12
class Song {
    
    Song(String name) {
        //...
    }
    
    Song() {
        this("");
        //...
    }
    
}
cs

this

인스턴스 자신을 가리키는 참조 변수, 인스턴스의 주소가 저장되어 있다.
모든 인스턴스 메서드에 지역 변수로 숨겨진 채 존재한다.
아래 예시처럼 생성자를 이용하여 인스턴스를 복사할 수 있다

1
2
3
4
5
6
7
8
9
class Song {
    
    String name;
 
    Song(Song song) {
        this.name = song.name;
    }
    
}
cs

* 복사된 인스턴스는 기존 인스턴스와 같은 값들을 갖지만 서로 독립적인 메모리 공간에 존재하므로 각자 값의 변화에 영향을 받지 않는다.

변수의 초기화

변수를 선언하고 처음으로 값을 저장하는 것

멤버변수는 초기화 하지 않아도 자동적으로 변수의 자료형에 맞는 기본값으로 초기화가 이루어지므로 초기화하지 않고 사용해도 되지만 지역변수는 사용하기 전에 반드시 초기화를 해야한다.

멤버변수(클래스, 인스턴스) : 초기화 선택( 기본값 초기화)

지역 변수 : 반드시 초기화 필수

멤버변수의 초기화 방법

1. 명시적 초기화(Explicit Initialization) : 선언과 동시에 초기화 하는 것
2. 생성자(Constructor)
3. 초기화 블럭(Initialization Block) - 복잡한 초기화 작업에 사용된다
   - 인스턴스 초기화 블럭(인스턴스 변수를 초기화 하는데 사용)
   - 클래스 초기화 블럭(클래스 변수를 초기화 하는데 사용)

1
2
3
4
5
6
7
8
9
10
11
class Song {
    
    static {
        // 클래스가 메모리에 처음 로딩될 때 한번만 수행
    }
 
    {
        // 인스턴스가 생성될 때마다 수행(생성자보다 먼저 수행된다)
    }
    
}
cs

* 초기화 블럭 내에서는 조건문, 반복문 예외처리 구문 등을 자유롭게 사용할 수 있다.

변수별 초기화 정리

클래스 변수

초기화 시점 : 클래스가 처음 로딩될 때
초기화 순서 : 기본값 -> 명시적 초기화 -> 클래스 초기화 블럭

인스턴스 변수

초기화 시점 : 인스턴스가 생성될 때마다 각 인스턴스 별로 초기화
초기화 순서 :기본값 -> 명시적 초기화 -> 인스턴스 초기화 블럭 -> 생성자