책읽기

[Java의 정석][Chapter-6] 객체지향 프로그래밍1 (1/2)

pythaac 2021. 8. 9. 04:55
이 글은 "Java의 정석 (남궁 성 지음)"을 읽고 주관적으로 요약한 글입니다. 

출처 : http://www.kyobobook.co.kr/product/detailViewKor.laf?mallGb=KOR&ejkGb=KOR&barcode=9788994492032#N

 

1. 객체지향 언어

  • 과학자들의 모의실험을 위해 가상 세계를 컴퓨터 속에 구현하며 객체지향이론 탄생
  • 객체지향이론의 기본 개념
    • 실세계는 사물(객체)로 이루어져있고, 발생하는 모든 사건은 사물간의 상호작용이다
  • 객체지향언어
    • 코드 간의 서로 관계를 지어 유기적으로 프로그램을 구성하는 것이 가능해짐
  • 객체지향언어의 특징
    • 코드의 재사용율이 높음
      - 기존 코드를 이용하여 쉽게 작성
    • 코드 관리가 용이
      - 코드간의 관계를 이용하여 쉽게 코드 변경
    • 신뢰성이 높은 프로그래밍
      - 제어자/메서드로 데이터 보호, 올바른 값 유지 및 코드 불일치로 인한 오작동 방지

 

2. 클래스와 객체

1) 클래스와 인스턴스의 정의

  • 클래스
    • 객체를 정의해놓은 것
    • 객체의 설계도
      - 설계도만 잘 만들어 놓으면 제품을 만드는 일이 쉬워짐
  • 인스턴스(객체)
    • 클래스에 정의된 내용대로 메모리에 생성된 것
    • 클래스 -> (인스턴스화) -> 인스턴스
  • 객체의 구성요소
    • 객체는 속성과 기능의 집합이며, 객체가 가진 속성과 기능을 멤버라고 함
    • 속성
      - 멤버변수
    • 기능
      - 메서드

2) 인스턴스의 사용

  • 인스턴스의 생성과 사용
    • 인스턴스의 생성 (new 연산자)
      - 변수명 = new 클래스명();
      - 연산자 new에 의해 클래스의 인스턴스가 메모리의 빈 공간에 생성
      - 멤버변수는 자료형의 기본값으로 초기화
    • 인스턴스의 사용
      - 참조변수를 통해서만 접근 가능
      - 참조변수의 타입은 인스턴스의 타입과 일치해야함
    • 인스턴스의 제거
      - 참조하는 참조변수가 하나도 없는 인스턴스는 사용할 수 없음
      - 가비지 컬렉터에 의해 자동으로 메모리에서 제거
  • 객체 배열
    • 배열에 객체 주소가 저장됨
    • 즉, 참조변수들을 하나로 묶은 참조변수 배열
    • 객체 배열 선언
      - 클래스명[] 변수명
    • 객체를 생성해서 객체 배열의 각 요소에 저장하는 것이 필수
      - ex) for(int i=0; i<tvArr.length; i++){
                  tvArr[i] = new Tv();
             }

3) 클래스의 장점

  • 클래스를 사용했을 때 장점은 다음 3가지
    1. 데이터와 함수의 결합
    2. 사용자정의 타입
    3. 데이터 유효성
  • 데이터와 함수의 결합
    - 변수 -> 배열 -> 구조체 -> 클래스
    - 데이터는 데이터끼리, 함수는 함수끼리 따로 다루어져왔으나, 데이터와 함수는 관계가 깊음
  • 사용자정의 타입
    - 구조체와 같이 사용자가 타입을 정의할 수 있음
  • 데이터 유효성
    - 데이터에 대한 제약조건을 반영할 수 있음
    - 포멧, 범위, 양수/음수 등등
    - 제어자를 통해 변수를 직접 변경하지 못하고 메서드를 통해 값을 변경하도록 작성
    - 메서드에서 값의 유효성을 조건문으로 점검

 

3. 변수와 메서드

1) 변수

  • 변수의 종류
    • 선언 위치에 따라 다음 3가지로 나뉨
      1. 지역 변수
        - 멤버 변수를 제외한 나머지 변수
      2. 클래스 변수
        - 멤버 변수 중 static이 붙은 것
      3. 인스턴스 변수
        - static이 붙지 않은 것
변수의 종류 선언위치 생성시기
멤버 변수 클래스 변수 클래스 영역 클래스가 메모리에 올라갈 때
인스턴스 변수 인스턴스가 생성되었을 때
지역 변수 클래스 영역 이외의 영역
(메서드, 생성자, 초기화블럭)
변수 선언문이 수행되었을 때
class Variables
{
    int instanceValue;          // 인스턴스 변수
    static int classValue;      // 클래스 변수
    
    void method()
    {
        int localValue = 0;     // 지역 변수
    }
}
  • 인스턴스 변수
    • 생성 시기
      - 클래스의 인스턴스를 생성할 때 만들어짐
    • 사용
      - 사용하기 위해서는 인스턴스를 먼저 생성해야함
    • 인스턴스마다 독립적인 값
      - 인스턴스는 독립적인 저장공간을 가지므로 독립적인 상태(서로 다른 값)을 가짐
  • 클래스 변수
    • 생성 시기
      - 클래스가 메모리에 로딩될 때 생성
      - 클래스가 메모리에 로딩되는 시점 : 참조변수의 선언 / 객체의 생성 등 클래스 정보가 필요할 때
    • 사용
      - 인스턴스를 생성하지 않고 바로 사용 가능
    • 인스턴스 모두가 같은 값
      - 모든 인스턴스가 공통된 저장공간(변수)를 공유
      - 따라서, 모든 인스턴스가 공통적인 값을 유지해야할 때 사용
    • public을 붙일 경우, 전역 변수의 성격을 가지며 같은 프로그램 내에서 어디서나 접근 가능

2) 메서드

  • 메서드 정의
    • 특정 작업을 수행하는 일련의 문장을 하나로 묶은 것
    • 필요한 값으로 원하는 결과만 얻으면 됨
      - 결과를 만드는 세부 과정은 몰라도 됨(블랙박스)
  • 메서드를 사용하는 이유 (함수 사용 이유와 같음)
    • 높은 재사용성
      - 한 번 만들면 계속 재사용이 가능하고 다른 프로그램도 사용 가능
    • 중복 코드 제거
      - 중복된 문장을 줄여 가독성을 높임
    • 프로그램의 구조화
      - 큰 규모의 프로그램에서 여러 메서드를 담아 구조를 단순화 시키는 것이 필수적
      - 먼저 내용이 없는 메서드를 작업단위로 만들고, 하나씩 완성해가는 것도 구조화의 좋은 방법
  • 메서드 선언과 구현
    • 매개변수도 지역 변수다
    • 메서드 이름은 기능을 쉽게 알 수 있는 함축적이면서 의미있는 이름을 지어야 함
  • 메서드의 호출
    • 인자(argument)와 매개변수(parameter)
      - 인자 : 메서드를 호출할 때 괄호()안에 지정해준 값
      - 메서드에 정의된 매개변수의 개수/순서와 일치해야함
    • 메서드의 실행 흐름
      - 같은 클래스 내에서 메서드끼리 서로 호출 가능
      - 그러나 static메서드(클래스 메서드)는 인스턴스 메서드를 호출할 수 없음
  • 매개변수의 유효성 검사
    • 메서드에서 제일 먼저 해야할 일은 매개변수에 대한 유효성 검사
    • '호출하는 쪽에서 알아서 적절한 값을 넘겨주겠지'라는 생각을 절대로 가져서는 안됨
    • 0으로 나누는 것은 금지되어 있기 때문에, 확인하지 않으면 프로그램이 비정상적으로 종료

3) JVM의 메모리 구조

  • 응용 프로그램이 실행될 때 JVM
    • 시스템으로부터 프로그램 수행에 필요한 메모리를 할당 받음
    • 이 메모리를 용도에 따라 영역을 나누어 관리
      1. 메서드 영역 (method area)
      2. 호출 스택 (call stack 또는 execution stack)
      3. 힙 (heap)

  • 메서드 영역 (method area)
    • 프로그램 실행 중 어떤 클래스가 사용되면
    • JVM이 해당 클래스파일을 읽고 분석해서
    • 클래스에 대한 정보(클래스 데이터)를 이곳에 저장
    • 클래스 변수도 포함
  • 힙 (heap)
    • 프로그램 실행 중 모든 인스턴스가 생성되는 공간
    • 인스턴스 변수도 포함
  • 호출 스택 (call stack 또는 execution stack)
    • 메서드의 작업에 필요한 메모리 공간 제공
    • 메서드 호출시
      - 호출된 메서드의 메모리 할당
      - 지역변수(매개변수 포함) / 연산 중간 결과 등을 저장
    • 작업을 마치면 메모리 반환

4) 기본형 변수와 참조형 변수

  • 메서드 호출 시 매개변수
    • 기본형 매개변수는 값이 복사됨
      - 읽기만 가능 (read-only)
    • 참조형 매개변수는 주소가 복사됨
      - 읽기/쓰기 가능 (read/write)
  • 참조형 반환타입
    • 반환타입도 참조형이 될 수 있음
    • 모든 참조형 타입의 값은 '객체의 주소'
    • 호출 결과를 저장하는 변수의 타입과 반환되는 참조변수의 타입이 일치해야함
class Data { int x; }

class ReferenceReturnEx{
    public static void main(String[] args){
        //...
        Data d = new Data();
        Data d2 = copy(d);
        //...
    }
    
    static Data copy(Data d){
        Data tmp = new Data();
        tmp.x = d.x;
        return tmp;
    }
}
  • 재귀호출
    • 메서드 입장에서는 자기자신을 호출하는 것과 다른 메서드를 호출하는 것이 차이가 없음
    • 호출한 메서드(caller)와 관계없이 독립적인 작업 수행
      - 호출된 메서드(callee)는 '값에 의한 호출(call by value)'을 통해
      - 원래의 값이 아닌 복사된 값으로 작업
    • 매개변수 복사 / 종료 후 복귀할 주소저장 등으로 인해 반복문보다 오래걸림
    • 그러나 논리적 간결함으로 오류 발생도 적고 수정도 쉬워 사용
    • 재귀호출 예시
      - 피보나치
      - 매개변수 n의 상한을 12로 유효성 검사가 필요 (약 20억보다 크기 때문)
      - 또한 stackoverflow 주의 -> 재귀호출은 반복문으로 작성하면 됨

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

  • 클래스 메서드
    • 객체를 생성하지 않고도 호출 가능 (클래스 참조변수 선언 or 클래스 이름 사용)
    • 인스턴스 변수를 사용할 수 없음
  • 인스턴스 메서드
    • 인스턴스 변수 / 인스턴스 메서드를 사용하는 작업을 하는 메서드
  • 클래스 설계시 static을 붙이는 경우
    1. 모든 인스턴스에 공통으로 사용되는 변수에는 static을 붙임
    2. 인스턴스 변수를 사용하지 않는 메서드는 static을 붙이는 것을 고려해야 함
  • Math 클래스
    • Math 클래스의 모든 메서드는 클래스 메서드
    • 인스턴스 변수 없이 모두 매개변수로 처리
  • 클래스 멤버의 인스턴스 멤버 호출
    • 아래와 같이 인스턴스 멤버 호출이 가능하긴 하지만, 클래스 변수로 다시 설계가 필요한지 검토가 필요
class MemberCall{
    int instanceValue = 10;
    
    // static int classValue = instanceValue; -> 불가능
    static int classValue = new MemberCall().iv; // 가능
}