Chapter 12 Generics、列挙型、Anneration/1.Generics


1.ギネス(Generics)


1.1ギネス記録とは?

  • コンパイル時タイプチェック機能
  • を提供する.
    ギネス世界記録の長所
    1.タイプ安定性を提供する.
    2.タイプチェックとタイプ変換を省略して、コードをより簡潔にすることができます.
  • は、予期しないタイプのオブジェクトを格納することを阻止する
  • である.
  • は、記憶オブジェクトをエラータイプに変換する際に発生する可能性のあるエラー
  • を低減する.

    1.2地理クラスの宣言

  • クラスに入るGenericタイプ
  • を発表
    class Box{
         Object item;
         
         void setItem(Object item) {this.item = item;}
         Object getItem(){return item;}
    }
  • ギネス世界記録クラスに変更し、クラスの横に「」を付けてください.
  • 「Object」はすべて「T」に変換されます.
  • class Box<T>{ // 지네릭 타입 T를 선언
       T item;
       
       void setItem(T item) { this.item = item;}
       T getItem() { return item;}
    }
  • Boxでは、Tは「タイプ変数」と呼ばれ、「タイプ」の最初の字から取られる.
  • 型変数は、Tではなく他の変数を使用することができる.
    ex) ArrayList< E >, Map
  • できれば、無条件に「T」を使うよりも、場合によって意味のある文字を選んだほうがいいです.
  • 記号のみの種類が異なり、「任意参照型」が同じであることを意味する.
  • 以前には、様々なタイプのメソッドを処理するパラメータや戻りタイプとして多くのオブジェクトタイプの参照変数が使用されていたため、変換はできなかったが、Objectcetタイプではなく所望のタイプを指定するだけでよいようになった.
  • Box<String> b = new Box<String>(); //타입 T 대신, 실제 타입을 지정
    b.setItem(new Object());           //에러, String이외의 타입은 지정불가
    b.setItem("ABC");                  //Ok. String타입이므로 가능
    String item = (String) b.getItem(); // 형변환이 필요없음
  • は、ギネスを導入する前のコードと互換性があるため、以前の方法でオブジェクト(ギネスクラスであるにもかかわらず)
  • を作成することができる.
  • ギネスブックタイプが指定されていないため、不安全警告
  • が発行されます.
    Box b = new Box();    // OK. T는 Object로 간주된다.
    b.setItem("ABC");     // 경고. unchecked or unsafe operation
    b.setItem(new Object()); // 경고. unchecked or unsafe operation
  • 型変数Tにオブジェクトタイプが指定されている場合は、タイプが指定されていないのではなく、既知のタイプであるため、警告は発生しません.
  • Box<Object> b = new Box<Object>();
    b.setItem("ABC");     //경고발생 안함
    b.setItem(new Object()); // 경고발생 안함
  • ギネスは導入前のコードと互換性を保つためにギネスのコードを使用しないことを許可しているだけで、今後ギネスクラスを使用する場合は必ずタイプを指定してギネスに関する警告を避けなければならない.
  • ギネス世界記録



    「ボックスギネス世界記録」TのBoxまたは「T Box」と読みます.
    T型変数または型パラメータ.(Tはタイプ文字)
    Boxオリジナルタイプ(オリジナルタイプ)

    ギネス世界記録の制限

  • は、すべてのオブジェクトについて同じ動作を行うため、タイプ変数Tは、属する静的メンバーには使用できません.
  • Tはインスタンス変数と見なされるからである.
  • 静的メンバーはインスタンス変数を参照できません.
  • class Box<T>{
        static T item; // 에러
        static int compare(T t1, T t2){...} // 에러
        ...
    }
  • タイプは同じでなければなりません
  • ギネスタイプの配列の作成は許可されていません
  • class Box<T>{
       T[] itemArr; // OK. T타입의 배열을 위한 참조 변수 
       ...
       T[] toArray(){
           T[] tmpArr = new T[itemArr.length]; // 에러. 지네릭 배열 생성불가
           ...
           return tmpArr;
    }
    ...
    }
  • バイナリ配列を生成できないのはnew演算子のためであり,この演算子はコンパイル時にタイプTが何であるかを正確に知る必要がある.
  • 頂点配列を生成する必要がある場合、「Reflection API」のnewInstance()などの動的生成オブジェクトを使用して配列を作成したり、オブジェクト配列を作成してコピーして「T[]」に変換したりすることができます.
  • 1.3ムカデ類を使用したオブジェクトの作成

  • 参照変数は、ジェネレータに入力されたタイプ(パラメトリックタイプ)と一致する必要があります.
  • Box<Apple> appleBox = new Box<Apple>(); // OK
    Box<Apple> appleBox = new Box<Grape>(); // 에러
  • の2つのGenericクラスのタイプは継承関係に属し、代入のタイプは同じでよい.
    FruitBoxがBoxの子孫であると仮定する
  • Box<Apple> appleBox = new FruitBox<Apple>(); // OK. 다형성
  • JDK1.7から、推測可能であれば、タイプは省略できます.
  • 参照変数のタイプから、BoxはAppleタイプのオブジェクトのみを格納していることがわかるので、ジェネレータにタイプを繰り返し指定する必要はありません.
  • Box<Apple> appleBox = new Box<Apple>();
    Box<Apple> appleBox = new Box<>(); // OK. JDK1.7부터 생략가능
    「void add(T item)」で生成された
  • のBoxにオブジェクトを追加する場合、置換されたタイプとは異なるオブジェクトを追加することはできません.
  • Box<Apple> appleBox = new Box<Apple>();
    appleBox.add(new Apple()); // Ok.
    appleBox.add(new Grape()); // 에러. Box<Apple>에는 Apple객체만 추가가능 
  • タイプTが「Fruit」である場合、「void add(Fruit item)」であるため、Fruitの子孫はこの方法のパラメータとして使用することができる.
  • Box<Fruit> fruitBox = new Box<Fruit>();
    fruitBox.add(new Fruit()); //OK
    fruitBox.add(new Apple()); //Ok. void add(Fruit item)
    import java.utilArrayList;
    
    class Fruit { public String toString(){return "Fruit";}}
    class Apple extends Fruit { public String toString() {return "Apple";}}
    class Grape extends Fruit { public String toString() {return "Grape";}}
    class Toy { public String toString() {return "Toy";}}
    
    class FruitBoxEx1 {
       public sttic void main(String[] args) {
           Box<Fruit> fruitBox = new Box<Fruit>();
           Box<Apple> appleBox = new Box<Apple>();
           Box<Toy> toyBox = new Box<Toy>()
    //     Box<Grape> grapeBox = new Box<Apple>(); // 에러. 타입 불일치
    
           fruitBox.add(new Fruit()); 
           fruitBox.add(new Apple()); // OK. void add(Fruit item)
       
           appleBox.add(new Apple());
           appleBox.add(new Apple());
    //     appleBox.add(new Toy()); // 에러. Box<Apple>에는 Apple만 담을 수 있음 
    
           toyBox.add(new Toy());
           toyBox.add(new Apple()); // 에러. Box<Toy> 에는 Apple을 담을 수 없음
    
           System.out.println(fruitBox);
           System.out.println(appleBox);
           System.out.println(toyBox);
    } // main의 끝
    }
    
    class Box<T> {
       ArrayList<T> list = new ArrayList<T>();
       void add(T item) { list.add(item); }
       T get(int i) {return list.get(i);}
       int size() { return list.size();}
    public String toString(){ return list.toString();}
    }

    1.4制限された地理的クラス

  • ギネスタイプで「extends」を使用すると、特定のタイプの子孫が加入できるように制限できます.
  • class FruitBox<T extends Fruit> { // Fruit의 자손만 타입을 지정가능
         ArrayList<T> list = new ArrayList<T>();
    ...
    }
  • Fruitクラスの子孫を収容できる制限追加
  • FruitBox<Apple> appleBox = new FruitBox<Apple>(); // OK
    FruitBox<Toy> toyBox = new FruitBox<Toy>(); // 에러. Toy는 Fruit의 자손이 아님 
  • 多形の祖先タイプの参照変数が子孫タイプのオブジェクトを指すことができるように、パラメトリックタイプの子孫タイプも可能である.
  • タイプのパラメータTにオブジェクトを代入すると、すべてのタイプのオブジェクトを保存できます.
  • クラスの制約ではなくインタフェースを実装する必要がある場合は、「extends」を使用します.
  • 「implements」は使用しません.
  • interface Eatable{}
    class FruitBox<T extends Eatable>{ ... }
  • クラスFruitの子であり、Eatableインタフェースを実装する必要がある場合は、次の「&」記号を使用して接続します.
    class FruitBox<T extends Fruit & Eatable>{...}