ジェニーリック


Generic


JENICは、外部指定クラス内で使用されるデータ型の技術である.
package practice;

class Student<T> {
    public T info;
}

public class GenericDemo {
    public static void main(String[] args) {
        Student<String> s1 = new Student<String>();
        Student<StringBuilder> s2 = new Student<StringBuilder>();
    }
}
s1.infoとs 2.infoのデータ型は、各インスタンスを作成する際に使用される<>間のデータ型に依存します.
  • s1.info : String
  • s2.info : StringBuilder
  • public T info;:クラスStudioのフィールドinfoのデータ型はTです.この値は、class Student<T>{}のTによって決定される.ここでのTは、Student<String> s1 = new Student<String>();<>で指定されたデータ型によって決定される.Student<String> s1 = new Student<String>();Student<String> p1は変数p 1のデータ型を定義し、new Student<String>();はインスタンスを生成する.
    👓 Jenericはクラスを定義する際にinfoが不確定なデータ型인스턴스를 생성할 때 데이터 타입을 지정하는 기능である.

    なぜジェニーンリックを使うの?


    1.タイプ安定性

    package practice;
    
    class StudentInfo{
        public int grade;
        StudentInfo(int grade){ this.grade = grade; }
    }
    class EmployeeInfo{
        public int rank;
        EmployeeInfo(int rank){ this.rank = rank; }
    }
    class Person{
        public Object info;
        Person(Object info) { this.info = info; }
    }
    
    public class GenericDemo {
        public static void main(String[] args) {
            Person p1 = new Person("부장");
            EmployeeInfo ei = (EmployeeInfo)p1.info;
            System.out.println("Rank is... " + ei.rank); // 1
        }
    }
    このコードをコンパイルすると、実行時にエラーが発生します.パラメータinfoのデータ型がオブジェクトであるため、クラスPersionの作成者はすべてのオブジェクトである可能性があります.

    2.ジェニーン・リックワード

    package practice;
    
    class StudentInfo{
        public int grade;
        StudentInfo(int grade){ this.grade = grade; }
    }
    class EmployeeInfo{
        public int rank;
        EmployeeInfo(int rank){ this.rank = rank; }
    }
    class Person<T>{
        public T info;
        Person(T info) { this.info = info; }
    }
    
    public class GenericDemo {
        public static void main(String[] args) {
            Person<EmployeeInfo> p1 = new Person<EmployeeInfo>(new EmployeeInfo(1));
            EmployeeInfo ei1 = p1.info;
            System.out.println("Rank is... " + ei1.rank); // 성공
    
            Person<String> p2 = new Person<String>("부장");
            String ei2 = p2.info;
            System.out.println(ei2.rank); // 컴파일 실패
        }
    }
    p 2はコンパイルエラーを発生します.p2.infoはStringなので、Stringにはrankフィールドはありませんが、呼び出されています.このことからJENICを利用した理由は以下の通りである.
  • コンパイル時にエラーが検出されました
  • 重複除外とともにタイプ安定性
  • ジェニーリックの特徴


    1.復讐のジェニーンリック


    クラスに複数のJENICが必要な場合があります.
    package practice;
    
    class EmployeeInfo{
        public int rank;
        EmployeeInfo(int rank){ this.rank = rank; }
    }
    class Person<T, S>{
        public T info;
        public S id;
        Person(T info, S id){ 
            this.info = info; 
            this.id = id;
        }
    }
    public class GenericDemo {
        public static void main(String[] args) {
            Person<EmployeeInfo, int> p1 = new Person<EmployeeInfo, int>(new EmployeeInfo(1), 1);
        }
    }

    2.基本データ型とGeneric


    ジェニーリックは参照データ型にしか書けない.(デフォルトのデータ型に書き込めません)
    package practice;
    
    class EmployeeInfo{
        public int rank;
        EmployeeInfo(int rank){ this.rank = rank; }
    }
    class Person<T, S>{
        public T info;
        public S id;
        Person(T info, S id){ 
            this.info = info;
            this.id = id;
        }
    }
    public class GenericDemo {
        public static void main(String[] args) {
            EmployeeInfo e = new EmployeeInfo(1);
            Integer i = new Integer(10);
            Person<EmployeeInfo, Integer> p1 = new Person<EmployeeInfo, Integer>(e, i);
            System.out.println(p1.id.intValue());
        }
    }
    新Integerは、基本データ型intを参照データ型に変換することができる.これらのクラスをパッケージクラスと呼びます.したがって、基本データ型を使用できないJENICでintを使用することができます.

    3.ジェニーンリックの省略


    ジュネーブは省略できます.
    public class GenericDemo {
        public static void main(String[] args) {
            EmployeeInfo e = new EmployeeInfo(1);
            Integer i = new Integer(10);
            Person<EmployeeInfo, Integer> p1 = new Person<EmployeeInfo, Integer>(e, i);
            Person p2 = new Person(e, i);
        }
    }
    eとiのデータ型はすでに分かっており、Person p2 = new Person(e, i);を記入するだけでよい.

    4.メソッドへの適用

    package practice;
    
    class EmployeeInfo{
        public int rank;
        EmployeeInfo(int rank){ this.rank = rank; }
    }
    class Person<T, S>{
        public T info;
        public S id;
        Person(T info, S id){ 
            this.info = info;
            this.id = id;
        }
        public <U> void printInfo(U info){
            System.out.println(info);
        }
    }
    public class GenericDemo {
        public static void main(String[] args) {
            EmployeeInfo e = new EmployeeInfo(1);
            Integer i = new Integer(10);
            Person<EmployeeInfo, Integer> p1 = new Person<EmployeeInfo, Integer>(e, i);
            p1.<EmployeeInfo>printInfo(e);
            p1.printInfo(e);
        }
    }

    5.ジェニーンリックの制限


    extends

  • データ型は、特定のクラスのサブタイプに制限することができる.(クラスまたはサブクラス以外のクラスはアクセスできません)
  • 継承(extends)だけでなく、(implements)関係の実装にも使用できます.
  • Reference
    1. ジェニーリック