Java의 메서드 구성요소와 메서드 오버로딩
메서드는 특정 작업을 수행하는 일련의 문장들을 하나로 묶은 것이다. 기본적으로 수학의 함수와 유사하며, 어떤 값을 입력하면 그 값으로 작업을 수행해서 결과를 반환한다. 수학의 함수와 다른 점은 메서드는 입력값이나 결과값이 없을 수도 있다는 것이다.
메서드는 크게 선언부와 구현부로 이루어져 있으며, 메서드를 정의한다는 것은 선언부와 구현부를 작성하는 것을 뜻한다.
// 메서드 선언
반환타입 메서드이름 (매개변수타입 매개변수이름, 매개변수타입 매개변수이름, ...) // 선언부
{ // 구현부
// 메서드 호출 시 수행될 코드
}
void
void
가 아닌 경우 return문을 반드시 포함해야 함void
인 경우 컴파일러가 메서드의 마지막에 ‘return;’을 자동적으로 추가함메서드를 호출해야한 구현부의 문장들이 수행될 수 있는데 자바에서 main 메서드는 프로그램 실행 시 운영체제에 의해 자동적으로 호출된다.
// 메서드 호출
메서드이름(인수1, 인수2, ...);
호출 스택은 메서드의 작업에 필요한 메모리 공간이다. 메서드가 호출되는 순서대로 호출 스택에 메서드를 위한 메모리가 할당되고, 이 메모리는 메서드가 작업을 수행하는 동안 지역변수들과 연산의 중간 결과 등을 저장하는데 사용된다. 그리고 메서드가 작업을 마치면 할당되었던 메모리 공간은 반환되어 비워진다.
다음은 호출 스택을 그림으로 나타낸 것이다.
public class CallStack {
public static void main(String[] args) {
System.out.println("Hello");
}
}
메서드 앞에 static이 붙으면 클래스 메서드이고 없으면 인스턴스 메서드가 된다. 클래스 메서드는 객체를 생성하지 않고도 클래스이름.메서드이름(매개변수)
와 같은 식으로 호출이 가능하다. 인스턴스 메서드는 반드시 객체를 생성해야만 호출할 수 있지만 같은 클래스에 속한 멤버들 간에는 별도의 인스턴스를 생성하지 않고도 서로 참조 또는 호출할 수 있다. 단, 클래스 멤버가 인스턴스 멤버를 참조 또는 호출하고자 하는 경우에는 인스턴스를 생성해야 한다. 인스턴스 멤버가 존재하는 시점에 클래스 멤버는 항상 존재하지만, 클래스 멤버가 존재하는 시점에 인스턴스 멤버가 존재하지 않을 수도 있기 때문이다.
메서드는 메서드 시그니처를 갖는다. 메서드 시그니처란, 메서드 선언부에서 메서드 이름과 매개변수의 리스트를 의미한다. 메서드도 변수와 마찬가지로 같은 클래스 내에서 서로 구별될 수 있어야 하기 때문에 각기 다른 이름을 가져야 하는데 이름이 같아도 매개변수의 개수 또는 타입이 다르면 다른 메서드 시그니처로 인식된다. 이처럼 한 클래스 내에 같은 이름의 메서드를 여러 개 정의하는 것을 ‘메서드 오버로딩'이라고 한다. 참고로 반환 타입은 오버로딩을 구현하는데 아무런 영향을 주지 못한다.
// 매개변수의 이름만 다를 뿐 매개변수의 타입이 같으므로 오버로딩 X
int add(int a, int b) { return a + b; }
int add(int x, int y) { return x + y; }
// 리턴 타입만 다른 경우 매개변수의 타입과 개수가 일치하기 때문에 어떤 메서드가 호출된 것인지 알 수 없음
// 오버로딩 X
int add(int a, int b) { return a + b; }
long add(int a, int b) { return (long) a + b; }
// 매개변수의 순서가 서로 다른 경우 호출 시 매개변수의 값에 의해 호출될 메서드가 구분될 수 있음
// 오버로딩 O
long add(int a, long b) { return a + b; }
long add(long a, int b) { return a + b; }