List 데이터 구조에 어떻게 추가 할 수 있습니까?
다음과 같이 선언 된 목록이 있습니다.
List<? extends Number> foo3 = new ArrayList<Integer>();
foo3에 3을 추가하려고했습니다. 그러나 다음과 같은 오류 메시지가 나타납니다.
The method add(capture#1-of ? extends Number) in the type List<capture#1-of ?
extends Number> is not applicable for the arguments (ExtendsNumber)
미안하지만 할 수 없습니다.
와일드 카드 선언은 List<? extends Number> foo3
변수 foo3
가 특정 유형의 값이 아닌 유형 패밀리의 모든 값을 보유 할 수 있음을 의미합니다 . 이는 다음 중 하나가 법적 과제임을 의미합니다.
List<? extends Number> foo3 = new ArrayList<Number>; // Number "extends" Number
List<? extends Number> foo3 = new ArrayList<Integer>; // Integer extends Number
List<? extends Number> foo3 = new ArrayList<Double>; // Double extends Number
따라서, List foo3
위의 가능한 ArrayList
할당 후에 합법적 인 객체 유형을 추가 할 수 있습니다 .
- 에서를 가리킬 수
Integer
있기 때문에를 추가 할 수 없습니다 .foo3
List<Double>
- 에서를 가리킬 수
Double
있기 때문에를 추가 할 수 없습니다 .foo3
List<Integer>
- 에서를 가리킬 수
Number
있기 때문에를 추가 할 수 없습니다 .foo3
List<Integer>
List<? extends T>
어떤 종류의 객체 List
가 실제로 가리키는 지 보장 할 수 없기 때문에 객체를 추가 할 수 없으므로 객체가 해당 객체에서 허용되는지 보장 할 수 없습니다 List
. 유일한 "보증인"은 오직 그것으로부터 만 읽을 수 있고의 T
또는 서브 클래스를 얻게된다는 것 입니다 T
.
역 논리가 super
예를 들어에 적용됩니다 List<? super T>
. 이들은 합법적입니다.
List<? super Number> foo3 = new ArrayList<Number>; // Number is a "super" of Number
List<? super Number> foo3 = new ArrayList<Object>; // Object is a "super" of Number
당신은 특정 유형 T (예 : 읽을 수없는 Number
에서) List<? super T>
당신이 종류의 것을 보장 할 수 없기 때문에 List
정말 가리키는됩니다. 당신이 가진 유일한 "보장"당신이 유형의 값을 추가 할 수있다 T
(또는 서브 클래스를 T
지적되는 목록의 무결성을 위반하지 않고).
이것의 완벽한 예는 다음에 대한 서명입니다 Collections.copy()
.
public static <T> void copy(List<? super T> dest,List<? extends T> src)
src
목록 선언 extends
이 관련 목록 유형의 패밀리에서 목록을 전달하고 T 유형 또는 T의 서브 클래스 값을 생성하도록 보장 하는 방법에 주목하십시오 . 그러나 src
목록에 추가 할 수는 없습니다 .
dest
목록 선언 용도 super
나 관련 목록 유형의 가족에서 모든 목록을 전달할 수 있도록하고 아직도 내가 그 목록에 특정 유형 T의 값을 쓸 수 있습니다 보장합니다. 그러나 목록에서 읽으면 특정 유형 T 의 값을 읽을 수는 없습니다 .
이제 제네릭 와일드 카드 덕분에 단일 메소드로 이러한 호출을 수행 할 수 있습니다.
// copy(dest, src)
Collections.copy(new ArrayList<Number>(), new ArrayList<Number());
Collections.copy(new ArrayList<Number>(), new ArrayList<Integer());
Collections.copy(new ArrayList<Object>(), new ArrayList<Number>());
Collections.copy(new ArrayList<Object>(), new ArrayList<Double());
이 혼란스럽고 넓은 코드를 고려하여 뇌를 운동 시키십시오. 주석 처리 된 행은 불법이며 그 이유는 행의 맨 오른쪽에 표시됩니다 (일부 항목을 보려면 스크롤해야 함).
List<Number> listNumber_ListNumber = new ArrayList<Number>();
//List<Number> listNumber_ListInteger = new ArrayList<Integer>(); // error - can assign only exactly <Number>
//List<Number> listNumber_ListDouble = new ArrayList<Double>(); // error - can assign only exactly <Number>
List<? extends Number> listExtendsNumber_ListNumber = new ArrayList<Number>();
List<? extends Number> listExtendsNumber_ListInteger = new ArrayList<Integer>();
List<? extends Number> listExtendsNumber_ListDouble = new ArrayList<Double>();
List<? super Number> listSuperNumber_ListNumber = new ArrayList<Number>();
//List<? super Number> listSuperNumber_ListInteger = new ArrayList<Integer>(); // error - Integer is not superclass of Number
//List<? super Number> listSuperNumber_ListDouble = new ArrayList<Double>(); // error - Double is not superclass of Number
//List<Integer> listInteger_ListNumber = new ArrayList<Number>(); // error - can assign only exactly <Integer>
List<Integer> listInteger_ListInteger = new ArrayList<Integer>();
//List<Integer> listInteger_ListDouble = new ArrayList<Double>(); // error - can assign only exactly <Integer>
//List<? extends Integer> listExtendsInteger_ListNumber = new ArrayList<Number>(); // error - Number is not a subclass of Integer
List<? extends Integer> listExtendsInteger_ListInteger = new ArrayList<Integer>();
//List<? extends Integer> listExtendsInteger_ListDouble = new ArrayList<Double>(); // error - Double is not a subclass of Integer
List<? super Integer> listSuperInteger_ListNumber = new ArrayList<Number>();
List<? super Integer> listSuperInteger_ListInteger = new ArrayList<Integer>();
//List<? super Integer> listSuperInteger_ListDouble = new ArrayList<Double>(); // error - Double is not a superclass of Integer
listNumber_ListNumber.add(3); // ok - allowed to add Integer to exactly List<Number>
// These next 3 are compile errors for the same reason:
// You don't know what kind of List<T> is really
// being referenced - it may not be able to hold an Integer.
// You can't add anything (not Object, Number, Integer,
// nor Double) to List<? extends Number>
//listExtendsNumber_ListNumber.add(3); // error - can't add Integer to *possible* List<Double>, even though it is really List<Number>
//listExtendsNumber_ListInteger.add(3); // error - can't add Integer to *possible* List<Double>, even though it is really List<Integer>
//listExtendsNumber_ListDouble.add(3); // error - can't add Integer to *possible* List<Double>, especially since it is really List<Double>
listSuperNumber_ListNumber.add(3); // ok - allowed to add Integer to List<Number> or List<Object>
listInteger_ListInteger.add(3); // ok - allowed to add Integer to exactly List<Integer> (duh)
// This fails for same reason above - you can't
// guarantee what kind of List the var is really
// pointing to
//listExtendsInteger_ListInteger.add(3); // error - can't add Integer to *possible* List<X> that is only allowed to hold X's
listSuperInteger_ListNumber.add(3); // ok - allowed to add Integer to List<Integer>, List<Number>, or List<Object>
listSuperInteger_ListInteger.add(3); // ok - allowed to add Integer to List<Integer>, List<Number>, or List<Object>
You can't (without unsafe casts). You can only read from them.
The problem is that you don't know what exactly the list is a list of. It could be a list of any subclass of Number, so when you try to put an element into it, you don't know that the element actually fits into the list.
For example the List might be a list of Byte
s, so it would be an error to put a Float
into it.
"List '<' ? extends Number> is actually an upper bound wildcard !
The upper-bounded wildcard says that any class that extends Number or Number itself can be used as the formal parameter type: The problem stems from the fact that Java doesn’t know what type List really is. It has to be an EXACT and UNIQUE Type. I hope it helps :)
You could do this instead:
List<Number> foo3 = new ArrayList<Number>();
foo3.add(3);
It has been confusing to me even though I read answers here, until I found the comment by Pavel Minaev:
Note that List < ? extends Number > does not mean "list of objects of different types, all of which extend Number". It means "list of objects of a single type which extends Number"
After this I was able to understand BertF awesome explanation. List < ? extends Number > means ? could be of any type extending Number(Integer, Double, etc) and its not clearified in declaration ( List < ? extends Number > list ) that which of them it is, so when u wanna use add method its not known if the input is of the same type or not; what is the type at all?
So the elements of List < ? extends Number > could only be set when constructing.
Also note this: When we're using templates we are telling the compiler what type we're messing with. T for example holds that type for us, but not ? does the same
I gotta say.. This is one of the dirty ones to explain/learn
where extend list from 'Object' , you can use list.add and when want use list.get only need to cast Object to your Object;
참고URL : https://stackoverflow.com/questions/2776975/how-can-i-add-to-list-extends-number-data-structures
'programing tip' 카테고리의 다른 글
char은 기본적으로 서명 또는 서명되지 않습니까? (0) | 2020.06.18 |
---|---|
favicon.ico에 대한 링크 태그를 추가해야합니까? (0) | 2020.06.18 |
때때로 사용하기가 좋지 (0) | 2020.06.17 |
문자열의 첫 문자를 제거 (0) | 2020.06.17 |
Xcode에서 블록 주석을 작성하는 단축키가 있습니까? (0) | 2020.06.17 |