Java Generics (와일드 카드)


109

Java의 일반 와일드 카드에 대한 몇 가지 질문이 있습니다.

  1. List<? extends T>과 의 차이점은 무엇입니까 List<? super T>?

  2. 제한 와일드 카드 란 무엇이며 제한되지 않은 와일드 카드 란 무엇입니까?


하는 경우에는 테드 가오의 대답은 (는 링크 만 이후) 삭제, 여기에 있습니다 블로그 포스트 가 연결되는.
royhowie 2015

답변:


123

첫 번째 질문에서 <? extends T><? super T>경계 와일드 카드의 예입니다. 제한되지 않은 와일드 카드는 다음과 같 <?>으며 기본적으로 의미 <? extends Object>합니다. 느슨하게 제네릭이 모든 유형이 될 수 있음을 의미합니다. 경계 와일드 카드 ( <? extends T>또는 <? super T>) 그 어느한다는 것을 말하며 종류에 제한을 둔다 연장 특정 유형 ( <? extends T>상한로 알려져있다), 또는 특정 유형 (의 조상이어야 <? super T>하한이라고 함) .

Java Tutorials에는 WildcardsMore Fun with Wildcards 기사에서 제네릭에 대한 꽤 좋은 설명이 있습니다.


제대로하기 위해서 A <B와 B <C라면 : <A extends C>가 틀렸나 요?
Pablo Fernandez

A <B에 의해 A가 B를 확장하고 A가 C를 확장한다는 뜻입니다. 와일드 카드 구문에서는 사용하지 않겠지 만 <? C>를 확장하여 선택을 A 또는 B로 제한합니다.
Bill the Lizard

그리고 그 경우에 <? super C> 차이점은 무엇입니까?
Pablo Fernandez

3
Java Generics에 대한 또 다른 참조를 추천하고 싶었습니다. angelikalanger.com/GenericsFAQ/JavaGenericsFAQ.html
Zach Scrivena

3
@Pablo : <? super C>유형이 C유형 계층 구조에서 위의 항목으로 제한됨을 의미합니다 . (매우 늦게 답장을 드려 죄송합니다. 2 년 전에 댓글 알림이 없었던 것 같습니다.)
Bill the Lizard

49

클래스 계층 구조 A가있는 경우 B는 A의 하위 클래스이고 C와 D는 모두 아래와 같이 B의 하위 클래스입니다.

class A {}
class B extends A {}
class C extends B {}
class D extends B {}

그때

List<? extends A> la;
la = new ArrayList<B>();
la = new ArrayList<C>();
la = new ArrayList<D>();

List<? super B> lb;
lb = new ArrayList<A>(); //fine
lb = new ArrayList<C>(); //will not compile

public void someMethod(List<? extends B> lb) {
    B b = lb.get(0); // is fine
    lb.add(new C()); //will not compile as we do not know the type of the list, only that it is bounded above by B
}

public void otherMethod(List<? super B> lb) {
    B b = lb.get(0); // will not compile as we do not know whether the list is of type B, it may be a List<A> and only contain instances of A
    lb.add(new B()); // is fine, as we know that it will be a super type of A 
}

제한된 와일드 카드는 ? extends BB가 어떤 유형 인 경우 와 같습니다 . 즉, 유형을 알 수 없지만 "바운드"를 배치 할 수 있습니다. 이 경우 B의 하위 클래스 인 일부 클래스에 의해 제한됩니다.


List가 클래스 B의 부모 클래스 인 유형을 수락 한다고 가정 List<? super B>합니다 . C와 D가 흠 컴파일하지 않는 이유는 무엇입니까?
Volkan Güven

38

조쉬 블로흐도 사용하는 경우의 좋은 설명이 있습니다 superextends이의 비디오 이야기 IO 구글 그가 언급 생산자 extends소비자super 니모닉.

프레젠테이션 슬라이드에서 :

대량 메서드를 추가하려는 경우 Stack<E>

void pushAll(Collection<? extends E> src);

– src는 E 생산자입니다.

void popAll(Collection<? super E> dst);

– dst는 E 소비자입니다.


Bloch의 책을 읽었지만이 특별한 경우에 extends와 super의 차이점을 알 수 없습니다.
Pablo Fernandez

비디오를 보면 꽤 분명하다고 생각합니다. 또한 "List <? extends T>와 List <? super T>의 차이점은 무엇입니까?"에 대해 또 다른 질문을해야한다고 생각합니다. (그렇다면 여기에서 링크를 추가하십시오.)
blank

2
침대-완벽하고 독립적으로 만들기 위해이 답변에 예제를 포함하지 마십시오. 링크는 일시적입니다.
James Schek

3

유형 매개 변수에 전달할 수있는 유형의 종류를 제한하려는 경우가있을 수 있습니다. 예를 들어 숫자에 대해 작동하는 메서드는 Number 또는 해당 하위 클래스의 인스턴스 만 허용하려고 할 수 있습니다. 이것이 경계 유형 매개 변수의 용도입니다.

Collection<? extends MyObject> 

즉, MyObject와 IS-A 관계를 가진 모든 개체 (즉, myObject의 유형 인 모든 개체 또는 MyObject의 모든 하위 클래스의 개체라고 말할 수 있음) 또는 MyObject 클래스의 개체를 허용 할 수 있습니다.

예를 들면 :

class MyObject {}

class YourObject extends MyObject{}

class OurObject extends MyObject{}

그때,

Collection<? extends MyObject> myObject; 

MyObject 또는 MyObject의 자식 (즉, OurObject, YourObject 또는 MyObject 유형의 모든 개체, MyObject의 수퍼 클래스 개체 제외) 만 허용합니다.


1

일반적으로

구조에 형식 유형의 요소가 포함되어있는 경우 구조에서 요소를 ? extends E가져올 수 있지만 구조에 요소를 넣을 수는 없습니다.

List<Integer> ints = new ArrayList<Integer>();
ints.add(1);
ints.add(2);
List<? extends Number> nums = ints;
nums.add(3.14); // compile-time error
assert ints.toString().equals("[1, 2, 3.14]"); 

구조에 요소를 넣으려면라는 다른 종류의 와일드 카드가 필요합니다 Wildcards with super.

 List<Object> objs = Arrays.<Object>asList(2, 3.14, "four");
    List<Integer> ints = Arrays.asList(5, 6);
    Collections.copy(objs, ints);
    assert objs.toString().equals("[5, 6, four]");

    public static <T> void copy(List<? super T> dst, List<? extends T> src) {
          for (int i = 0; i < src.size(); i++) {
                dst.set(i, src.get(i));
         }
    }

1

컬렉션에서 작동하는 메서드를보다 재사용 가능하게 만들기 위해 일반 와일드 카드가 생성됩니다.

예를 들어 메소드에 매개 변수가있는 경우이 메소드 List<A>에만 제공 할 수 있습니다 List<A>. 어떤 상황에서는이 방법의 기능이 낭비입니다.

  1. 이 메서드가에서만 객체를 읽는다면이 메서드 List<A>에 제공 List<A-sub>할 수 있어야합니다 . (A-sub가 A이기 때문에)
  2. 이 메서드가 객체를에 삽입하기 만하면이 메서드 List<A>에 제공 List<A-super>할 수 있습니다 . (A는 A 슈퍼이기 때문에)
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.