자바 모델 중?extends T 와?슈퍼 T 의 차이

27555 단어 자바
앞에서 말 했 듯 이 위로 전환 하 는 것 은 안전 하고 아래로 전환 하 는 것 은 안전 하지 않다.List 의 실제 유형 을 알 지 않 으 면 아래로 전환 하 는 것 이 잘못 될 것 이다.
extends
List extends Number>foo 3 은 아래 의 할당 문 구 를 합 법 적 으로 의미 합 니 다.
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 에서 어떤 유형의 대상 을 꺼 낼 수 있 습 니까?
  • Number 대상 을 읽 을 수 있 습 니 다.위의 임의의 list 는 Number 대상 이나 Number 하위 클래스 의 대상(위의 Number,Integer,Double 은 Number 로 전환 할 수 있 고 안전 하기 때문에 읽 을 수 있 습 니 다)을 포함 합 니 다.다음 코드 는 틀 리 지 않 습 니 다:
  •         List<? extends Number> foo4 = new ArrayList<Integer>();
            Number number = foo4.get(0);
    
  • Integer 대상 을 읽 을 수 없습니다.foo3List 을 가리 킬 수 있 기 때 문 입 니 다.다음 코드 를 컴 파일 할 때 foo3 오 류 를 보고 합 니 다:
  •         List<? extends Number> foo4 = new ArrayList<Integer>();
            Integer number = foo4.get(0);
    

    컴 파일 할 때 컴 파일 러 는 foo 4 참조 가 하나의 List extends Number>인 것 만 알 고 실행 할 때 new Array List()에 연결 되 기 때문에 컴 파일 할 때 foo 4 가 가리 키 는 List 에서 어떤 유형 인지 판단 할 수 없습니다.유일 하 게 확실한 것 은 이 유형 이 Number 의 하위 클래스(또는 Number 클래스)입 니 다.
  • Integer 대상 을 읽 을 수 없습니다.Incompatible types 이 가리 킬 수 있 는 것 은 Double 이기 때 문 입 니 다.

  • 2.쓰기
    상기 가능 한 할당 문 구 를 지정 하면 foo3 에 어떤 유형의 대상 을 추가 하여 가능 한 모든 List 이 합 법 적 이라는 것 을 보증 할 수 있 습 니까?
  • List foo3 대상 을 추가 할 수 없습니다.ArrayListInteger 을 가리 킬 수 있 기 때 문 입 니 다.다음 코드 는 컴 파일 오류 가 발생 할 수 있 습 니 다:
  •         List<? extends Number> foo4 = new ArrayList<Integer>();
            foo4.add(new Integer(1));
    

    컴 파일 기간 동안 foo 4 가 가리 키 는 Array List 에 어떤 유형 이 들 어 있 는 지 알 수 없 기 때문에 실행 할 때 만 알 수 있 습 니 다.실행 할 때 하나의 Array List 에 하나의 Integer 를 추가 하 는 것 을 발견 하기 보 다 는 형식 변환 이상 을 초래 하 는 것 이 좋 습 니 다.컴 파일 할 때 오 류 를 보고 하 는 것 이 좋 습 니 다.설령 Array List 에 Integer 형식 이 놓 여 있 더 라 도.
  • foo3 대상 을 추가 할 수 없습니다.ListDouble 을 가리 킬 수 있 기 때 문 입 니 다.
  • foo3 대상 을 추가 할 수 없습니다.ListNumber 을 가리 킬 수 있 기 때 문 입 니 다.

  • 요약:foo3 에 대상 을 추가 할 수 없습니다.List 이 진정 으로 어떤 유형 을 가리 키 는 지 보장 할 수 없 기 때문에 추가 대상 이 List extends T> 이 받 아들 일 수 있 는 유형 인지 확인 할 수 없습니다.보증 할 수 있 는 것 은 List 에서 읽 을 수 있 을 때 List 유형의 대상(List 유형의 하위 대상 이라도 T 유형)을 얻 을 수 있 습 니 다.
    Super
    현재 T 에 마스크 를 포함 하 는 성명 T 을 고려 하면 다음 의 모든 할당 문 구 는 합 법 적 이라는 것 을 의미한다.
    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 super T> 의 요 소 를 읽 을 때 어떤 유형의 대상 을 받 을 수 있 습 니까?
  • List super Integer> foo3 대상 이 라 고 보장 할 수 없습니다.List foo3Integer 또는 foo3 대상 을 가리 킬 수 있 기 때 문 입 니 다.ListList
  • Number 류 의 인 스 턴 스 나 foo3 자 류 의 인 스 턴 스 를 가리 킬 수 있 기 때 문 입 니 다.

  • 2.쓰기
    상기 가능 한 할당 문 구 를 지정 하면 List
  • Object 에 어떤 유형의 대상 을 추가 하여 가능 한 모든 Object 이 합 법 적 이라는 것 을 보증 할 수 있 습 니까?
  • List foo3 인 스 턴 스 를 추가 할 수 있 습 니 다.ArrayList 유형 은 상기 모든 list 에 합 법 적 이기 때 문 입 니 다.
  • Integer 하위 클래스 의 인 스 턴 스 를 추가 할 수 있 습 니 다.Integer 하위 클래스 의 인 스 턴 스 가 위 목록 의 요소 유형 으로 전환 할 수 있 기 때 문 입 니 다.
  • Integer 유형 을 추가 할 수 없습니다.IntegerDouble 을 가리 킬 수 있 기 때 문 입 니 다.
  • foo3 유형 을 추가 할 수 없습니다.ArrayListNumber 을 가리 킬 수 있 기 때 문 입 니 다.
  • foo3 유형 을 추가 할 수 없습니다.ArrayListObject 을 가리 킬 수 있 기 때 문 입 니 다.

  • PECS
    PECS 는'프로듀서 확장,컨 슈 머 슈퍼'(생산자 용 확장,소비자 용 슈퍼)의 약자 다.
  • 'Producer Extendes'는 foo3ArrayList 유형 values(즉,list 에서 List 유형의 인 스 턴 스 를 읽 어야 한 다 는 뜻)를 생산 해 야 한다 면 이 T 의 요 소 는 T,예 를 들 어 List 이지 만 그 안에 요 소 를 추가 할 수 없다 는 뜻 이다.
  • 'Consumer Super'는 ? extends T 을 소비 하 는 List extends Integer> 유형의 values(즉,list 에 List 유형의 인 스 턴 스 를 추가 해 야 한 다 는 뜻)가 필요 하 다 면 이 T 의 요 소 는 T 이 고 예 를 들 어 List 이다.하지만 이 list 에서 대상 형식 을 읽 을 수 는 없습니다.
  • 만약 에 list 에 써 야 할 뿐만 아니 라 list 에서 읽 어야 한다 면 마스크 ? super T 을 사용 할 수 없고 정확 한 유형 을 사용 해 야 한다.예 를 들 어 List super Integer> 이다.
  • 은 JDK 소스 코드 중의 Collections 류 의 copy 방법 을 참고 하여 PECS 를 이해 할 수 있 고 소스 코드 는 문 말 에 있다.

  • 원본 링크:https://stackoverflow.com/questions/4343202/difference-between-super-t-and-extends-t-in-java
    원문의 내용 은 다음 과 같다.
    extends
    The wildcard declaration of List extends Number> foo3 means that any of these are legal assignments:
    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
    
  • Reading - Given the above possible assignments, what type of object are you guaranteed to read from List foo3:
  • You can read a Number because any of the lists that could be assigned to foo3 contain a Number or a subclass of Number.
  • You can’t read an Integer because foo3 could be pointing at a List.
  • You can’t read a Double because foo3 could be pointing at a List.
  • Writing - Given the above possible assignments, what type of object could you add to List foo3 that would be legal for all the above possible ArrayList assignments:
  • You can’t add an Integer because foo3 could be pointing at a List.
  • You can’t add a Double because foo3 could be pointing at a List.
  • You can’t add a Number because foo3 could be pointing at a List.
  • You can’t add any object to List extends T> because you can’t guarantee what kind of List it is really pointing to, so you can’t guarantee that the object is allowed in that List. The only “guarantee” is that you can only read from it and you’ll get a T or subclass of T.

  • super
    Now consider List super T>.
    The wildcard declaration of List super Integer> foo3 means that any of these are legal assignments:
    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
    
  • Reading - Given the above possible assignments, what type of object are you guaranteed to receive when you read from List foo3:
  • You aren’t guaranteed an Integer because foo3 could be pointing at a List or List.
  • You aren’t guaranteed a Number because foo3 could be pointing at a List.
  • The only guarantee is that you will get an instance of an Object or subclass of Object (but you don’t know what subclass).
  • Writing - Given the above possible assignments, what type of object could you add to List foo3 that would be legal for all the above possible ArrayList assignments:
  • You can add an Integer because an Integer is allowed in any of above lists.
  • You can add an instance of a subclass of Integer because an instance of a subclass of Integer is allowed in any of the above lists.
  • You can’t add a Double because foo3 could be pointing at an ArrayList.
  • You can’t add a Number because foo3 could be pointing at an ArrayList.
  • You can’t add an Object because foo3 could be pointing at an ArrayList.

  • PECS Remember PECS: “Producer Extends, Consumer Super”.
  • “Producer Extends” - If you need a List to produce T values (you want to read Ts from the list), you need to declare it with ? extends T, e.g. List extends Integer>. But you cannot add to this list.
  • “Consumer Super” - If you need a List to consume T values (you want to write Ts into the list), you need to declare it with ? super T, e.g. List super Integer>. But there are no guarantees what type of object you may read from this list.
  • If you need to both read from and write to a list, you need to declare it exactly with no wildcards, e.g. List.

  • Example Note this example from the Java Generics FAQ. Note how the source list src (the producing list) uses extends, and the destination list dest (the consuming list) uses 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)); 
      } 
    }
    

    또한 JDK 의 Collections 클래스 의 copy 방법 을 참고 하여 PECS 규칙 을 기억 하 는 데 도움 이 됩 니 다.
        /**
         * Copies all of the elements from one list into another.  After the
         * operation, the index of each copied element in the destination list
         * will be identical to its index in the source list.  The destination
         * list must be at least as long as the source list.  If it is longer, the
         * remaining elements in the destination list are unaffected. 

    * * This method runs in linear time. * * @param the class of the objects in the lists * @param dest The destination list. * @param src The source list. * @throws IndexOutOfBoundsException if the destination list is too small * to contain the entire source List. * @throws UnsupportedOperationException if the destination list's * list-iterator does not support the set operation. */

    public static <T> void copy(List<? super T> dest, List<? extends T> src) { int srcSize = src.size(); if (srcSize > dest.size()) throw new IndexOutOfBoundsException("Source does not fit in dest"); if (srcSize < COPY_THRESHOLD || (src instanceof RandomAccess && dest instanceof RandomAccess)) { for (int i=0; i<srcSize; i++) dest.set(i, src.get(i)); } else { ListIterator<? super T> di=dest.listIterator(); ListIterator<? extends T> si=src.listIterator(); for (int i=0; i<srcSize; i++) { di.next(); di.set(si.next()); } } }

    참고 글:https://www.cnblogs.com/suxuan/p/4970467.html
  • 좋은 웹페이지 즐겨찾기