개발관련/(과거)메모

자바 제네릭 지우개

동팡 2017. 3. 31. 16:43

참고



코드

Apple.java

package tested;

public class Apple extends fruit{
	public Apple() {
	
	}
}

fruit.java

package tested;

public class fruit {
	
	public fruit() {
		
	}

}

test.java

package tested; import java.util.ArrayList; import java.util.List; public class test { public static void main(String args[]) { fruit apple = new Apple(); if (apple instanceof Apple) System.out.println("요미요미~"); if (apple instanceof List<Apple>) System.out.println("요미요미~"); } }


위의 코드를 실행 시 에러가 뜬다.

apple instanceof List<Apple>

Cannot perform instanceof check against parameterized type List<Apple>. Use the form List<?> instead since further generic type information will be erased at runtime


"런타임 시 type 정보가 지워지기 때문에,  List<?> 사용해라. 

List<?> 하는 순간 제네릭의 의미가 상실되지 않나... 생각한다..

List<?>는 List<? extends Object>라 이해하면 되겠다. Object는 모든 클래스 중 최상위 클래스다.

위의 ?는 공변성, 반공변성 또는 리플렉션 API에 대해 포스팅 할 때 다루겠다.

이런 현상으로 인하여 자바 제네릭은 여러 개발자에게 많은 욕을 잡수셨다.

 

C#의 경우, IL로 컴파일되어 => CLR 위에서 바이너리로 컴파일: 제네릭 타입은 여전히 상주한다.

즉 C#은 런타임 시 제네릭 정보를 지속적으로 보유하고 있다.

또한 제네릭 사용으로의 코드 간결화, 성능 개선의 이점을 확보한다.




여기까지 임백준 작가님의 책 내용이다.

(좀 더 풍부하지만, 깊은 내용과 관련된 내용은 독서하는 것을 추천한다.




추가적으로 알아보자 


예로 ArrayList<String>을 할 경우, 자바 런타임에서는 new ArrayList() 객체 생성한다.

그리고 컴파일을 할 때 타입을 잃어버린다.


자바는 설계상 바이트 코드로 컴파일 할 경우, 모든 타입 정보를 드랍시킨다. 그 이유는 자바 소스 코드와 바이트 코드의 버전 호환을 위해서다. 그래서 결국 제네릭도 똑같이 타입 정보를 드랍한다. 이러한 사항에서의 이점은 런타임 오버 헤드를 발생하지 않는다.


(C#의 경우, 이런 문제를 해결하기 위해 CLR 자체를 수정했지만, 자바는 하지 않았다.) 


그러나 모든 경우 타입 정보를 드랍하는 것은 아니다. 익명 클래스를 사용할 경우, 타입 정보를 보존할 수 있다. 


그 다음은 귀찮다. 담주나 주말에 게시글 수정하겠다.








ㅇㅇ