[java] Java Generics (와일드 카드)

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

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

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



답변

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

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


답변

클래스 계층 구조 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의 하위 클래스 인 일부 클래스에 의해 제한됩니다.


답변

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

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

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

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

– src는 E 생산자입니다.

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

– dst는 E 소비자입니다.


답변

유형 매개 변수에 전달할 수있는 유형의 종류를 제한하려는 경우가있을 수 있습니다. 예를 들어 숫자에 대해 작동하는 메서드는 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의 수퍼 클래스 개체 제외) 만 허용합니다.


답변

일반적으로

구조에 형식 유형의 요소가 포함되어있는 경우 구조에서 요소를 ? 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));
         }
    }


답변

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

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

  1. 이 메서드가에서만 객체를 읽는다면이 메서드 List<A>에 제공 List<A-sub>할 수 있어야합니다 . (A-sub가 A이기 때문에)
  2. 이 메서드가 객체를에 삽입하기 만하면이 메서드 List<A>에 제공 List<A-super>할 수 있습니다 . (A는 A 슈퍼이기 때문에)

답변