공부/Java

[Java-06] 객체지향프로그래밍 - 오버로딩, 생성자

줭♪(´▽`) 2021. 2. 18. 11:10

1. 오버로딩(Overloading)

1) 오버로딩(overloading)이란?

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

- 메서드 오버로딩(method overloading)이라고도 함

 

2) 오버로딩의 조건

 

1. 메서드 이름이 같아야 함
2. 매개변수의 개수 또는 타입이 달라야 함
(반환 타입은 오버로딩을 구현하는데 아무런 영향을 주지 않음)

 

 

3) 오버로딩의 예

 

[ex1] PrintStream 클래스의 10개의 오버로딩된 println 메서드

 

void println()
void println(boolean x)
void println(char x)
void println(char[] x)
void println(double x)
void println(float x)
void println(int x)
void println(long x)
void println(Object x)
void println(String x)

 

[ex2]

 

int add(int a, int b) {...}
long add(long a, long b) {...}
long add(int[] a) {...}

 

 

4) 오버로딩의 장점

- 같은 기능을 하는 메서드를 서로 이름을 구분해서 짓는 불편함을 해소하고 오류를 줄여줌

- 메서드의 이름을 절약할 수 있음

 

5) 가변인자(varargs)와 오버로딩

- 기존에는 메서드의 매개변수 개수가 고정적이었으나 JDK1.5부터 동적으로 지정해줄 수 있음

- 가변인자(variable arguments) : 동적으로 지정된 매개변수

- '타입... 변수명' 형식으로 선언

- 가변인자 외에도 매개변수가 있다면 가변인자를 제일 마지막에 선언해야 함

- 가변인자에 배열이 들어가도 됨

- 가변인자가 선언된 메서드를 호출할 때마다 배열이 새로 생성되어 비효율적이므로 꼭 필요한 경우에만 사용

 

// 올바른 예
public PrintStream printf(String format, Object... args) { ... } // (O)

// 틀린 예 (가변인자는 맨 마지막에 위치해야 함)
public PrintStream printf(Object... args, String format) { ... } // (X)

 

2. 생성자(Constructor)

1) 생성자란?

- 인스턴스가 생성될 때 호출되는 '인스턴스 초기화 메서드'

- 인스턴스 변수 초기화 및 인스턴스 생성 시 실행되어야 할 작업에 사용

- 메서드처럼 클래스 내에 선언되며, 리턴값이 없음

 

1. 생성자의 이름은 클래스의 이름과 같아야 함
2. 생성자는 리턴 값이 없음

 

클래스이름(타입 변수명, 타입 변수명, ...) {

}

 

- 하나의 클래스에 여러 개의 생성자가 존재할 수 있음 (오버로딩)

class Card {
    // 1. 매개변수가 없는 생성자
    Card() {
    	...
    }
    
    // 2. 매개변수가 있는 생성자
    Card(String k, int num) {
    	...
    }
}

 

- 연산자 new가 인스턴스를 생성함 (O)

  생성자가 인스턴스를 생성함 (X)

- 인스턴스를 생성할 때는 반드시 클래스 내에 정의된 생성자 중 하나를 지정해줘야 함

 

Card c = new Card();

1. 연산자 new에 의해서 메모리(heap)에 Card클래스의 인스턴스가 생성됨
2. 생성자 Card()가 호출되어 수행됨
3. 연산자 new의 결과로, 생성된 Card인스턴스의 주소가 반환되어 참조변수 c에 저장됨

 

 

2) 기본 생성자(default constructor)

- 컴파일러는 소스파일(*.java)의 클래스에 생성자가 하나도 정의되지 않은 경우 자동적으로 기본 생성자를 추가하여 컴파일함

Card() { }

 

- 하지만 클래스에 생성자가 하나라도 정의된 경우 기본 생성자는 자동으로 추가되지 않음

class Card {
    int value;
    
    Card(int x) {
    	value = x;
    }
}

class CardEx {
    public static void main(String[] args) {
    	Card c = new Card();	// 컴파일 에러 발생, 기본 생성자가 없음
        Card c = new Card(3);
    }
}

 

3) 매개변수가 있는 생성자

- 매개변수가 있는 생성자를 사용하여 초기화를 간결하고 직관적으로 할 수 있음

class Car {
    String color;
    Stirng type;
    int door;
    
    Car() {}
    Car(String c, String t, int d){
    	color = c;
        type = t;
        door = d;
    }
}

class CarEx {
    public static void main(String[] args) {
    	// 일일이 초기화하는 경우
        Car c1 = new Car();
        c1.color = "white";
        c1.type = "auto";
        c1.door = 4;
        
        // 매개변수가 있는 생성자로 초기화하는 경우
        Car c2 = new Car("white","auto",4);
    }
}
        
        

 

4) 생성자에서 다른 생성자 호출하기 - this(), this

- 같은 클래스의 생성자 간에도 서로 호출할 수 있음

 

조건

1. 생성자의 이름으로 클래스이름 대신 this를 사용
2. 한 생성자에서 다른 생성자를 호출할 때는 반드시 첫 줄에서만 호출 가능

 

class Car {
    String color;
    Stirng type;
    int door;
    
    Car() {
    	this("white","auto",4);
    }
    Car(String c) {
    	this(c, "auto", 4);
    }
    Car(String c, String t, int d){
    	color = c;
        type = t;
        door = d;
    }
}

class CarEx {
    public static void main(String[] args) {
        Car c1 = new Car();	// "white","auto",4
        Car c2 = new Car("blue"); // "blue","auto",4
        Car c3 = new Car("yello", "manual", 2); // "yello","manual",2
        Car c4 = new Car("red", 3); // 컴파일 오류, 일치하는 생성자가 없음
    }
}
        
        

 

- 매개변수 이름과 인스턴스변수 이름이 동일할 경우에는 this를 사용하여 구분해줌

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

 

this
- 인스턴스 자신을 가리키는 참조변수
- 인스턴스의 주소가 저장되어 있음
- 모든 인스턴스메서드에 지역변수로 숨겨진 채 존재

this(), this(매개변수)
- 생성자
- 같은 클래스의 다른 생성자를 호출할 때 사용

 

 

3. 변수의 초기화

1) 변수의 초기화

- 멤버변수 : 초기화를 하지 않아도 자동적으로 변수의 자료형에 맞는 기본값으로 초기화

- 지역변수 : 사용하기 전에 반드시 초기화해야 함

- 멤버변수의 초기화 방법 : 명시적 초기화, 생성자, 초기화 블럭

 

2) 명시적 초기화(explicit initialization)

- 변수를 선언과 동시에 초기화하는 것

class Car {
    int door = 4;
    Engine e = new Engine();
}

 

 

3) 초기화 블럭(initialization block)

- 클래스 초기화 블럭 : 클래스변수의 복잡한 초기화에 사용

- 인스턴스 초기화 블럭 : 인스턴스변수의 복잡한 초기화에 사용

 

순서 주의

 

멤버변수의 초기화 시기와 순서

1. 초기화 시점
1) 클래스변수 : 클래스가 처음 로딩될 때 단 한번 초기화
2) 인스턴스변수 : 인스턴스가 생성될 때마다 각 인스턴스별로 초기화

2. 초기화순서
1) 클래스변수 : 기본값 -> 명시적초기화 -> 클래스 초기화 블럭
2) 인스턴스변수 : 기본값 -> 명시적초기화 -> 인스턴스 초기화 블럭 -> 생성자

 

 

 

 

 

 

참고 - Java의 정석 3rd Edition (저자 : 남궁성, 출판 : 도우출판)