자바를 공부하다가 궁금한 점이 있어서 질문하나 드릴까합니다...
아래와 같이 A. wildcard를 사용하는 경우와 B. wildcard 대신 메소드레벨 제너릭 사용, [질문1]두 경우 사이에 차이점이 무엇이 있습니까?(성능상 차이라도 있는지...)
A.
public void Method(Collection<? extends Number> parameter){
//...
}
B.
public <T extends Number> void Method(Collection<T> parameter){
//...
}
제가 공부해 본바에 의하면 위 둘의 차이중 하나는, 와일드카드 캡처(http://docs.oracle.com/javase/tutorial/java/generics/capture.html)를를) 이용하기 위해서 B의 경우를 private Helper Method(Wildcard Capture)로 처리하는 것이었습니다.
public class WildcardFixed {
void foo(List<?> i) {
fooHelper(i);
}
// Helper method created so that the wildcard can be captured
// through type inference.
private <T> void fooHelper(List<T> l) {
l.set(0, l.get(0));
}
}
[질문2] 그렇다면 helper 메소드를 public으로 처리하면 간단할 것 같은데 이렇게 하지 않는 이유가 무엇입니까? (질문1과 비슷한 질문인 것 같습니다)
public class WildcardFixed {
public <T> void foo(List<T> l) {
l.set(0, l.get(0));
}
}
4개의 의견 from SLiPP
java 가 가진 강한 type safe 성격때문인거 같네요... return value 에 대해 어떤 type 인지 명확하지 않다보니... 제네릭은 다형성을 허용하지 않습니다. 때문에 그것을 보완하기 위해 나온게 와일드카드입니다.
와일드카드를 쓴 자료구조 variable 에는 add, addAll 등과 같은 메소드를 차단하여 향후 자료구조 내부 요소의 변경을 막습니다. 보여주신 예제와 링크는 자료구조 List의 set 메소드로 내부 자료구조 변경이 용이합니다. 사실 링크의 Error 클래스의 foo 메소드의 i 자료구조에 대해 type safe하지 않은 코드죠.
따라서 이는 컴파일레벨에서 잡혀지는 에러이고, 이를 잠재적인 런타임 레벨에서의 에러를 가지지만 프로그래머가 원하는 와일드카드를 쓰면서도 내부 자료구조에 대해 변경을 이용하려면 보여주신 링크처럼 우회방법을 써야합니다...
사실 눈속임이죠(?) 근데... 제가 질문을 이해하고 의견을 추가한거 맞나요..? 아니면 자삭할게요ㅠㅠㅠ
ps : 링크 감사합니다!!!!
@kimmunsu 답변 감사드립니다. 듣고보니 제 질문이 조금 이해하기 어려웠던 것 같아서 수정하였습니다.
일단 제목에서 오해가 생길 소지가 있어 보입니다. Wildcard는 Generics라는 주제의 하부 주제이므로 Generic(s) vs wildcard란 식으로 같은 수준으로 놓고 비교할 수 있을 것 같지 않네요. 질문 내용을 읽어보니 Generic Method vs Wildcard를 뜻하려고 하신 것 같은데 맞나요?
보통 Generic Method는 특정 타입 파라미터 T를 두 곳 이상, 예를 들어 메서드 인자와 반환값에 모두 사용할 때 사용하면 좋습니다.
public static List compact(List list)
물론 한 번만 쓰일 때에도 사용이 가능합니다.
public static void compact(List list)
하지만 이럴 때 와일드 카드를 사용하면 메서드 시그니처가 훨신 간단해 집니다.
public static void compact(List<?> list)
반환값이 없기 때문에 타입 추론의 장점도 없고, 와일드카드 쪽이 의도가 훨씬 명확하죠.
결국 타입 파라미터를 선언하고 2회 이상 쓸 일이 없을 경우, 비록 구현이 번거롭더라도, 시그니처 단순화의 관점에서 타입 파라미터를 선언하지 않는 와일드카드가 유용하다고 볼 수 있지 않을까 합니다.
@fupfin 답변 감사합니다. 어떻게 사용하든 결과에는 차이가 없다는 뜻이군요. 시그니처가 간단해 보인다는 것외에는...
제목은 바꾸고 싶은데 이슈 #155관련한 계정 오류가 있어서 그러질 못합니다. 양해해 주시길... (https://github.com/javajigi/slipp/issues/155))
의견을 남기기 위해서는 SLiPP 계정이 필요합니다.
안심하세요! 회원가입/로그인 후에도 작성하시던 내용은 안전하게 보존됩니다.
SLiPP 계정으로 로그인하세요.
또는, SNS 계정으로 로그인하세요.