Nice programing

차이

nicepro 2020. 9. 29. 18:41
반응형

차이 자바에서 [중복]


이 질문에 이미 답변이 있습니다.

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

내가 사용하는 데 사용 List<? extends T>하지만, 내가 그것에 요소를 추가 할 수 없습니다 list.add(e)(가) 반면, List<? super T>않습니다.


extends

와일드 카드 선언은 List<? extends Number> foo3다음 중 하나가 법적 할당임을 의미합니다.

List<? extends Number> foo3 = new ArrayList<Number>();  // Number "extends" Number (in this context)
List<? extends Number> foo3 = new ArrayList<Integer>(); // Integer extends Number
List<? extends Number> foo3 = new ArrayList<Double>();  // Double extends Number
  1. 읽기 -위의 가능한 할당이 주어지면 어떤 유형의 객체를 읽을 수 있습니까 List foo3?

    • 또는의 하위 클래스 Numberfoo3포함 하도록 할당 할 수있는 목록 중 하나를 읽을 수 있습니다 .NumberNumber
    • 가리킬 수 Integer있기 때문에 읽을 수 없습니다 .foo3List<Double>
    • 가리킬 수 Double있기 때문에 읽을 수 없습니다 .foo3List<Integer>
  2. 쓰기 감안할 때 당신이 추가 할 수있는 개체의 유형 가능한 과제, 위 - List foo3그 법적 될 모든 위의 수 ArrayList: 과제

    • 당신은 추가 할 수 없습니다 Integer때문에이 foo3가리키는 수 있습니다 List<Double>.
    • 당신은 추가 할 수 없습니다 Double때문에이 foo3가리키는 수 있습니다 List<Integer>.
    • 당신은 추가 할 수 없습니다 Number때문에이 foo3가리키는 수 있습니다 List<Integer>.

List<? extends T>어떤 종류의 객체를 List실제로 가리키는 지 보장 할 수 없기 때문에 어떤 객체도 추가 할 수 없습니다 . 따라서 객체가 .NET에서 허용된다는 것을 보장 할 수 없습니다 List. 유일한 "보증"은 읽기만 가능하며 T또는의 하위 클래스를 얻을 수 있다는 것 입니다 T.

super

이제 고려하십시오 List <? super T>.

와일드 카드 선언은 List<? super Integer> foo3다음 중 하나가 법적 할당임을 의미합니다.

List<? super Integer> foo3 = new ArrayList<Integer>();  // Integer is a "superclass" of Integer (in this context)
List<? super Integer> foo3 = new ArrayList<Number>();   // Number is a superclass of Integer
List<? super Integer> foo3 = new ArrayList<Object>();   // Object is a superclass of Integer
  1. 읽기 -위의 가능한 할당이 주어지면 다음에서 읽을 때 어떤 유형의 객체를받을 수 있는지 보장합니다 List foo3.

    • 또는을 가리킬 수 Integer있기 때문에 보장되지 않습니다 .foo3List<Number>List<Object>
    • 가리킬 수 Number있기 때문에 a가 보장되지 않습니다 .foo3List<Object>
    • 유일한 보증은 당신이의 인스턴스를 얻을 것입니다 Object또는 서브 클래스를 Object(하지만 서브 클래스가 무엇인지 모른다).
  2. 쓰기 감안할 때 당신이 추가 할 수있는 개체의 유형 가능한 과제, 위 - List foo3그 법적 될 모든 위의 수 ArrayList: 과제

    • 는 위 목록에서 허용 Integer되므로 추가 할 수 있습니다 Integer.
    • 위 목록에서 Integer의 서브 클래스의 인스턴스 Integer가 허용 되기 때문에의 서브 클래스의 인스턴스를 추가 할 수 있습니다 .
    • 당신은 추가 할 수 없습니다 Double때문에이 foo3가리키는 수 있습니다 ArrayList<Integer>.
    • 당신은 추가 할 수 없습니다 Number때문에이 foo3가리키는 수 있습니다 ArrayList<Integer>.
    • 당신은 추가 할 수 없습니다 Object때문에이 foo3가리키는 수 있습니다 ArrayList<Integer>.

PECS

PECS : "Producer Extends, Consumer Super"를 기억하십시오 .

  • "Producer Extends" - List을 생성하기 위해 를 필요로하는 경우 T( T목록에서 s 를 읽고 자 함 ) ? extends T, 예를 들어 List<? extends Integer>. 그러나이 목록에 추가 할 수 없습니다.

  • "Consumer Super" - List을 소비 해야하는 경우 T( T목록에 s 를 작성하려는 ? super T경우) 예를 들어 List<? super Integer>. 그러나이 목록에서 읽을 수있는 개체 유형에 대한 보장은 없습니다.

  • 목록에서 읽고 쓸 필요가있는 경우 와일드 카드없이 정확하게 선언해야합니다 (예 : List<Integer>.

Java Generics FAQ에서이 예를 참고 하십시오 . 소스 목록 src(생산 목록)이를 사용 extends하고 대상 목록 dest(소비 목록)이 다음을 사용 하는 방법에 유의하십시오 super.

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

또한 어떻게 목록에 추가 할 수 있습니까?를 참조하십시오 . Number> 데이터 구조를 확장합니까?


이 계층 구조가 있다고 상상해보십시오.

여기에 이미지 설명 입력

1. 확장

쓰기로

    List<? extends C2> list;

당신은 그 말을 list(예를 들어) 유형의 객체 참조 할 수있을 것이다 ArrayList제네릭 형식 7 개 중 하나입니다 아형 의를 C2( C2포함) :

  1. C2 : new ArrayList<C2>(); , (C2 또는 하위 유형을 저장할 수있는 객체) 또는
  2. D1 : new ArrayList<D1>(); , (D1 또는 하위 유형을 저장할 수있는 객체) 또는
  3. D2 : new ArrayList<D2>(); , (D2 또는 하위 유형을 저장할 수있는 객체) 또는 ...

등등. 7 가지 다른 경우 :

    1) new ArrayList<C2>(): can store C2 D1 D2 E1 E2 E3 E4
    2) new ArrayList<D1>(): can store    D1    E1 E2  
    3) new ArrayList<D2>(): can store       D2       E3 E4
    4) new ArrayList<E1>(): can store          E1             
    5) new ArrayList<E2>(): can store             E2             
    6) new ArrayList<E3>(): can store                E3             
    7) new ArrayList<E4>(): can store                   E4             

가능한 각 경우에 대해 "저장 가능한"유형 세트가 있습니다. 여기서 그래픽으로 표현 된 7 (빨간색) 세트

여기에 이미지 설명 입력

보시다시피 모든 경우에 공통적 인 안전한 유형 은 없습니다 .

  • 그럴 수 list.add(new C2(){});있기 때문에 당신은 할 수 없습니다list = new ArrayList<D1>();
  • 그럴 수 list.add(new D1(){});있기 때문에 당신은 할 수 없습니다list = new ArrayList<D2>();

등등.

2. 슈퍼

쓰기로

    List<? super C2> list;

당신은 그 말을 list(예를 들어) 유형의 객체 참조 할 수있을 것이다 ArrayList제네릭 형식 7 개 중 하나입니다 슈퍼 타입 의를 C2( C2포함) :

  • A1 : new ArrayList<A1>(); , (A1 또는 하위 유형을 저장할 수있는 객체) 또는
  • A2 : new ArrayList<A2>(); , (A2 또는 하위 유형을 저장할 수있는 객체) 또는
  • A3 : new ArrayList<A3>(); , (A3 또는 하위 유형을 저장할 수있는 객체) 또는 ...

등등. 7 가지 다른 경우 :

    1) new ArrayList<A1>(): can store A1          B1 B2       C1 C2    D1 D2 E1 E2 E3 E4
    2) new ArrayList<A2>(): can store    A2          B2       C1 C2    D1 D2 E1 E2 E3 E4
    3) new ArrayList<A3>(): can store       A3          B3       C2 C3 D1 D2 E1 E2 E3 E4
    4) new ArrayList<A4>(): can store          A4       B3 B4    C2 C3 D1 D2 E1 E2 E3 E4
    5) new ArrayList<B2>(): can store                B2       C1 C2    D1 D2 E1 E2 E3 E4
    6) new ArrayList<B3>(): can store                   B3       C2 C3 D1 D2 E1 E2 E3 E4
    7) new ArrayList<C2>(): can store                            C2    D1 D2 E1 E2 E3 E4

가능한 각 경우에 대해 "저장 가능한"유형 세트가 있습니다. 여기서 그래픽으로 표현 된 7 (빨간색) 세트

여기에 이미지 설명 입력

당신이 볼 수 있듯이, 우리가 일곱이 개 안전 유형 모든 경우에 공통적 : C2, D1, D2, E1, E2, E3, E4.

  • 당신은 할 수 list.add(new C2(){});있기 때문에,에 관계없이 우리가 참조하고 목록의 종류, C2허용
  • 당신은 할 수 list.add(new D1(){});있기 때문에,에 관계없이 우리가 참조하고 목록의 종류, D1허용

등등. 이러한 유형은 type에서 시작하는 계층 구조에 해당합니다 C2.

메모

몇 가지 테스트를하려면 여기에 완전한 계층 구조가 있습니다.

interface A1{}
interface A2{}
interface A3{}
interface A4{}

interface B1 extends A1{}
interface B2 extends A1,A2{}
interface B3 extends A3,A4{}
interface B4 extends A4{}

interface C1 extends B2{}
interface C2 extends B2,B3{}
interface C3 extends B3{}

interface D1 extends C1,C2{}
interface D2 extends C2{}

interface E1 extends D1{}
interface E2 extends D1{}
interface E3 extends D2{}
interface E4 extends D2{}

나는 @Bert F의 대답을 좋아하지만 이것이 내 두뇌가 보는 방식입니다.

손에 X가 있습니다. 내가 원하는 경우 연락처 목록 내 X 내가 IE에서 어떤을 쓰기로 업 캐스팅 할 수있는 X의 목록 또는 물건의 목록이 될 필요가 있음, 목록에 내 X를 슈퍼 클래스 X의를 ...

List<? super   X>

내가 목록을 얻고 그 목록 에서 X 읽고 싶다면 , 그것은 X의 목록이거나 내가 읽을 때 X로 업 캐스트 될 수있는 것들의 목록, 즉 X 확장하는 모든 것입니다.

List<? extends X>

도움이 되었기를 바랍니다.


Bert F의 답변을 바탕으로 내 이해를 설명하고 싶습니다.

다음과 같이 3 개의 클래스가 있다고 가정 해 봅시다.

public class Fruit{}

public class Melon extends Fruit{}

public class WaterMelon extends Melon{}

여기 우리는

List<? extends Fruit> fruitExtendedList = …

//Says that I can be a list of any object as long as this object extends Fruit.

Ok 이제 fruitExtendedList에서 값을 가져옵니다.

Fruit fruit = fruitExtendedList.get(position)

//This is valid as it can only return Fruit or its subclass.

다시 시도 해보자

Melon melon = fruitExtendedList.get(position)

//This is not valid because fruitExtendedList can be a list of Fruit only, it may not be 
//list of Melon or WaterMelon and in java we cannot assign sub class object to 
//super class object reference without explicitly casting it.

같은 경우

WaterMelon waterMelon = fruitExtendedList.get(position)

이제 fruitExtendedList에 객체를 설정해 보겠습니다.

과일 개체 추가

fruitExtendedList.add(new Fruit())

//This in not valid because as we know fruitExtendedList can be a list of any 
//object as long as this object extends Fruit. So what if it was the list of  
//WaterMelon or Melon you cannot add Fruit to the list of WaterMelon or Melon.

멜론 개체 추가

fruitExtendedList.add(new Melon())

//This would be valid if fruitExtendedList was the list of Fruit but it may 
//not be, as it can also be the list of WaterMelon object. So, we see an invalid 
//condition already.

마지막으로 WaterMelon 개체를 추가해 보겠습니다.

fruitExtendedList.add(new WaterMelon())

//Ok, we got it now we can finally write to fruitExtendedList as WaterMelon 
//can be added to the list of Fruit or Melon as any superclass reference can point 
//to its subclass object.

그러나 누군가가 새로운 유형의 레몬을 만들기로 결정하면 SaltyLemon이

public class SaltyLemon extends Lemon{}

이제 fruitExtendedList는 Fruit, Melon, WaterMelon 또는 SaltyLemon의 목록이 될 수 있습니다.

그래서 우리의 진술

fruitExtendedList.add(new WaterMelon())

또한 유효하지 않습니다.

기본적으로 우리는 fruitExtendedList에 아무것도 쓸 수 없다고 말할 수 있습니다.

이것은 요약 List<? extends Fruit>

이제 보자

List<? super Melon> melonSuperList= …

//Says that I can be a list of anything as long as its object has super class of Melon.

이제 melonSuperList에서 값을 얻으십시오.

Fruit fruit = melonSuperList.get(position)

//This is not valid as melonSuperList can be a list of Object as in java all 
//the object extends from Object class. So, Object can be super class of Melon and 
//melonSuperList can be a list of Object type

마찬가지로 Melon, WaterMelon 또는 다른 개체는 읽을 수 없습니다.

하지만 객체 유형 인스턴스를 읽을 수 있습니다.

Object myObject = melonSuperList.get(position)

//This is valid because Object cannot have any super class and above statement 
//can return only Fruit, Melon, WaterMelon or Object they all can be referenced by
//Object type reference.

이제 melonSuperList에서 값을 설정해 보겠습니다.

개체 유형 개체 추가

melonSuperList.add(new Object())

//This is not valid as melonSuperList can be a list of Fruit or Melon.
//Note that Melon itself can be considered as super class of Melon.

과일 유형 개체 추가

melonSuperList.add(new Fruit())

//This is also not valid as melonSuperList can be list of Melon

멜론 유형 개체 추가

melonSuperList.add(new Melon())

//This is valid because melonSuperList can be list of Object, Fruit or Melon and in 
//this entire list we can add Melon type object.

WaterMelon 유형 개체 추가

melonSuperList.add(new WaterMelon())

//This is also valid because of same reason as adding Melon

요약하면 melonSuperList에 Melon 또는 그 하위 클래스를 추가하고 Object 유형 객체 만 읽을 수 있습니다.


super는 하한이고 extends는 상한입니다.

http://download.oracle.com/javase/tutorial/extra/generics/morefun.html 에 따르면 :

해결책은 우리가 아직 보지 못한 경계 와일드 카드의 형태를 사용하는 것입니다 : 하한이있는 와일드 카드입니다. 구문? super T는 T의 상위 유형 (또는 T 자체; 상위 유형 관계가 반사적임을 기억하십시오) 인 알 수없는 유형을 나타냅니다. 우리가 사용했던 경계 와일드 카드의 이중입니다. T를 확장하여 T의 하위 유형 인 알 수없는 유형을 나타냅니다.


차이점을 시각화하고 싶습니다. 다음이 있다고 가정합니다.

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

List<? extends T> -읽기 및 할당 :

|-------------------------|-------------------|---------------------------------|
|         wildcard        |        get        |              assign             |
|-------------------------|-------------------|---------------------------------|
|    List<? extends C>    |    A    B    C    |   List<C>                       |
|-------------------------|-------------------|---------------------------------|
|    List<? extends B>    |    A    B         |   List<B>   List<C>             |
|-------------------------|-------------------|---------------------------------|
|    List<? extends A>    |    A              |   List<A>   List<B>   List<C>   |
|-------------------------|-------------------|---------------------------------|

List<? super T> -쓰기 및 할당 :

|-------------------------|-------------------|-------------------------------------------|
|         wildcard        |        add        |                   assign                  |
|-------------------------|-------------------|-------------------------------------------|
|     List<? super C>     |    C              |  List<Object>  List<A>  List<B>  List<C>  |
|-------------------------|-------------------|-------------------------------------------|
|     List<? super B>     |    B    C         |  List<Object>  List<A>  List<B>           |
|-------------------------|-------------------|-------------------------------------------|
|     List<? super A>     |    A    B    C    |  List<Object>  List<A>                    |
|-------------------------|-------------------|-------------------------------------------|

모든 경우 :

  • 와일드 카드에 관계없이 항상 목록에서 가져올 수 있습니다 Object.
  • 와일드 카드에 관계없이 언제든지 변경 가능한 목록에 추가 할 수 있습니다 null.

extends사용 하면 컬렉션에서만 얻을 수 있습니다. 그것에 넣을 수 없습니다. 또한 super 는 get과 put을 모두 허용 하지만 get 중 반환 유형은 ? 슈퍼 T .


목록에 항목 추가 :

  • 목록 extends X>null목록을 제외하고는 아무것도 추가 할 수 없습니다 .

  • 목록 super X> 는 X (X 또는 하위 유형) 또는 null 인 모든 것을 추가 할 수 있습니다.

목록에서 항목 가져 오기 :

  • 언제에서 항목 가져 목록 <? X>를 확장하면 X 유형의 변수 또는 Object를 포함한 X의 수퍼 유형에 할당 할 수 있습니다.
  • 언제에서 항목 가져 목록 <? super X> , 당신은 유형의 변수에만 할당 할 수 있습니다 Object.

몇 가지 예 :

    List<? extends Number> list1 = new ArrayList<Integer>();
    list1.add(null);  //OK
    Number n = list1.get(0);  //OK
    Serializable s = list1.get(0);  //OK
    Object o = list1.get(0);  //OK

    list1.add(2.3);  //ERROR
    list1.add(5);  //ERROR
    list1.add(new Object());  //ERROR
    Integer i = list1.get(0);  //ERROR

    List<? super Number> list2 = new ArrayList<Number>();
    list2.add(null);  //OK
    list2.add(2.3);  //OK
    list2.add(5);  //OK
    Object o = list2.get(0);  //OK

    list2.add(new Object());  //ERROR
    Number n = list2.get(0);  //ERROR
    Serializable s = list2.get(0);  //ERROR
    Integer i = list2.get(0);  //ERROR

당신은이 이유를 이해하기 위의 모든 답변을 통해 갈 수 .add()제한됩니다 '<?>', '<? extends>'그리고 부분적으로 '<? super>'.

그러나 기억하고 싶고 매번 답을 탐구하고 싶지 않다면 여기에 모든 결론이 있습니다.

List<? extends A>이 모든 동의 의미 ListA의와 서브 클래스를 A. 그러나이 목록에는 아무것도 추가 할 수 없습니다. 유형의 개체도 아닙니다 A.

List<? super A>의 모든 목록 A및 수퍼 클래스를 허용합니다 A. 유형의 개체 A와 해당 하위 클래스를 추가 할 수 있습니다 .


여기서 가장 혼란스러운 점은 지정하는 유형 제한이 무엇이든 할당이 한 가지 방식으로 만 작동한다는 것입니다.

baseClassInstance = derivedClassInstance;

당신은 그렇게 생각 Integer extends Number하고는 IntegerA와 할 것 <? extends Number>,하지만 컴파일러는 당신을 말할 것이다 <? extends Number> cannot be converted to Integer(인간의 말투에서, 그 이 수를 확장 아무것도 정수로 변환 할 수 있다는 잘못된 것입니다 ) :

class Holder<T> {
    T v;
    T get() { return v; }
    void set(T n) { v=n; }
}
class A {
    public static void main(String[]args) {
        Holder<? extends Number> he = new Holder();
        Holder<? super Number> hs = new Holder();

        Integer i;
        Number n;
        Object o;

        // Producer Super: always gives an error except
        //       when consumer expects just Object
        i = hs.get(); // <? super Number> cannot be converted to Integer
        n = hs.get(); // <? super Number> cannot be converted to Number
                      // <? super Number> cannot be converted to ... (but
                      //       there is no class between Number and Object)
        o = hs.get();

        // Consumer Super
        hs.set(i);
        hs.set(n);
        hs.set(o); // Object cannot be converted to <? super Number>

        // Producer Extends
        i = he.get(); // <? extends Number> cannot be converted to Integer
        n = he.get();
        o = he.get();

        // Consumer Extends: always gives an error
        he.set(i); // Integer cannot be converted to <? extends Number>
        he.set(n); // Number cannot be converted to <? extends Number>
        he.set(o); // Object cannot be converted to <? extends Number>
    }
}

hs.set(i);Integer슈퍼 클래스로 변환 할 수Number 있기 때문에 괜찮습니다 ( true가 아닌 Integer의 슈퍼 클래스 이기 때문 Number이 아닙니다).

편집은 소비자가 확장 및 프로듀서 슈퍼에 대한 코멘트를 추가 -가, 대응, 지정하지 않는 때문에 의미없는 아무것도 그냥 Object. CEPS는 유용하지 않기 때문에 PECS를 기억하는 것이 좋습니다.


일반 와일드 카드는 두 가지 주요 요구 사항을 대상으로합니다.

일반 컬렉션에서 읽기 일반 컬렉션에 삽입 일반 와일드 카드를 사용하여 컬렉션 (변수)을 정의하는 세 가지 방법이 있습니다. 이것들은:

List<?>           listUknown = new ArrayList<A>();
List<? extends A> listUknown = new ArrayList<A>();
List<? super   A> listUknown = new ArrayList<A>();

List<?>알 수없는 유형으로 입력 된 목록을 의미합니다. List<A>, a List<B>, a List<String>이 될 수 있습니다 .

List<? extends A>class A, 또는의 인스턴스 인 개체 목록을 의미합니다 subclasses of A(예 : B 및 C). List<? super A>목록이 A class, 또는에 입력되었음을 의미합니다 superclass of A.

더 읽기 : http://tutorials.jenkov.com/java-generics/wildcards.html


Extends 및 Super를 사용하는 경우

와일드 카드는 메소드 매개 변수에서 가장 유용합니다. 메소드 인터페이스에서 필요한 유연성을 허용합니다.

사람들은 종종 extends를 사용할 때와 super bound를 사용할 때 혼동합니다. 경험의 법칙은 get-put 원칙입니다. 매개 변수화 된 컨테이너에서 무언가를 얻는 경우 extends를 사용하십시오.

int totalFuel(List<? extends Vehicle> list) {
int total = 0;
for(Vehicle v : list) {
    total += v.getFuel();
}
return total;}

totalFuel 메소드는 목록에서 Vehicles를 가져 와서 연료가 얼마나 있는지 묻고 총계를 계산합니다. 매개 변수화 된 컨테이너에 개체를 넣는 경우 super를 사용합니다.

int totalValue(Valuer<? super Vehicle> valuer) {
int total = 0;
for(Vehicle v : vehicles) {
    total += valuer.evaluate(v);
}
return total;}

totalValue 메소드는 Vehicles를 Valuer에 넣습니다. extends bound가 super보다 훨씬 더 일반적이라는 것을 아는 것이 유용합니다.


찬성 된 답변은 여러 측면에 대한 세부 사항을 다룹니다. 그러나 나는 이것을 다른 방식으로 대답하려고 노력할 것입니다.

고려해야 할 두 가지 사항이 있습니다.

1. 목록 변수에 할당

List<? extends X> listvar;

여기서 X의 목록 또는 X의 하위 클래스 목록 을 listvar에 할당 할 수 있습니다 .

List<? extends Number> listvar; listvar = new ArrayList<Number>(); listvar = new ArrayList<Integer>();


List<? super X> listvar;

여기서 X의 목록 또는 X의 수퍼 클래스 목록 을 listvar에 할당 할 수 있습니다 .

List<? super Number> listvar; listvar = new ArrayList<Number>(); listvar = new ArrayList<Object>();

2. 목록 변수에서 읽기 또는 쓰기 작업을 수행합니다.

`List<? extends X> listvar;`

이 기능을 사용하여 메서드 인수의 목록을 수락하고 유형 X 에 대한 작업을 수행 할 수 있습니다 (참고 : 목록에서 X 유형의 개체 만 읽을있음 ).

`List<? super Number> listvar;

이 기능을 사용하여 메서드 인수의 목록을 수락하고 Object 유형에 대한 모든 작업을 수행 할 수 있습니다 . 목록에서 Object 유형의 개체 만 읽을 수 있기 때문 입니다. 하지만 예, 여기에 추가로 X 유형의 개체를 목록에 추가 할 수 있습니다.


예를 들어 상속 순서는 O> S> T> U> V로 가정합니다.

extends 키워드 사용,

옳은:

List<? extends T> Object = new List<T>();
List<? extends T> Object = new List<U>();
List<? extends T> Object = new List<V>();

올바르지 않음 :

List<? extends T> Object = new List<S>();
List<? extends T> Object = new List<O>();

슈퍼 키워드 :

옳은:

List<? super T> Object = new List<T>();
List<? super T> Object = new List<S>();
List<? super T> Object = new List<O>();

올바르지 않음 :

List<? super T> Object = new List<U>();
List<? super T> Object = new List<V>();

객체 추가 : List Object = new List ();

Object.add(new T()); //error

하지만 왜 오류입니까? List Object 초기화 가능성을 살펴 보겠습니다.

List<? extends T> Object = new List<T>();
List<? extends T> Object = new List<U>();
List<? extends T> Object = new List<V>();

Object.add (new T ()); 다음 경우에만 정확합니다.

List<? extends T> Object = new List<T>(); 

하지만 두 가지 가능성이 더 있습니다.

목록 개체 = new List (); 목록 개체 = new List (); 위의 두 가지 가능성에 (new T ())를 추가하려고하면 T가 U 및 V의 상위 클래스이기 때문에 오류가 발생합니다. U 및 V 유형의 목록에 T 객체 [(new T ())]를 추가하려고합니다. 상위 클래스 개체 (기본 클래스)는 하위 클래스 개체 (하위 클래스)에 전달할 수 없습니다.

추가 두 가지 가능성으로 인해 Java는 올바른 가능성을 사용하더라도 오류가 발생합니다 .Java는 사용자가 참조하는 Object가 무엇인지 알지 못하므로 List Object = new List ();에 객체를 추가 할 수 없습니다. 유효하지 않은 가능성이 있기 때문입니다.

객체 추가 : List Object = new List ();

Object.add(new T()); // compiles fine without error
Object.add(new U()); // compiles fine without error
Object.add(new V()); // compiles fine without error

Object.add(new S()); //  error
Object.add(new O()); //  error

그러나 위의 두 가지에서 오류가 발생하는 이유는 무엇입니까? Object.add (new T ()); 사용할 수 있습니다. 아래 가능성에 대해서만,

List<? super T> Object = new List<T>();
List<? super T> Object = new List<S>();
List<? super T> Object = new List<O>();

List에서 Object.add (new T ())를 사용하려고했다면 Object = new List (); 및 List Object = new List (); 그러면 오류가 발생합니다. 이것은 우리가 List Object = new List ();에 T object [new T ()]를 추가 할 수 없기 때문입니다. U 유형의 객체이기 때문입니다. T는 기본 클래스이고 U는 하위 클래스이기 때문에 T 객체 [새로운 T ()]를 U 객체에 추가 할 수 없습니다. 하위 클래스에 기본 클래스를 추가 할 수 없으므로 오류가 발생합니다. 이것은 다른 경우에도 동일합니다.

참고 URL : https://stackoverflow.com/questions/4343202/difference-between-super-t-and-extends-t-in-java

반응형