메서드 오버 로딩은 클래스 내부에서 똑같은 메서드 네이밍을 가지지만 아규먼트의 개수가 다르고 리턴 타입을 다르게 하는 기법을 의미한다.
대부분의 서적에서는 위의 글을 설명하고 몇몇 예시를 설명하고 끝낸다.
하지만 나는 여기에 머무르지 않고 조금 더 깊게 볼 것이다. 메서드 오버 로딩의 시점이 어느 시점에 이루어지는가와 JVM에서 이를 컴파일하는 기법에 대해서 알아볼 예정이다.
메서드 오버로딩은 컴파일 시점에 이루어진다.
메서드 오버라이딩은 런타임 시점이 아닌 컴파일 시점에 이루어진다.
이점을 염두하면서 아래 예시 코드를 보자!
/**
* Project : EffectiveStudy
* Created by InteliJ IDE
* Developer : junwoochoi
* Date : 2020/04/06
* Time : 11:33 오후
*/
public class CollectionClassifier {
public static String classify(Set<?> s) {
return "집합";
}
public static String classify(List<?> list) {
return "리스트";
}
public static String classify(Collection<?> c) {
return "그외";
}
public static void main(String[] args) {
Collection<?>[] collections = {
new HashSet<String>(),
new ArrayList<BigInteger>()
};
for (Collection<?> collection : collections) {
System.out.println(classify(collection));
}
}
}
Collection 타입으로 HashSet, ArrayList을 담았다.
출력 결과는 나의 예상과 달랐다.
만약 오버로딩이 런타임 시점에 어느 메서드를 호출할지를 결정한다면 집합, 리스트 결과가 출력되겠지만
오버 로딩은 컴파일 시점에 메서드 호출을 결정하기 때문에 즉 컴파일 시점에는 Collection 타입이기 때문에 "그 외"가 출력되는 것이다.
Autoboxing과 Widening
https://jwdeveloper.tistory.com/148
만약 아규먼트 타입을 Wrapper 클래스 타입으로 선언하고 그에 대응하는 primitive타입이 존재한다면?
class Conversion {
public void method(int i) {
System.out.println("Primitive type int :: "+ i);
}
public void method(Integer i) {
System.out.println("Reference type Integer :: "+ i);
}
public void method(long i) {
System.out.println("Primitive type long :: "+ i);
}
}
class Test {
public static void main(String[] args) {
Conversion conversion = new Conversion();
conversion.method(new Long(100));
}
}
아규먼트 타입을 long으로 갖는 메서드를 찾아서 AutoBoxing을 한다.
만약 아규먼트 타입을 Wrapper 클래스 타입으로 선언하고 그에 대응하는 primitive타입이 존재하지 않는다면?
class Conversion {
public void method(int i) {
System.out.println("Primitive type int :: "+ i);
}
public void method(Integer i) {
System.out.println("Reference type Integer :: "+ i);
}
public void method(float i) {
System.out.println("Primitive type float :: "+ i);
}
}
class Test {
public static void main(String[] args) {
Conversion conversion = new Conversion();
conversion.method(new Long(100));
}
}
컴파일러가 AutoBoxing에 대응하는 어떠한 메서드를 찾는데 실패할 경우 widened primitive 데이터 타입의 메서드 파라미터를 찾는다.
widening과 AutoBoxing이 동시에 일어나는 경우
동시에 일어나는 경우 우선순위는 아래와 같다.
- widening
- AutoBoxing
- 가변 인수
class Conversion {
public void method(Integer i) {
System.out.println("Reference type Integer :: "+ i);
}
}
class Test {
public static void main(String[] args) {
Conversion conversion = new Conversion();
byte val = 5;
conversion.method(val);
}
}
byte에 해당하는 타입을 widening 할 수가 없으니 컴파일 에러가 발생한다.
이때 방법이 있다😀
Object 타입을 사용하여 타입 캐스팅을 하는 것이다.
class Conversion {
public void method(Object i) {
Byte b = (Byte) i;
System.out.println("Reference type Integer :: "+ i);
}
}
class Test {
public static void main(String[] args) {
Conversion conversion = new Conversion();
byte val = 5;
conversion.method(val);
}
}
Code Link
https://github.com/mike6321/PURE_JAVA/tree/master/EffectiveStudy
References
https://www.javaworld.com/article/3268983/java-challengers-1-method-overloading-in-the-jvm.html
https://www.geeksforgeeks.org/method-overloading-autoboxing-widening-java/
|
'Java > Java' 카테고리의 다른 글
(JAVA) Garbage Collector (0) | 2020.05.10 |
---|---|
(JAVA) Method 오버라이딩에 대해서 (0) | 2020.04.15 |
(JAVA) Interning of String in JAVA (0) | 2020.04.02 |
(JAVA) static keyword in java (0) | 2020.03.04 |
(JAVA) 상속보다는 컴포지션을 사용하자 (0) | 2020.02.27 |