[Java/자바] 오버로딩 (overloading)이란 ?

오버로딩(Overloading)이라는 뜻은 사전적으로 '과적하다.'라는 뜻으로,

오버로딩이란 ?  한 클래스 내에서 같은 이름의 메서드를 여러 개 정의하는 것을 말합니다.

 


오버로딩의 조건

오버로딩이 성립되기 위해선 다음과 같은 조건을 만족해야합니다.

1. 메서드 이름이 같아야 한다.
2. 매개변수의 개수 또는 타입이 달라야 한다.

비록 메서드의 이름이 같더라도 매개변수가 다르면 서로 구별될 수 있기 때문에 오버로딩이 가능합니다.

위의 조건을 만족시키지 못할시에는, 메서드가 중복으로 간주되어 컴파일 시 에러가 발생합니다.

 

주의할 점으로는 반환 타입( 리턴 타입 )은 오버로딩을 구현하는데 아무런 영향을 주지 않습니다.

 

오버로딩 예시 코드

 

아래 코드는 전부 오버로딩의 조건을 만족합니다.

class OverloadingTest {
	public static void main(String args[]) {
		MyMath3 mm = new MyMath3();
		System.out.println("mm.add(3, 3) 결과:"    + mm.add(3,3));
		System.out.println("mm.add(3L, 3) 결과: "  + mm.add(3L,3));
		System.out.println("mm.add(3, 3L) 결과: "  + mm.add(3,3L));
		System.out.println("mm.add(3L, 3L) 결과: " + mm.add(3L,3L));

		int[] a = {100, 200, 300};
		System.out.println("mm.add(a) 결과: " + mm.add(a));
   }
}

class MyMath3 {
	int add(int a, int b) {
		System.out.print("int add(int a, int b) - ");
		return a+b;
	}
	
	long add(int a, long b) {
		System.out.print("long add(int a, long b) - ");
		return a+b;
	}
	
	long add(long a, int b) {
		System.out.print("long add(long a, int b) - ");
		return a+b;
	}

	long add(long a, long b) {
		System.out.print("long add(long a, long b) - ");
		return a+b;
	}

	int add(int[] a) {		// 배열의 모든 요소의 합을 결과로 돌려준다.
		System.out.print("int add(int[] a) - ");
		int result = 0;
		for(int i=0; i < a.length;i++) {
			result += a[i];
		}	
		return result;
	}
}

출력 결과

여기서 헷갈릴 수 있는 부분이 long add(int a, long b)와 long add(long a, int b)매개변수의 타입 순서만 다른 것인데,

이 또한 두 메서드 간 매개변수의 타입이 다른 것이기 때문에 오버로딩 조건이 충족됩니다.


오버로딩의 장점

 

1. 메서드의 이름을 절약할 수 있다.

 

2. 오버로딩을 통해 여러 메서드들이 하나의 이름으로 정의되므로 하나의 이름만 기억하면 된다. 그렇기 때문에, 기억하기 쉽고 오류의 가능성을 줄일 수 있다.

 

우리가 흔히 콘솔창에 텍스트를 출력할 때 사용하는 println 메서드가 오버로딩의 대표적인 예라 할 수 있습니다.

println메서드를 호출 할 때, 매개변수로 넘겨주는 값의 타입에 따라 아래의 오버로딩된 메서들 중의 하나가 선택되어 실행됩니다. 

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

 


가변인자와 오버로딩

 

기존에는 메서드의 매개변수 개수가 고정적이었으나, JDK1.5부터 동적으로 지정해 줄 수 있게 되었습니다.

이 기능을 "가변인자"라고 하며 가변인자는 "타입...변수명"같은 형식으로 선언하고 printf()가 대표적인 예입니다.

가변인자 외에도 매개변수가 더 있다면, 가변인자는 매개 변수 중 가장 마지막에 선언해야 합니다.

public PrintStream printf(String format, Object... args) { ... }

 

가변인자를 마지막에 선언하지 않았다면 다음과 같은 컴파일 에러가 발생합니다.

// 에러 : 가변인자는 항상 마지막 매개변수이어야 한다.
public PrintStream printf(Object... args, String format) { ... }

 

가변인자 사용 예

만약 여러 문자열을 하나로 결합하여 반환하는 concatenate 메서드가 다음과 같다면,

String concatenate(String s1, Strint s2) { ... }
String concatenate(String s1, Strint s2, Stirng s3) { ... }
String concatenate(String s1, Strint s2, Stirng s3, String s4) { ... }

가변인자를 사용하여 메서드 하나로 간단히 대체할 수 있습니다.

String concatenate(String...str) { ... }

 

또한, 배열도 가변인자를 적용할 수 있습니다.

매개변수의 타입을 배열로 하게 되면 반드시 인자를 지정해 줘야합니다.

그렇기 때문에 길이가 0일 배열도 null 이나, new String[0]으로 인자를 지정해 줘야합니다.

String concatenate(String[] str) { ... }

String result = concatenate(new String[0]); // 인자로 배열을 지정
String result = concatenate(null); // 인자로 null을 지정
String result = concatenate(); // 에러 : 인자가 없음

 


가변인자 예시코드

 

아래의 코드는 매개변수로 받은 구분자를 문자열에 추가하는 코드입니다.

class VarArgsEx {
	public static void main(String[] args) {
		String[] strArr = { "100", "200", "300" };
		
		System.out.println(concatenate("", "100", "200", "300"));
		System.out.println(concatenate("-", strArr));
		System.out.println(concatenate(",", new String[]{"1", "2", "3"}));
		System.out.println("["+concatenate(",", new String[0])+"]");
		System.out.println("["+concatenate(",")+"]");
	}

	// 매개변수로 입력된 문자열에 구분자를 넣는 메서드
	static String concatenate(String delim, String... args) {
		String result = "";

		for(String str : args) {
			result += str + delim;
		}
		
		return result;
	}

/* 주석을 풀면 위의 concatenate 클래스 메서드와 구분되지 않아 에러가 발생한다.
 * 가변인자 메서드는 오버로딩하지 않는 것이 좋다.
	static String concatenate(String... args) {
		return concatenate("",args);
	}
*/
}

concatenate 메서드는 가변인자로 매개변수를 선언했기 때문에 문자열을 개수의 제약없이 매개변수로 지정가능합니다.

 

맨 아래 코드를 보면 주석처리가 되어 있는데, 두 메서드가 오버로딩되어 별 문제가 없어보이지만,

주석을 풀고 실행하면 에러가 발생합니다.

그 이유는 가변인자를 선언한 메서드를 오버로딩하면 메서드를 호출할 때 구별되지 못하는 경우가 발생하기 때문입니다.

그렇기 때문에 가능하면 가변인자를 사용한 메서드는 오버로딩하지 않는 것이 좋습니다.


참고자료 : 자바의 정석 3