Java Generics (와일드 카드)
Java의 일반 와일드 카드에 대한 몇 가지 질문이 있습니다.
List<? extends T>
과 의 차이점은 무엇입니까List<? super T>
?제한 와일드 카드 란 무엇이며 제한되지 않은 와일드 카드 란 무엇입니까?
첫 번째 질문에서 <? extends T>
및 <? super T>
바운드 와일드 카드의 예입니다. 제한되지 않은 와일드 카드는 다음과 같 <?>
으며 기본적으로 의미 <? extends Object>
합니다. 느슨하게 제네릭이 모든 유형이 될 수 있음을 의미합니다. 경계 와일드 카드 ( <? extends T>
또는 <? super T>
) 그 어느한다는 것을 말하며 종류에 제한을 둔다 연장 특정 유형 ( <? extends T>
상한로 알려져있다), 또는 특정 유형 (의 조상이어야 <? super T>
하한이라고 함) .
Java Tutorials에는 Wildcards 및 More 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 B
B가 어떤 유형 인 경우 와 같습니다 . 즉, 유형을 알 수 없지만 "바운드"를 배치 할 수 있습니다. 이 경우 B의 하위 클래스 인 일부 클래스에 의해 제한됩니다.
조쉬 블로흐도 사용하는 경우의 좋은 설명이 있습니다 super
및 extends
이의 비디오 이야기 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의 수퍼 클래스 개체 제외) 만 허용합니다.
일반적으로
If a structure contains elements with a type of the form
? extends E
, we can get elements out of the structure, but we cannot put elements into the structure
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]");
To put elements into the structure we need another kind of wildcard called 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));
}
}
Pre Requirements
public class A { }
public class B extends A { }
public class C extends A { }
List<A> listA = new ArrayList<A>();
List<B> listB = new ArrayList<B>();
The problem
listB = listA; //not compiled
listA = listB; //not compiled
listB = listA;
In listA you can insert objects that are either instances of A, or subclasses of A (B and C). When you make listB = listA
you could risk that listA
contains non-B objects. When you then try to get objects out of listB
you could risk to get non-B objects out (e.g. an A or a C). That breaks the contract of the listB
variable declaration.
listA = listB;
If you could make this assignment, it would be possible to insert A and C instances into the List pointed to by listB
. You could do that via the listA
reference, which is declared to be of List. Thus you could insert non-B objects into a list declared to hold B (or B subclass) instances.
The problem
As you see the problem is in assignments. For example you can not create a method that processes List's elements that are relatives, in this manner.
The solution
Generic Wildcards to the rescue
You should use List <? extends A>
aka upper bound aka covariance aka producers if you are going to read .get() from the list
When you know that the instances in the collection are of instances of A or subclasses of A, it is safe to read the instances of the collection and cast them to A instances.
You can not insert elements into the list, because you don't know if the list is typed to the class A, B or C.
You should use List <? super A>
aka lower bound aka contravariance aka consumers if you are going to insert .add() into the list
When you know that the list is typed to either A, or a superclass of A, it is safe to insert instances of A or subclasses of A (e.g. B or C) into the list.
You cannot read from the list though, except if it casts the read objects to Object. The elements already present in the list could be of any type that is either an A or superclass of A, but it is not possible to know exactly which class it is.
Please read more here
Generic wildcards are created to make methods that operate on Collection more reusable.
For example, if a method has a parameter List<A>
, we can only give List<A>
to this method. It is a waste for this method's funtion under some circumstances:
- If this method only reads objects from
List<A>
, then we should be allowed to giveList<A-sub>
to this method. (Because A-sub IS a A) - If this method only inserts objects to
List<A>
, then we should be allowed to giveList<A-super>
to this method. (Because A IS a A-super)
참고URL : https://stackoverflow.com/questions/252055/java-generics-wildcards
'program story' 카테고리의 다른 글
객체의 Javascript 배열 내에 객체 값이 있는지 확인하고 배열에 새 객체를 추가하지 않는 경우 (0) | 2020.08.09 |
---|---|
문자열에 새 줄을 만들지 않고 긴 템플릿 리터럴 줄을 여러 줄로 줄 바꿈 (0) | 2020.08.09 |
PHP에서 동적으로 선택된 클래스 상수 값 가져 오기 (0) | 2020.08.09 |
프로그래밍 방식으로 브라우저 캐시를 비우는 방법은 무엇입니까? (0) | 2020.08.09 |
ssh : 호스트 이름 [hostname]을 확인할 수 없습니다 : nodename 또는 servname이 제공되었거나 알 수 없음 (0) | 2020.08.09 |