이 글은 "Java의 정석 (남궁 성 지음)"을 읽고 주관적으로 요약한 글입니다.
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에 저장
- Card c = new Card();
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) 대제목
- 초기화가 필요한 변수
- 멤버 변수
- 초기화하지 않으면 기본값으로 설정 - 지역 변수
- 반드시 사용전에 초기화해야함
- 멤버 변수
- 멤버 변수의 초기화 방법
- 명시적 초기화(explicit initialization)
- 생성자(constructor)
- 초기화 블럭(initialization block)
- 명시적 초기화
- 변수 선언과 동시에 값을 초기화하는 것
- 지역 변수의 초기화 방법
- 초기화 블럭
- 복잡한 멤버변수 초기화에 사용
- 종류
- 클래스 초기화 블럭
- static { }
- 클래스가 메모리에 처음 로딩될 때 한 번만 수행 - 인스턴스 초기화 블럭
- { }
- 인스턴스 생성마다 수행
- 클래스 초기화 블럭
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 종류에 따라, 클래스가 참조될 때 로딩되거나 프로그램 실행시 미리 로딩됨)
- 따라서, 이미 메모리에 로딩된 클래스는 초기화가 다시 되지 않음
- 기본값 -> 명시적 초기화 -> 클래스 초기화 블럭 - 인스턴스 변수의 초기화
- 인스턴스가 생성될 때마다 초기화됨
- 기본값 -> 명시적 초기화 -> 인스턴스 초기화 블럭 -> 생성자
- 클래스 변수의 초기화
'책읽기' 카테고리의 다른 글
[파이썬 알고리즘 인터뷰][이진검색] 이진 검색 (0) | 2021.08.12 |
---|---|
[파이썬 알고리즘 인터뷰] 18장 - 이진 검색 (0) | 2021.08.12 |
[Java의 정석][Chapter-6] 객체지향 프로그래밍1 (1/2) (0) | 2021.08.09 |
[파이썬 알고리즘 인터뷰][정렬] 원점에 K번째로 가까운 점 (0) | 2021.08.07 |
[파이썬 알고리즘 인터뷰][정렬] 색 정렬 (0) | 2021.08.07 |