2012-02-01 2 views
1

내 자신의 버전의 Collections.fill() 및 Collections.reverse()를 구현할 과제가 있습니다. 알고리즘은 충분히 간단하지만 관련 제네릭에서 약간의 손실이 발생합니다. 특히 캐스팅을해야 할 때입니다. 물론 내가 유형으로 임시을 선언 할 수 없습니다Java 메소드에서 제네릭을 사용할 때 올바르게 캐스팅하는 방법은 무엇입니까?

public static void reverse(List<?> a_list) { 
    int list_size = a_list.size(); 
    ListIterator<?> left_to_right = a_list.listIterator(); 
    ListIterator<?> right_to_left = a_list.listIterator(list_size); 
    ? temp_variable; 

    // ..doing some stuff 

    right_to_left.set(temp_variable); 

} 

그러나 :

내 원래의 아이디어는 무엇인가 같다 "?". "Object temp_variable"로 선언하는 것은 의미가 있습니다 만, 마지막에 set (temp_variable)의 호출은 동작하지 않습니다. ListIterator는 Object를 취하지 않기 때문에 List는 List <Object> 유형이 아니기 때문에 Object를 취하지 않습니다.

그것은 ListIterators 객체로 온도를 선언하고 캐스팅 한 후, 나에게 의미가 있습니다 :이 작업을 수행 할 때

ListIterator<Object> left_to_right = 
    (ListIterator<Object>) a_list.listIterator(); 
ListIterator<Object> right_to_left = 
    (ListIterator<Object>) a_list.listIterator(list_size); 

컴파일러는 나에게되지 않은 캐스트 경고를 제공합니다,하지만 난 방법을 생각할 수 없다 내 구현을 감안할 때 이것은 깨질 것입니다. 이 일에 위험이 있습니까? 도

public static <E> void fill(List<? super E> a_list, E an_object) { 
    ListIterator<E> an_iterator = (ListIterator<E>) a_list.listIterator(); 

      // ..doing some stuff 
    an_iterator.set(an_object); 

} 

이 검사되지 않은 캐스트 경고를 제공합니다

그런 다음 Collections.fill()에, 나는 원래 그런 짓을하고 싶었다. 이에 안전해야한다,리스트의 제네릭 형식이 실제로 E의 슈퍼 클래스 인 경우

ListIterator<Object> an_iterator = (ListIterator<Object>)a_list.listIterator(); 

: 그리고 같은 캐스팅 할 안전 할 것, 난 여전히 경고를 얻을에도 불구하고, 더 그것에 대해 생각 리스트의 범용적인 형태의 서브 클래스의 ListIterator는 아니고, 오브젝트의 List의 ListIterator에 캐스트 할 수 있을지 어떨지는?

조언을 해주시면 감사하겠습니다. 강사가이 문제를 해결하기를 바랍니다. 제네릭을 더 잘 이해하고 싶습니다.

+1

제네릭을 사용하면 * AVOID * 캐스팅에 도움이된다고 생각합니까? 그리고 제네릭을 사용하는 전체 * POINT *와 모순되는 일반적인 종류의 "객체"를 사용하지 않습니까? – paulsm4

+0

제안 : 1) 다음 링크를 읽어보십시오. http://www.javacodegeeks.com/2011/04/java-generics-quick-tutorial.html http://docs.oracle.com/javase/tutorial/extra/generics /wildcards.html 2) "?" 기본 제네릭에 익숙해 질 때까지 와일드 카드 구문을 사용합니다. 그런 다음 "?" 당신이 정말로 필요로하는 경우에만 구문을 사용하십시오. IMHO ... – paulsm4

+0

@ paulsm4 링크를 가져 주셔서 감사합니다. 나는 나의 두 가지 문제를 해결했다고 생각한다 : 하나를 사용 하는가?하나의 type-parameter를 가진 메소드가 실제로 지우는 것과 같은 시그니처이기 때문에 타입 매개 변수를 사용할 수 있습니다. 이제 ListIterator 유형으로 을 사용할 수 있음을 알았습니다 (허용되지 않음). – Trent

답변

6

캐스팅하지 마십시오. ?을 사용하지 마십시오. 형식 매개 변수화 된 메서드 사용; 이 같은. 양식 Xyz<?>의 일반적인 유형이

public static <T> void reverse(List<T> a_list) { 
    int list_size = a_list.size(); 
    ListIterator<T> left_to_right = a_list.listIterator(); 
    ListIterator<T> right_to_left = a_list.listIterator(list_size); 
    T temp_variable; 

    while(left_to_right.nextIndex() < list_size/2) { 
     temp_variable = left_to_right.next(); 
     left_to_right.set(right_to_left.previous()); 
     right_to_left.set(temp_variable); 
    } 
} 
+0

Java Collection을 구현 중이므로 문제가됩니다. reverse()를 사용하려면'static void reverse (List list)'자바 서명을 사용해야합니다. 확실히 오히려 당신의 버전을 사용하고 싶습니다. – Trent

+0

아니요, * 모든 * 제네릭은 이제 "?" 와일드 카드 구문. 그렇다고해서 구체적인 수업을 사용할 수 없다는 의미는 아닙니다. 다시, 위에서 언급 한 링크를 읽으십시오. – paulsm4

+0

흠, 좋아요. 'static void reverse (List list)'는 정말로 지워진 후에'static void reverse (List list)'와 같은 서명인가요? – Trent

3

다음 ?는 어떤 특별한 (그러나 반드시 denotable) 입력에 대한 설 것이다. (이것은 Abc<Xyz<?>>에 해당하지 않습니다.) 메서드 호출은 형식을 유추 할 수 있습니다. 따라서 "캡처 도우미"메서드를 사용하여 형식에 레이블을 지정할 수 있습니다 (감사합니다 @newacct).

public static void reverse(List<?> list) { 
    reverseImpl(list); 
} 
private static <T> void reverseImpl(List<T> list) { 

이제 로컬 유형을 T으로 정의 할 수 있습니다.

+0

@Tom, 고마워요.하지만 private 메서드에 목록 (형식 아님)을 전달하려고합니까? – Trent

+0

@Trent 예. 수정 됨. –

+1

+1 이것은 "캡처 도우미"라고하며, 와일드 카드로 서명하기에 충분하지만 내부적으로는 실제 매개 변수가 필요한 상황에 적합합니다. 다른 사람들은 내부 자료에 신경 쓰지 않아야하므로이 방법을 사용하여 숨길 수 있습니다. – newacct

관련 문제