2012-01-23 2 views
16

here 등의 여러 위치에서 메서드 반환 형식에 바운딩 된 와일드 카드를 사용하는 것은 나쁜 생각입니다. 그러나, 나는 그것을 수업에서 피할 수있는 방법을 찾을 수 없다. 내가 놓친 게 있니? 영어 일부 변형에 출판물을 소비에 요약반환 형식의 Java 경계 와일드 카드

class EnglishReaderOfPublications { 

    private final Publication<? extends English> publication; 

    EnglishReaderOfPublications(Publication<? extends English> publication) { 
     this.publication = publication; 
    } 

    void readPublication() { 
     publication.omNomNom(); 
    } 

    Publication<? extends English> getPublication() { 
     return publication; 
    } 
} 

, 나는 수 있기를 원하는 클래스 :

상황은 다음과 같이 보입니다. 수업에서는 외부에서 발행물에 액세스 할 수 있어야하지만 이상적으로 getPublication의 발신자는 바운드 된 와일드 카드로 결과를 원하지 않습니다. 그들은 Publication<English>에 만족할 것입니다.

방법이 있습니까?

+0

Joshua Bloch의 "Effective Java"항목 28은 "리턴 유형으로 와일드 카드 유형을 사용하지 마십시오."라고 권장합니다. –

답변

12

바인딩 된 와일드 카드는 전염성이 있으며, 이는 링크 된 페이지가 애도하는 것처럼 보입니다. 글쎄, 거기에 부인할 수는 없지만 ... 큰 문제는 아닌 것 같아.

바운드 된 와일드 카드를 정확히 으로 반환하는 경우가 많으므로 전염성이 있습니다. JDK는 더 좋든 나쁘 든 (나쁘다고 말하지만 다른 비누 상자입니다 :)) 읽기 전용 컬렉션을위한 인터페이스가 없습니다. 내가 List<Foo>을 돌려주고 사람들이 수정하고 싶지 않다면 (아마도 Collections.unmodifiableList으로 감싸 졌을 수도 있습니다.), 내 귀환 서명에 선언 할 방법이 없습니다. 불쌍한 사람의 해결 방법으로 종종 나는 List<? extends Foo>을 반환 할 것입니다. 요소를 제거하거나 null을 삽입하여 해당 목록을 수정할 수는 있지만 적어도 add(new Foo())은 읽기 전용 일 수 있다는 사실을 알려 드릴 수 없습니다.

일반적으로 호출 사이트가 객체에 대한 액세스를 제한하려면 바운드 리턴 유형으로 반환하는 것이 가장 합리적입니다.

또 다른 예는 하나의 스레드가 생산자이고 다른 스레드가 소비자 인 다른 스레드로 전달하는 스레드 안전 큐입니다. 생산자에게 Queue<? super Foo>을 주면 상품을 넣으려는 의도가 분명합니다 (상품을 가져 가지 않음). 마찬가지로, 소비자에게 Queue<? extends Foo>을 주면 아이템을 가져 가고 (아이템을 넣지 않을 것임) 분명합니다.

4

클래스 선언에 바운드 형식 매개 변수를 사용할 수 있습니까?

class EnglishReaderOfPublications<E extends English> { ... 

그런 다음 와일드 카드 매개 변수가있는 모든 곳에서이 유형 매개 변수를 사용할 수 있습니다.

+1

내 경우에는 도움이 될지 모르겠다.나는이 영어 독자들의 이질적 컬렉션을 가지고 있으며, 그들이 관심을 가질 때 출판물을 얻고 싶습니다. 출판물은 '출판물 '입니다. 내 질문에 대한 이유는'간행물 '이'간행물 를 확장합니다. 나는 이것이 콜렉션 (왜 와일드 카드를 만족하지만 실제 타입을 위반 한 것을 추가 할 수있다)을 얻었지만, 출판물은 런타임에 언어를 변경할 수있는 방법을 제공하지 않기 때문에 나는 이것이 왜 그렇게 느껴지는 지 알지 못한다. 잘못된. – thehouse

0

"이상적으로 getPublication을 호출 한 사용자는 바운드 된 와일드 카드로 결과를 얻지 않으므로 Publication<English>에 만족할 것입니다."

왜 "원하지 않습니까?" 그들은 Publication<? extends English>으로 "행복 할"것입니까? 질문은이 호출자가이 게시 객체로 수행해야하는 작업입니다. 그들이하는 일로 인해 모든 일이 끝나면, Publication<? extends English>이면 충분하며, 더 일반적이기 때문에 더 좋습니다. 그러나 물건을 넣어야 할 경우 Publication<? extends English>을 사용할 수 없습니다.

+0

기본적으로 오염 때문에. 호출 코드는'getPublication'을 호출하여 각 발행물을 가져 와서'Set'에 넣습니다. 그 순간 나는'Set >를 확장하면 코드를 읽기가 어려워집니다. 어쩌면 내가 까다 롭습니다. – thehouse

+0

읽기가 어렵지만 더 일반적입니다. 불행히도 구문이 길다는 것에 동의합니다. 이러한 클래스/메소드가 자신의 코드에있는 경우, 더 잘 읽고 싶다면 읽기 쉬운 접근 방식을 사용할 수 있습니다. 다른 사람들이 읽을 것으로 기대하는 API를 작성하는 경우에는 와일드 카드를 올바르게 가져 오는 것이 매우 중요합니다. 누군가가 출판물을 가지고 있다면 수치 스러울 것입니다. 영어>를 확장하여 "게으른"(또는 "예쁜", 원한다면) 타이핑 때문에 API에서 사용할 수 없습니다. – yshavit