아래 코드를 보시고 1, 2번 라인중에 어디서 에러가 날 지를 찾아보세요.
네, 2번 라인입니다.
그럼 다음 코드는?
네, 1번입니다. 잘 이해가 되질 않아 사내 메일링 리스트에 물어보니
이랍니다. 즉 T 타입이 아직 결정되지 않은 상태라 D와 T는 compatible한 타입이 아닌거죠.
강제로 casting을 해서 컴파일이 되게 만들면 그 코드는 runtime error (ClassCastException)를 발생하게 됩니다. 다음 코드를 보세요. 즉 이런 방법으론 도저히 type-safe한 코드를 작성할 수 없습니다.
이 같은 상황을 방지하기 위해 1번 라인에서 에러를 내 주는 것이죠.
코딩 가이드라인을 만들어 보자면 "method의 parameter로 사용되지 않는 type variable을 사용하면 안된다"입니다. 다음과 같은 경우는 parameter로도 사용되고 있으므로 문제가 없는 경우들입니다.
사실... 아직도 잘 모르겠어요. Java generic. =(
interface B { void doB(); } class D implements B { public void doB() {} } interface H { B getB(); } class HImpl implements H { public B getB() { return new D(); // 1) } } ... H h = new HImpl(); D d = h.getB(); // 2)
네, 2번 라인입니다.
그럼 다음 코드는?
interface B1 { void doB1(); } interface B2 { void doB2(); } class D implements B1, B2 { public void doB1() {} public void doB2() {} } interface H { <T extends B1 & B2> T getB(); } class HImpl implements H { public <T extends B1 & B2> T getB() { return new D(); // 1) } } ... H h = new HImpl(); D d = h.getB(); // 2)
네, 1번입니다. 잘 이해가 되질 않아 사내 메일링 리스트에 물어보니
I think you're seeing and interpreting it as "this method can return anything that implements both interfaces". What it's actually saying is "the caller is going to tell you a specific class that implements both interfaces, and you must return one of those".
이랍니다. 즉 T 타입이 아직 결정되지 않은 상태라 D와 T는 compatible한 타입이 아닌거죠.
강제로 casting을 해서 컴파일이 되게 만들면 그 코드는 runtime error (ClassCastException)를 발생하게 됩니다. 다음 코드를 보세요. 즉 이런 방법으론 도저히 type-safe한 코드를 작성할 수 없습니다.
class D2 implements B1, B2 { public void doB1() {} public void doB2() {} } ... D2 d = h.getB(); // ClassCastException!!
이 같은 상황을 방지하기 위해 1번 라인에서 에러를 내 주는 것이죠.
코딩 가이드라인을 만들어 보자면 "method의 parameter로 사용되지 않는 type variable을 사용하면 안된다"입니다. 다음과 같은 경우는 parameter로도 사용되고 있으므로 문제가 없는 경우들입니다.
<T> T makeInstance(Class<T> cls) { return cls.newInstance(); } ... <T extends Comparable<? super T>> T min(T a, T b) { return a.compareTo(b) < 1 ? a : b; }위의 예제 코드같은 경우 아래와 같은 방법으로 type-safe하게 작성될 수 있습니다.
interface B1 { void doB1(); } interface B2 { void doB2(); } class D implements B1, B2 { public void doB1() {} public void doB2() {} } interface H <T extends B1, B2> { T getB(); } class HImpl implements H<D> { public D getB() { return new D(); // 1) } } ... H<D> h = new HImpl(); D d = h.getB(); // 2)
사실... 아직도 잘 모르겠어요. Java generic. =(
"method의 parameter로 사용되지 않는 type variable을 사용하면 안된다" 에 대한 counter example을 보여드리면 ^^
ReplyDeletemkseo@ubuntu:~/tmp$ javac -1.5 Generics.java
mkseo@ubuntu:~/tmp$ java Generics
1
2
3
mkseo@ubuntu:~/tmp$ cat Generics.java
import java.util.*;
class Lists {
public static ArrayList newArrayList() {
return new ArrayList();
}
}
public class Generics {
public static void main(String[] args) {
List li = Lists.newArrayList();
li.add(1);
li.add(2);
li.add(3);
for (int i: li) {
System.out.println(i);
}
}
}
mkseo@ubuntu:~/tmp$
제가 보기에 위에서 하신 부분에서의 에러는 타입 T가 쓰인적이 없기때문에 타입 T가 정의되지 않아서인걸로 생각됩니다...
http://mkseo.pe.kr/blog/?p=1691 에 링크된 자료 읽어보세요. 그리고 http://www.angelikalanger.com/GenericsFAQ/FAQSections/TechnicalDetails.html#Topic3 도요.
전 자바 Generics는 정말 최대의 실패작이 아닌가 하는 생각을 합니다..
꺽쇠가 다 날아가네요. 다시...
ReplyDeletemkseo@ubuntu:~/tmp$ cat Generics.java
import java.util.*;
class Lists {
public static <T> ArrayList<T> newArrayList() {
return new ArrayList<T>();
}
}
public class Generics {
public static void main(String[] args) {
List<Integer> li = Lists.newArrayList();
li.add(1);
li.add(2);
li.add(3);
for (int i: li) {
System.out.println(i);
}
}
}
mkseo@ubuntu:~/tmp$
참 이 코드의 원본은 http://code.google.com/p/google-collections/source/browse/trunk/src/com/google/common/collect/Lists.java#62 에 있습니다.
흠.. 근데 newArrayList의 return type은 T가 아니라 ArrayList라 좀 다른 경우 아닐까요?
ReplyDelete아.. 그럼 method의 parameter로 사용되지 않는 type variable을 리턴타입으로 사용하면 안된다 이렇게 되겠네요.
ReplyDeleteChecked exception도 싫어하시고 generic도... :)
ReplyDelete그럼 java의 productivity는 어디서 나오는걸까요? 역시 eclipse? ^^;
네. 아마 eclipse!! ^^ eclipse처럼 척척 개발되는 환경은 다른 언어는 힘든거 같아요. 파이썬도 C++도 루비도 다 엉망이고...
ReplyDelete자바빼면 C#이 참으로 괜찮은 언어이고 .NET이 참으로 괜찮은 프레임워크라고 생각합니다... 근데 참 C#은 도무지 뜨지를 못하는거 같아요.
예전 경험에 비춰보면 ms기술들은 너무 닫혀 있는 거 같아요. 그래서 Windows 플랫폼 아닌데선 뜨기 쉽지 않은 듯.
ReplyDelete