▶ 오버로딩이란?
메서드도 변수와 마찬가지로 같은 클래스 내에서 서로 구별될 수 있어야 하기 때문에 각기 다른 이름을 가져야 한다. 그러나 자바에서는 한 클래스 내에 이미 사용하려는 이름과 같은 이름을 가진 메서드가 있더라도 매개변수의 개수 또는 타입이 다르면, 같은 이름을 사용해서 메서드를 정의할 수 있다.
이처럼, 한 클래스 내에 같은 이름의 메서드를 여러 개 정의하는 것을 '메서드 오버로딩(method overloading)' 또는 간단히 '오버로딩(overloading)'이라 한다.
▶ 오버로딩의 조건
같은 이름의 메서드를 정의한다고 해서 무조건 오버로딩인 것은 아니다. 오버로딩이 성립하기 위해서는 다음과 같은 조건을 만족해야한다.
- 메서드 이름이 같아야한다.
- 매개변수의 개수 또는 타입이 달라야한다.
위의 조건을 만족시키지 못하는 메서드는 중복 정의로 간주되어 컴파일 시에 에러가 발생한다. 그리고 오버로딩된 메서드들은 매개변수에 의해서만 구별될 수 있으므로 반환 타입은 오버로딩을 구현하는데 아무런 영향을 주지 못한다는 것에 주의해야한다.
▶ 오버로딩의 장점
만일 메서드도 변수처럼 단지 이름만으로 구별된다면, 한 클래스 내의 모든 메서드들은 이름이 달라야한다. 그렇다면, 이전에 예로 들었던 10가지의 println메서드들은 각기 다른 이름을 가져야 한다.
예를 들면, 아래와 같은 방식으로 메서드 이름이 변경되어야 할 것이다.
void println()
void printlnBoolean(boolean x)
void printlnChar(char x)
void printlnString(String x)
하지만 오버로딩을 통해 여러 메서드들이 println이라는 하나의 이름으로 정의될 수 있다면, println이라는 이름만 기억하면 되므로 기억하기도 쉽고 이름도 짧게 할 수 있어 오류의 가능성을 많이 줄일 수 있다.
▶ 가변인자(varargs)와 오버로딩
가변인자는 '타입... 변수명'과 같은 형식으로 선언하며, PrintStream클래스의 printf()가 대표적인 예이다.
public PrintStream printf(String format, Object.. args) {...}
위와 같이 가변인자 외에도 매개변수가 더 있다면, 가변인자를 매개변수 중에서 제일 마지막에 선언해야 한다.
※ 가변인자는 내부적으로 배열을 이용한다. 그래서 가변인자가 선언된 메서드를 호출할 때마다 배열이 새로 생성된다. 가변인자가 편리하지만, 이런 비효율이 숨어있으므로 꼭 필요한 경우에만 가변인자를 사용해야 한다.
class VarArgsEx{
// No.1
static String concatenate(String delim, String ... args){
String result = "";
for(String str : args){
result += str + delim;
}
return result;
}
// No,2
static String concatenate(String ... args){
return concatenate("", args);
}
}
위 두 메서드는 별 문제가 없어 보이지만 위의 예제를 컴파일하면 컴파일에러가 발생한다.
이유는 두 오버로딩된 메서드가 구분되지 않아서 발생하는 것이다. 가변인자를 선언한 메서드를 오버로딩하면, 메서드를 호출했을 때 이와 같이 구별되지 못하는 경우가 발생하기 쉽기 때문에 주의해야 한다.
가능하면 가변인자를 사용한 메서드는 오버로딩하지 않은 것이 좋다.
▶ 변수의 초기화
멤머변수 (클래스변수와 인스턴스변수)와 배열의 초기화는 선택적이지만, 자역변수의 초기화는 필수적이다.
[멤버 변수의 초기화 방법]
- 명시적 초기화 (explicit initialization)
- 생성자 (constructor)
- 초기화 블럭(initialization block)
- 인스턴스 초기화 블럭 : 인스턴스변수를 초기화 하는데 사용
- 클래스 초기화 블럭 : 클래스변수를 초기화 하는데 사용
⊙ 명시적 초기화(explicit initialization)
class Car{
int door = 4; // 기본형(primitive type) 변수의 초기화
Engine e = new Engine(); // 참조형(reference type) 변수의 초기화
// ...
}
⊙ 초기화 블럭(initialization block)
초기화 블럭에는 '클래스 초기화 블럭'과 '인스턴스 초기화 블럭' 두 가지 종류가 있다.
초기화 블럭 내에서는 메서드 내에서와 같이 조건문, 반복문, 예외처리구문 등을 자유롭게 사용할 수 있으므로, 초기화 작업이 복잡하여 명시적 초기화만으로는 부족한 경우 초기화 블럭을 사용한다.
class InitBlock{
static { /* 클래스 초기화블럭입니다. */ }
{ /* 인스턴스 초기화블럭입니다. */ }
// ...
}
→ 생성자보다 인스턴스 초기화 블럭이 먼저 수행된다
▶ 멤버변수 초기화 시기와 순서
클래스변수의 초기화 시점 : 클래스가 처음 로딩될 때 단 한번 초기화된다.
인스턴스변수의 초기화시점 : 인스턴스가 생성될 때마다 각 인스턴스 별로 초기화가 이루어진다.
클래스변수의 초기화 순서 : 기본값 → 명시적초기화 → 클래스 초기화 블럭
인스턴스변수의 초기화 순서 : 기본값 → 명시적초기화 → 인스턴스 초기화 블럭 → 생성자
프로그램 실행 도중 클래스에 대한 정보가 요구될 때, 클래스는 메모리에 로딩된다. 예를 들면, 클래스 멤버를 사용했을 때, 인스턴스를 생성할 때 등에 이에 해당된다.
하지만, 해당 클래스가 이미 메모리에 로딩되어 있다면, 또다시 로딩하지 않는다. 물론 초기화도 다시 수행되지 않는다
'JAVA > Java의 정석' 카테고리의 다른 글
Java의 객체지향 프로그래밍 [4] : 다형성, 추상클래스, 인터페이스, 내부 클래스 (0) | 2023.06.26 |
---|---|
Java의 객체지향 프로그래밍 [3] : 상속, 오버라이딩, 제어자 (0) | 2023.06.24 |
Java의 객체지향 프로그래밍 [1] : 클래스 변수, 인스턴스 변수, JVM의 메모리 구조, 클래스 메서드와 인스턴스 메서드 (0) | 2023.06.22 |
JIT 컴파일러와 Java Hotspot (0) | 2023.06.18 |
JVM이란? (Java Virtual Machine) JVM의 구조와 장점, 단점 (0) | 2023.06.16 |