'자바의 정석 3rd Edition'을 공부하며 정리한 내용입니다.
4. 오버로딩(overloading)
4.1 오버로딩이란?
- 메서드도 같은 클래스 내에서 서로 구별될 수 있어야 하기 때문에 각기 다른 이름을 가져야 함
- 자바에서는 한 클래스 내에 이미 사용하려는 이름과 같은 이름을 가진 메서드가 있더라도 매개변수의 개수 또는 타입이 다르면, 같은 이름을 사용해서 메서드를 정의할 수 있음
- 메서드 오버로딩(method overloading): 한 클래스 내에 같은 이름의 메서드를 여러 개 정의하는 것
4.2 오버로딩의 조건
- 메서드 이름이 같아야 함
- 매개변수의 개수 또는 타입이 달라야 함
- 메서드의 이름이 같다 하더라도 매개변수가 다르면 서로 구별될 수 있기 때문에 오버로딩이 가능
- 위의 조건을 만족하지 못하는 메서드는 중복 정의로 간주되어 컴파일 시 에러 발생
- 오버로딩된 메서드들은 매개변수에 의해서만 구별될 수 있으므로 반환 타입은 오버로딩을 구현하는데 아무런 영향을 주지 못함
- 같은 일을 하지만 매개변수를 달리해야하는 경우에 이름은 같고 매개변수를 다르게 하여 오버로딩을 구현
4.4 오버로딩의 장점
- 오버로딩을 통해 같은 기능을 하는 여러 메서드들이 하나의 이름으로 정의될 수 있어 이름을 기억하기 쉽고 이름을 짧게 할 수 있어 오류의 가능성을 줄여줌. 또한 메서드의 리름만 보고도 '메서드의 이름이 같으니, 같은 기능을 하겠구나'라고 예측이 가능
- 메서드의 이름을 절약할 수 있음. 하나의 이름으로 여러 개의 메서드를 정의할 수 있으니, 메서드의 이름을 짓는데 고민을 덜 수 있는 동시에 사용되어야 할 메서드 이름을 다른 메서드의 이름으로 사용할 수 있기 때문
4.5 가변인자(varargs)와 오버로딩
기존에는 메서드의 매개변수 개수가 고정적이었으나 JDK1.5부터 동적으로 지정해줄 수 있게 되었으며, 이 기능을 가변인자(variable arguments)라고 함
타입... 변수명
과 같은 형식으로 선언public PrintStream printf(String format, Object... args) {...}
가변인자 외에도 매개변수가 더 있다면, 가변인자를 매개변수 중 제일 마지막에 선언해야 함
- 그렇지 않으면 컴파일 에러 발생. 가변인자인지 아닌지를 구별할 방법이 없기 때문에 허용하지 않음
여러 문자열을 하나로 결합하여 반환하는
concatenat
메서드// 1. 가변인자를 사용하지 않을 경우 String concatenate(String s1, String s2) {...} String concatenate(String s1, String s2, String s3) {...} String concatenate(String s1, String s2, String s3, String s4) {...} // 2. 가변인자를 사용하는 경우 String concatenate(String... str) {...} // 3. 매개변수의 타입을 배열로 하는 경우 String concatenate(String[] str) {...}
가변인자를 사용하는 경우 인자의 개수를 가변적으로 할 수 있으며 인자가 아예 없어도 되고 배열도 인자가 될 수 있음
가변인자는 내부적으로 배열을 이용하는 것
- 가변인자가 선언된 메서드를 호출할 때마다 배열이 새로 생성됨
매개변수의 타입을 배열로 하면, 반드시 인자를 지정해 줘야하기 때문에, 2번 코드에서처럼 인자를 생략할 수 없음
- null이나 길이가 0인 배열을 인자로 지정해줘야 함
가변인자를 선언한 메서드를 오버로딩하면, 메서드를 호출했을 때 구별되지 못하는 경우가 발생하기 쉽기 때문에 가능하면 가변인자를 사용한 메서드는 오버로딩하지 않는 것이 좋음
5. 생성자(Constructor)
5.1 생성자란?
- 생성자: 인스턴스가 생성될 때 호출되는 '인스턴스 초기화 메서드'
- 인스턴스 변수의 초기화 작업에 주로 사용
- 인스턴스 생성 시에 실행되어야 할 작업을 위해서도 사용됨
- 생성자는 클래스 내에 선언되며, 구조는 메서드와 유사하지만 리턴값이 없다는 점이 다름
- 리턴값이 없다고 해서 생성자 앞에 키워드 void를 사용하지는 않고, 아무 것도 적지 않음
- 생성자도 오버로딩이 가능. 하나의 클래스에 여러 개의 생성자가 존재할 수 있음
생성자의 조건
- 생성자의 이름은 클래스의 이름과 같아야 함
- 생성자는 리턴 값이 없음
생성자 정의
클래스이름(타입 변수명, 타입 변수명, ...) {
// 인스턴스 생성시 수행될 코드,
// 주로 인스턴스 변수의 초기화 코드를 적음
}
class Card {
Card() { // 매개변수가 없는 생성자
...
}
Card(String k, int num) { // 매개변수가 있는 생성자
...
}
}
- 연산자 new는 인스턴스를 생성하는 것이지 생성자 인스턴스를 생성하는 것이 아님
- 생성자는 단순히 인스턴스변수들의 초기화에 사용되는 특별한 메서드일 뿐
Card 클래스의 인스턴스를 생성하는 코드와 수행 단계
Card c = new Card();
- 연산자 new에 의해서 메모리(heap)에 Card 클래스의 인스턴스가 생성됨
- 생성자 Card()가 호출되어 수행됨
- 연산자 new의 결과로, 생성된 Card 인스턴스의 주소가 반환되어 참조변수 c에 저장됨
- 인스턴스를 생성하기 위해 사용해왓던
클래스이름()
이 생성자였던 것 - 인스턴스를 생성할 때는 ㄴ반드시 클래스 내에 정의된 생성자 중의 하나를 선택하여 지정해주어야 함
5.2 기본 생성자(default constructor)
- 모든 클래스에는 반드시 하나 이상의 생성자가 정의되어 있어야 함. 클래스에 생성자를 정의하지 않고도 인스턴스를 생성할 수 있었던 이유는 컴파일러가 제공하는 기본 생성자(default constructor) 덕분
- 컴파일할 때, 소스파일('*.java')의 클래스에 생성자가 하나도 정의되지 않은 경우 컴파일러는 자동적으로
클래스이름() {}
를 기본 생성자로 추가해 컴파일 - 컴파일러가 자동적으로 추가해주는 기본 생성자는 매개변수도 없고 아무런 내용도 없음
- 특별히 인스턴스 초기화 작업이 요구되어지지 않는다면 생성자를 정의하지 않고 컴파일러가 제공하는 기본 생성자를 사용하는 것이 좋음
- 클래스 내에 생성자가 하나도 없을 때만 컴파일러가 자동적으로 기본 생성자를 추가해줌
5.3 매개변수가 있는 생성자
- 매개변수를 선언하여 호출 시 값을 넘겨받아서 인스턴스의 초기화 작업에 사용 가능
- 인스턴스마다 각기 다른 값으로 초기화되어야하는 경우가 많기 때문에 매개변수를 사용한 초기화는 매우 유용
- 클래스를 작성할 때 다양한 생성자를 제공합으로써 인스턴스 생성 후에 별도로 초기화를 하지 않아도 되도록 하는 것이 좋음
5.4 생성자에서 다른 생성자 호출하기 - this(), this
- 같은 클래스의 멤버들 간에 서로 호출할 수 있는 것처럼 생성자 간에도 서로 호출이 가능
조건
- 생성자의 이름으로 클래스 이름 대신 this를 사용
- 한 생성자에서 다른 생성자를 호출할 때는 반드시 첫 줄에서만 호출이 가능
- 생성자에서 다른 생성자를 첫 줄에서만 호출이 가능하도록 한 이유는 생성자 내에서 초기화 작업도중에 다른 생성자를 호출하게 되면, 호출된 다른 생성자 내에서도 멤버변수들의 값을 초기화할 것이므로 다른 생성자를 호출하기 이전의 초기화 작업이 무의미해질 수 있기 때문
- 자세한 내용은 7장에서
- 'this'는 참조변수로 인스턴스 자신을 가리킴. 참조변수를 통해 인스턴스의 멤버에 접근할 수 있는 것처럼, this로 인스턴스 변수에 접근할 수 있는 것
- this를 사용할 수 있는 것은 인스턴스 멤버뿐. static 메서드에서는 인스턴스 멤버들을 사용할 수 없는 것처럼, this도 사용 불가
- static 메서드는 인스턴스를 생성하지 않고도 호출될 수 있으므로 static 메서드가 호출된 시점에 인스턴스가 존재하지 않을 수도 있기 때문
- this: 인스턴스 자신을 가리키는 참조변수
- 인스턴스의 주소가 저장되어 있음
- 모든 인스턴스 메서드에 지역변수로 숨겨진 채로 존재
- this(), this(매개변수): 생성자
- 같은 클래스의 다른 생성자를 호출할 때 사용
5.5 생성자를 이용한 인스턴스의 복사
- 현재 사용하고 있는 인스턴스와 같은 상태를 갖는 인스턴스를 하나 더 만들고자 할 때 생성자를 이용할 수 있음
- 두 인스턴스가 같은 상태를 갖는다는 것은 두 인스턴스의 모든 인스턴스 변수(상태)가 동일한 값을 갖고 있다는 것을 의미
6. 변수의 초기화
6.1 변수의 초기화
- 변수의 초기화: 변수를 선언하고 처음으로 값을 저장하는 것
- 초기화는 경우에 따라 필수적 혹은 선택적이기도 하지만, 가능하면 선언과 동시에 적절한 값으로 초기화하는 것이 좋음
- 멤버변수는 초기화하지 않아도 자동적으로 변수의 자료형에 맞는 기본값으로 초기화가 이루어지므로 초기화하지 않고 상요해도 되지만, 지역변수는 사용하기 전에 반드시 초기화해야 함
멤버변수(클래스변수와 인스턴스변수)와 배열의 초기화는 선택적이지만, 지역변수의 초기화는 필수적
멤버변수의 초기화 방법
- 명시적 초기화(explicit initialization)
- 생성자(constructor)
- 초기화 블럭(initialization block)
- 인스턴스 초기화 블럭: 인스턴스 변수를 초기화하는데 사용
- 클래스 초기화 블럭: 클래스 변수를 초기화하는데 사용
6.2 명시적 초기화(explicit initialization)
- 변수를 선언과 동시에 초기화하는 것
class Car { int door = 4; // 기본형 변수의 초기화 Engine e = new Engine(); // 참조형 변수의 초기화 }
- 명시적 초기화가 간단하고 명료하지만, 복잡한 초기화 작업이 필요할 때는 초기화 블럭(initialization block) 또는 생성자를 사용해야 함
6.3 초기화 블럭(initialization block)
클래스 초기화: 블럭 클래스 변수의 복잡한 초기화에 사용
인스턴스 초기화: 블럭 인스턴스변수의 복잡한 초기화에 사용
- 인스턴스 초기화 블럭은 단순히 클래스 내에 블럭 {}을 만들고 그 안에 코드를 작성하면 됨
- 클래스 초기화 블럭은 인스턴스 초기화 블럭 앞에 static을 덧붙이면 됨
- 초기화 블럭 내에는 조건문, 반복, 예외처리구문 등을 자유롭게 사용 가능
- 초기화 작업이 복잡하여 명시적 초기화만으로는 부녹한 경우 초기화 블럭을 사용
class InitBlock {
static {/* 클래스 초기화블럭*/}
{/* 인스턴스 초기화블럭*/}
}
- 클래스 초기화 블럭은 클래스가 메모리에 처음 로딩될 때 한번만 수행되며, 인스턴스 초기화 블럭은 생성자와 같이 인스턴스를 생성할 때마다 수행됨
- 클래스가 처음 로딩될 때 클래스 변수들이 자동적으로 메모리에 만들어지고, 곧바로 클래스 초기화 블럭이 클래스 변수들을 초기화하게 되는 것
- 생성자보다 인스턴스 초기화 블럭이 먼저 수행됨
- 인스턴스 변수의 초기화는 주로 생성자를 사용하고, 인스턴스 초기화 블럭은 모든 생성자에서 공통으로 수행돼야 하는 코드를 넣는데 사용
// 1. 인스턴스 초기화 블럭 사용 X
Car () {
count++;
serialNo = count;
color = "White";
gearType = "Auto";
}
Car (String color, String gearType) {
count ++;
serialNo = count;
this.color = color;
this.gearType = gearType;
}
// 2. 인스턴스 초기화 블럭 사용 O
{
count ++;
serialNo = count;
}
Car () {
color = "White";
gearType = "Auto";
}
Car (String color, String gearType) {
this.color = color;
this.gearType = gearType;
}
- 코드의 중복을 제거해 코드의 신뢰성을 높여 주고, 오류 발생 가능성을 줄여줌
- 재사용성을 높이고 중복을 제거하는 것이 객체지향프로그래밍이 추구하는 궁극적인 목표
6.4 멤버변수의 초기화 시기와 순서
클래스변수의 초기화시점: 클래스가 처음 로딩될 때 단 한번 초기화됨
인스턴스변수의 초기화시점: 인스턴스가 생성될 때마다 각 인스턴스별로 초기화가 이루어짐
클래스변수의 초기화순서: 기본값 -> 명시적초기화 -> 클래스 초기화 블럭
인스턴스변수의 초기화순서: 기본값 -> 명시적초기화 -> 인스턴스 초기화 블럭 -> 생성자
클래스 변수는 항상 인스턴스 변수보다 먼새 생성되고 초기화됨
Chapter 6 끝!!!
'Book > Java의 정석' 카테고리의 다른 글
[Chapter 8] 예외처리(exception handling) (0) | 2022.04.01 |
---|---|
[Chapter 7] 객체지향 프로그래밍 2 (0) | 2022.04.01 |
[Chapter 6] 객체지향 프로그래밍 1_1 (0) | 2022.04.01 |
[Chapter 5] 배열 (Array) (0) | 2022.04.01 |
[Chapter 4] 조건문과 반복문 (0) | 2022.04.01 |
댓글