[Java] 제니크스 경계 어댑터 유형 소개

15019 단어 Java

경계 와일드카드 유형의 역할


자바의 일반형은 List<Integer>형을 List<Number>형으로 변환할 수 없다.
유형이 다르다
// OK 型パラメーターが同一の場合
List<Integer> foo = new ArrayList<Integer>();

// NG List<Integer> は、List<Number> に変換できない
List<Number> bar = foo;

// NG 初期化でも同様に変換不可
List<Number> foo = new ArrayList<Integer>();
따라서 경계 와일드카드를 사용하여 유형 매개변수를 어느 정도 넓게 만들 수 있습니다.
그러나 경계 와일드카드 유형은 두 가지입니다.
형의 경계를 결정할 때 각자의 장면에서 처리계에'확정불능형'문제가 발생하기 때문이다.
나는 그 문제를 하나하나 보고 싶다.
설명은 다음 Frite 클래스를 사용합니다.

최대 와일드카드 유형

Generic<? extends T>
유형 매개변수를 위에서 설명한 대로 지정하면 유형 매개변수는 상한 와일드카드 유형입니다.
? extends T-유형은 T 또는 모든 하위 클래스를 나타내는 유형입니다.
List<? extends Fruit> 유형을 고려하면 지정한 List형에서 Frit 클래스나 하위 클래스를 변환할 수 있습니다.
변환 가능 목록
List<? extends Fruit> basket = new ArrayList<Fruit>(); // 1
List<? extends Fruit> basket = new ArrayList<Melon>(); // 2
List<? extends Fruit> basket = new ArrayList<Lemon>(); // 3
다음으로List<? extends Fruit> basket 우리는 변수에서 원소를 추출하는 것을 고려한다
basket 변수는 1이든 2든 3이든 Frit 클래스에서 얻을 수 있는 요소입니다.

넣다


상한 경계 와일드카드에서 T클래스로 변환

List<? extends Fruit> basket 변수에서 원소를 추출하는 것을 고려한다.
상한 어댑터형은 최소한 T클래스와 그 하위 클래스를 나타내는 유형이며List에서 요소를 얻었을 때 상한 T를 지정할 수 있다.
최대 와일드카드 유형을 T-유형으로 변환
List<? extends Fruit> fruits = ...

// 問題なし
Fruit fruit = fruits.get(i);
이것은 ? extends T형에서 T형으로의 전환이다.

상한 경계 와일드카드에서 T의 하위 클래스로 변환


다음에 basket 변수에서 원소를 가져올 때 이 하위 클래스를 지정할 수 있는지 고려합니다.List<? extends Fruit>형은 적어도 아래 3가지 List형에서 전환할 수 있다.
  • ArrayList<Fruit>
  • ArrayList<Melon>
  • ArrayList<Lemon>
  • 따라서 원소를 얻을 때 여러 시퀀스에 파생된 하위 클래스를 지정할 수 없습니다.
    상한 어댑터 형식은 하위 종류로 변환할 수 없습니다
    List<? extends Fruit> basket = ...
    
    // NG コンパイルエラー Melon型には変換できません
    Melon fruit = basket.get(i);
    
    ? extends Fruit 유형을 하위 클래스로 변환할 수 있는 경우 다음과 같은 모순이 발생합니다.
    최대 와일드카드 유형을 T 하위 클래스 1로 변환
    // メロンリストを作る
    List<Melon> melonList = new ArrayList<Melon>()
    melonList.add(new Melon());
    
    // List<Melon> melonList型をList<? extends Fruit>型に変換
    List<? extends Fruit> basket = melonList;
    
    // サブクラスへの変換が可能であればLemonとして受け取ることが可能となってしまう
    Lemon fruit = basket.get(i);
    
    따라서 하위 클래스로 변환할 수 없습니다.
    따라서 ? extends T형에서 Tのサブクラス형으로 전환할 수 없다.

    쓰기


    다음List<? extends Fruit> fruits은 변수에 원소를 추가하는 것을 고려한다.? extends Fruit 유형에서 Fruit型로 전환할 수 있기 때문에 아래의 frits 변수에 Frits 대상을 추가할 수 있습니다.
    최대 와일드카드 유형에 쓰기
    List<? extends Fruit> fruits = new ArrayList<Fruit>();
    
    // 一見可能に思える
    fruits.add(new Fruit());
    
    그러나 이 같은 내용을 허용하면 다음과 같은 모순이 생길 수 있다.
    상한 어댑터 형식에 쓰기 모순
    // fruitsの実態はメロンリスト
    List<? extends Fruit> fruits = new ArrayList<Melon>();
    // LemonクラスはFruitクラスのサブクラス
    Fruit fruit = new Lemon();
    
    // メロンリストにレモンが追加出来ることになる
    fruits.add(fruit);
    
    따라서 구체형T형이나 Tのサブクラス형에서 ? extends T형으로 전환할 수 없다.
    상한선이 있는 와일드카드로 리스트형을 선언하면 요소를 추가할 수 없다는 의미다.
    그곳에는 경계 어댑터 모양의 출전이 하나 더 있다.
    ※ 앱펜딕스에 구체형에서 전환에 대한 설명이 추가되었습니다.

    최소 와일드카드 유형

    Generic<? super T>
    
    유형 매개변수를 위에서 설명한 대로 지정하면 유형 매개변수는 하한선이 있는 와일드카드 유형입니다.
    ? 슈퍼T형은 T나 그 슈퍼클래스의 모든 유형을 나타낸다.

    List형은 List형에서 Frit 클래스나 슈퍼 클래스를 형 매개 변수로 변환할 수 있다.
    변환 가능 목록
    List<? super Melon> baskets = new ArrayList<Melon>(); // 1
    List<? super Melon> baskets = new ArrayList<Fruit>(); // 2
    List<? super Melon> baskets = new ArrayList<Food>(); // 3
    List<? super Melon> baskets = new ArrayList<Object>(); // 4
    
    이번에는 제가 앞뒤로 basket 변수에 원소를 추가하는 걸 생각해 볼게요.
    1∼4에서는 1·2·3·4와 관계없이 basket 변수에 멜론류를 추가할 수 있다.

    쓰기


    최소 와일드카드 유형으로 변환

    List<? super Melon> basket 요소를 변수에 추가하려면 하한선이 있는 와일드카드 유형의 경우 최소한 T 클래스 또는 그 이상의 슈퍼 클래스를 나타내는 유형이어야 하기 때문에 List형에 요소를 추가할 때 하한선 T를 지정할 수 있어야 한다.
    확인은 예시를 참고하여 하나하나 추가할 수 있다.List<? super Melon> fruits = new ArrayList<Object>()
    Object 목록에 추가
    // OK
    fruits.add(new Melon())
    // OK
    fruits.add(new WaterMelon());
    
    List<? super Melon> fruits = new ArrayList<Food>()
    Food 목록에 추가
    // OK
    fruits.add(new Melon())
    // OK
    fruits.add(new WaterMelon());
    
    List<? super Melon> fruits = new ArrayList<Melon>()
    멜론에 추가
    // OK
    fruits.add(new Melon());
    // OK
    fruits.add(new WaterMelon());
    
    T 또는 Tのサブクラス형에서 ? super T형으로 전환할 수 있다는 것이다.

    넣다


    ? 슈퍼 멜론형은'멜론 클래스와 그 슈퍼 클래스를 나타내는 타입'이다.
    그리고 자바의 모든 학급은 Object형을 계승했다.
    따라서 ? super T형에서 Object형으로 전환할 수 있다.
    하위 와일드카드 유형에서 Object 유형으로 변환
    Object object = basket.get(i)
    

    총결산

  • 경계 매개 변수형을 사용하면 제네시스형
  • 을 광범위하게 나타낼 수 있다.

  • 상한 경계 어댑터 형식과 구체적인 형식의 변환 테이블
    가부
    변환 소스
    목표
    그런 뜻
    OK? extends T T T 유형치 획득 가능
    NGT ? extends T쓰기 불가

  • 하위 와일드카드 유형 및 특정 유형의 변환 테이블
    가부
    변환 소스
    목표
    그런 뜻
    OK? super T ObjectObject형으로 값을 얻을 수 있음
    OKT ? super T쓰기 가능 T-값
    OKTサブクラス ? super TT에 쓸 수 있는 하위 클래스 값

  • 일반적으로 PECS라는 주문이 존재하는데, 상한 경계 어댑터는 Producter라고 하고, 하한 경계 어댑터는 Consumer라고 한다
  • Producter 값의 생성 전문
  • Consummer 값의 수신 전공
  • Appendix


    경계 와일드카드 유형을 사용하여 값 쓰기


    상한 경계 와일드카드를 지정했을 때, 그 List는 쓸 수 없다는 말을 들은 적이 있을 것이다.
    이것은 단순히 이하로 할 수 없다는 뜻이다.具体型에서 上限付きワイルドカード型로 변경할 수 없음
    Genesis형 객체를 선언하는 데 상한 와일드카드를 사용하는 경우 이러한 유형의 매개 변수가 있는 함수를 호출할 때 이러한 변환이 발생합니다.
    다음은 Stack 클래스입니다.
    ack 등급
    class Stack<T> {
        void push(T e) {}
    }
    
    최대 와일드카드 유형을 사용하여 Stack 클래스를 선언합니다.
    Stack<? extends Fruit> basket = new Stack<Fruit>();
    
    이때 basket 변수의 유형 매개 변수 T는 ? extends Fruit형입니다.
    즉,push 방법은 다음과 같다.
    Stack의 유형 매개 변수가 최대 와일드카드일 경우
    void push(`? extends Fruit` e) {}
    
    따라서 이push 방법을 사용하면 具体型(Fruit)에서 ? extends Fruit형으로 전환됩니다.
    그리고 이 전환은 NG다.
    // NG Fruit型を `? extends Fruit` 型へは変換できない
    basket.push(new Fruit()); 
    

    좋은 웹페이지 즐겨찾기