728x90
제네릭 타입을 컴파일하면 class 파일에 제네릭이 남아있을까?
제네릭(Generic)
- 데이터 타입을 일반화(Generalize)하는 것을 의미.
- 클래스나 메소드에서 사용할 내부 데이터 타입을 컴파일 시 미리 지정하는 방법.(즉, 컴파일시 미리 타입검사를 수행하는 방법)
→ 클래스나 메소드 내부에서 사용되는 객체의 안정성을 높일 수 있음.
→ 반환값에 대한 타입 변환 및 타입 검사에 들어가는 노력을 줄일 수 있음.
Row Type
- 제네릭 타입에서 타입 매개변수를 전혀 사용하지 않을때를 의미.
자바 제네릭이란? ☜ Click!
Java Generics Type Erasure(제네릭 타입소거)
구체화 vs 비구체화
- 구체화 타입(reifiable type) : 자신의 타입 정보를 런타임에도 알고 있는것. 배열이 구체화 타입에 해당된다.
- 비구체화 타입(non-reify type) : 런타임에는 소거(erasure)가 되기 때문에 컴파일 타임보다 정보를 적게 가지는 것. 제네릭 타입이 비구체화 타입에 해당되며, 제네릭은 컴파일 타임에 타입 체크를 한 뒤 런타임에는 타입을 지우는 방법을 사용하고 있다.
Generics Type Erasure란?
말 그대로 소거(erasure). 원소 타입을 컴파일 타입에만 검사하고 런타임에는 해당 타입 정보를 알 수 없는 것이다. 정리하자면, 컴파일 타입에만 타입 제약 조건을 정의하고, 런타임에는 타입을 제거한다는 뜻이다.
자바 컴파일러의 타입 소거
Unbounded Type(<?>, <T>)는 Object으로 변환한다.
// 컴파일 할 때 (타입 소거 전)
public class Test<T> {
public void test(T test) {
System.out.println(test.toString());
}
}
// 런타임 때 (타입 소거 후)
public class Test {
public void test(Object test) {
System.out.println(test.toString());
}
}
Bound Type(<E extends Comparable>)의 경우 Object가 아닌 Comparable로 변환
// 컴파일 할 때 (타입 소거 전)
public class Test<T extends Comparable<T>> {
private T data;
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
}
// 런타임 때 (타입 소거 후)
public class Test {
private Comparable data;
public Comparable getData() {
return data;
}
public void setData(Comparable data) {
this.data = data;
}
}
확장된 제네릭 타입에서 다형성 보존을 위해 어떠한 클래스나, 인스턴스를 상속 혹은 구현할때 bridge method를 생성한다.
public class Node<T> {
public T data;
public Node(T data) { this.data = data; }
public void setData(T data) {
System.out.println("Node.setData");
this.data = data;
}
}
// 컴파일 할 때 (타입 소거 전)
public class MyNode extends Node<Integer> {
public MyNode(Integer data) { super(data); }
public void setData(Integer data) {
System.out.println("MyNode.setData");
super.setData(data);
}
}
// 런타임 때 (타입 소거 후)
public class MyNode extends Node {
// Bridge method generated by the compiler
public void setData(Object data) {
setData((Integer) data);
}
public void setData(Integer data) {
System.out.println("MyNode.setData");
super.setData(data);
}
// ...
}
bridge 메서드는 type erasure 이후 Node 클래스에서의 setData 메서드와 같은 이름의 메서드를 가지고 원래의 setData 메서드의 역할을 대신한다.
→ 제네릭 타입을 사용할 수 있는 일반 class, interface, method에만 소거 규칙을 적용한다.
→ 타입 안정성 측면에서 필요하면 type casting을 넣는다.
참조: https://velog.io/@guswns3371/%EC%A0%9C%EB%84%A4%EB%A6%AD
728x90
'JAVA' 카테고리의 다른 글
[Java] GC 종류별 차이 (0) | 2022.03.24 |
---|---|
[Java] 리플렉션(Reflection)이란? (1) | 2022.03.01 |
[Java] 자바 제네릭이란? Java Generic (0) | 2022.02.24 |
[Java] 자바가 컴파일 되는 과정 (0) | 2022.02.23 |
[Java] JVM 구조에 대한 설명. 그리고 버전에 따라 무엇이 바뀌는가? (0) | 2022.02.22 |