책읽기

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

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

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

 

4. 오버로딩(overloading)

1) 오버로딩

  • 오버로딩 정의
    • 같은 이름의 메서드를 여러 개 정의하는 것
    • 과적하다라는 뜻으로, 하나의 메서드 이름으로 여러 기능을 구현하기 때문
  • 오버로딩의 조건
    • 메서드 이름이 같아야함
    • 매개변수의 개수 / 타입이 달라야 함
  • 오버로딩이 성립하지 않는 경우
    • 매개변수명만 다른 경우
    • 리턴타입만 다른 경우
  • 오버로딩의 장점
    • 근본적으로 같은 기능이지만 다른 이름을 짓는 경우
    • 메서드 작성자는 이름을 잘 지어야함
    • 메서드 사용자는 여러 이름을 기억해야함

2) 가변인자와 오버로딩

  • 가변인자(varargs) 사용법
    • 타입... 변수명
      - public PrintStream printf(String format, Object... args) { ... }
    • 다른 매개변수가 있을 경우, 가변인자가 가장 마지막에 위치
    • 가변인자 메서드 호출시
      - 인자가 없어도 됨
      - 인자가 배열도 가능
  • 가변인자 원리
    • 가변인자는 내부적으로 배열을 사요
    • 가변인자가 선언된 메서드 호출마다 배열로 새로 생성
      - 비효율적이므로 꼭 필요할 때만 사용
    • 배열 타입 매개변수와 비교
      - 배열 타입 매개변수는 반드시 인자를 지정해줘야함
    • 가변인자를 사용할 때는 오버로딩을 사용하지 않는 것이 좋음

 

5. 생성자(constructor)

1) 생성자란

  • 인스턴스 초기화 메서드
    • 인스턴스 초기화는 인스턴스 변수들을 초기화한다는 의미
    • 인스턴스가 생성될 때 호출
  • 생성자의 조건
    • 생성자의 이름이 클래스의 이름과 같음
    • 리턴값이 없음 (void 생략 가능)
  • 생성자의 실행순서
    • Card c = new Card();
      - 연산자 new에 의해 메모리(heap)에 Card클래스의 인스턴스 생성
      - 생성자 Card()가 수행됨
      - Card인스턴스의 주소가 반환되어 참조변수 c에 저장

2) 기본 생성자 (default constructor)

  • 기본 생성자
    • 컴파일러가 제공하는 생성자
    • 생성자를 정의하지 않고도 인스턴스 생성이 가능했던 이유
    • 아래와 같은 기본 생성자를 추가하여 컴파일
      - 클래스이름() { }
      ex. Card() { }
    • 클래스의 '접근 제어자'가 public인 경우, 기본 생성자로 public 클래스이름() { }이 추가
  • 기본 생성자가 추가되는 조건
    • 정의된 생성자가 하나도 없을 때만 컴파일러가 추가

3) this

  • 오버로딩된 생성자간의 호출 조건
    • 클래스 이름 대신 this로 접근해야함
    • 다른 생성자 호출시 반드시 첫 줄에서만 호출 가능
      - 중간에 호출하면 초기화 작업이 무의미해질 수 있기 때문
    • 지역변수와 구별을 위해 인스턴스 변수는 this로 접근
class Car{
    String color;
    String gearType;
    int door;
    
    Car(String color, String gearType, int door){
        // 인스턴스 변수는 this로 접근
        this.color = color;
        this.gearType = gearType;
        this.door = door;
    }
    
    Car(){
        // 첫째줄
        // this로 접근
        this("white", "auto", 4);
    }
}
  • this
    • 인스턴스 자신을 가리키는 참조변수
    • 참조변수를 통해 인스턴스에 접근하듯이, this로 인스턴스 변수에 접근
    • 그러나 인스턴스멤버만 this 사용 가능
    • 모든 인스턴스 메서드에 this가 지역변수로 숨겨진채 존재

4) 생성자를 이용한 인스턴스 복사

  • 현재 사용중인 인스턴스와 같은 상태의 인스턴스 생성(복사)에 생성자 이용 가능 
    • 같은 클래스의 인스턴스 간의 차이는 인스턴스 변수 뿐이다
    • 따라서, 인스턴스 변수를 복사해주면 두 인스턴스는 같은 상태가 된다
    • 예제
class Car{
    String color;
    String gearType;
    int door;

	Car(String color, String gearType, int door){
        this.color = color;
        this.gearType = gearType;
        this.door = door;
    
    Car(Car c){
       this(c.color, c.gearType, c.door);
   }
}

// Car c1 = new Car("blue", "auto", 2);
// Car c2 = new Car(c1);
  • Object클래스에 정의된 clone메서드로 간단히 인스턴스를 복사할 수 있음
  • 인스턴스 생성시 고려사항
    • 어떤 클래스의 인스턴스를 생성할 것인지
    • 어떤 생성자로 인스턴스를 생성할 것인지

 

6. 변수의 초기화

1) 대제목

  • 초기화가 필요한 변수
    • 멤버 변수
      - 초기화하지 않으면 기본값으로 설정
    • 지역 변수
      - 반드시 사용전에 초기화해야함
  • 멤버 변수의 초기화 방법
    1. 명시적 초기화(explicit initialization)
    2. 생성자(constructor)
    3. 초기화 블럭(initialization block)
  • 명시적 초기화
    • 변수 선언과 동시에 값을 초기화하는 것
    • 지역 변수의 초기화 방법
  • 초기화 블럭
    • 복잡한 멤버변수 초기화에 사용
    • 종류
      1. 클래스 초기화 블럭
        - static { }
        - 클래스가 메모리에 처음 로딩될 때 한 번만 수행
      2. 인스턴스 초기화 블럭
        - { }
        - 인스턴스 생성마다 수행
class InitBlock{
    
    static { /* 클래스 초기화 블럭 */ }
    
    { /* 인스턴스 초기화 블럭 */ }
    
}
  • 생성자 vs 인스턴스 초기화 블럭
    • 인스턴스 변수의 초기화에는 생성자를 사용
    • 모든 생성자에서 공통으로 수행되어야 하는 코드(중복 코드)는 인스턴스 초기화 블럭을 사용
    • 코드의 중복을 제거하여, 재사용성을 높이고 신뢰성을 높여줌
// 생성자의 코드 중복
class Car{
   static int count = 0;
   int searialNo;
   String color;
   String gearType;
   
   Car() {
       // serialNo 저장 중복
       count++;
       this.searialNo = count;
       
       this.color = "white"
       this.gearType = "auto"
   }
   
   Car(String color, String gearType) {
       // serialNo 저장 중복
       count++;
       this.serialNo = count;
       
       this.color = color
       this.gearType = gearType;
   }
}


// 인스턴스 초기화 블럭을 이용한 중복 제거
class Car{
   static int count = 0;
   int searialNo;
   String color;
   String gearType;
   
   {
       count++;
       serialNo = count;
   }
   
   Car() {
       // serialNo 저장 중복
       this.color = "white";
       this.gearType = "auto";
   }
   
   Car(String color, String gearType) {
       this.color = color;
       this.gearType = gearType;
   }
}
  • 멤버변수 초기화 순서
    • 클래스 변수의 초기화
      - 클래스가 처음 로딩될 때 단 한 번 초기화됨 (JVM 종류에 따라, 클래스가 참조될 때 로딩되거나 프로그램 실행시 미리 로딩됨)
      - 따라서, 이미 메모리에 로딩된 클래스는 초기화가 다시 되지 않음
      - 기본값 -> 명시적 초기화 -> 클래스 초기화 블럭
    • 인스턴스 변수의 초기화
      - 인스턴스가 생성될 때마다 초기화됨
      - 기본값 -> 명시적 초기화 -> 인스턴스 초기화 블럭 -> 생성자