[JAVA]いわゆるジェネリック


アルゴリズムの問題を解くと、Collectionsクラスのsort()メソッドコードが表示されます.
public static <T extends Comparable<? super T>> void sort(List<T> list)
ジェニーンリックみたい...ちょっと複雑に見えますが、どういう意味か分かりません.
ショックを受けたので、これをきっかけにジェニーリックを再整理したいと思います.
ジェニーンリックって何?
Genericは、コンパイル時に異なるタイプのオブジェクトを含むメソッドまたは集合クラスをタイプチェックする機能です.
すなわち、予め指定されたタイプではなく、必要に応じてタイプの汎用タイプを指定できます.
ジェニーリックの長所は次のとおりです.
  • タイプ安定性を提供します.
  • Type CheckとType Transform、コードを簡略化します.
  • 貴族階級.
    次はGenericクラスの例です.
    class Box<T> {
    	T item;
        
        void setItem(T item) {
        	this.item = item;
        }
        T getItem() {
        	return item;
        }
    特定のタイプではなく、Tなどのタイプ変数を追加するだけです.
    汎用クラスを作成するときに、タイプTではなくコンストラクタで使用する参照変数と実際のタイプを指定します.
    Box<String> b = new Box<String>();
    b.setItem(new Object());
    Generickの使用には2つの制限があります.
    まず、タイプ変数TはGenericクラスの静的メンバーには使用できません.
    静的メンバーは、すべてのオブジェクトに対して同じ動作をしなければならないため、インスタンス変数とみなされるTは使用できません.
    2つ目の制限は、ネストされたタイプの配列を作成できないことです.
    汎用アレイタイプの参照変数を宣言できます.
    ただし、new T[10]などのアレイの作成は許可されていません.
    これはnew演算子がコンパイル時にタイプTを知る必要があるためである.
    TタイプのオブジェクトのみをGeneric ClassBox<T>に格納できます.
    オブジェクトを作成するときは、リファレンス変数が作成者にインポートされたタイプと一致する必要があります.Box<Apple> appleBox = new Box<Apple>(); - ok
    2つのタイプに継承関係がある場合でも、エラーが発生します.
    AppleはFruitの子孫ですねBox<Fruit> appleBox = new Box<Apple>(); - error
    ただし、2つのGenericクラスのタイプは継承関係にあり、同じタイプの置換は可能です.
    FruitBoxはBoxの子孫ですBox<Apple> appleBox = new FruitBox<Apple>(); - ok
    したがって、オブジェクトの作成時に代入されるタイプは常に同じでなければなりません.2つのGenericクラスに継承関係がある場合は、異なることができます.
    制限されたGenericクラス
    制限タイプパラメータTが指定できるタイプ.extends特定のタイプの子のみが参加できます.
    class FruitBox<T extends Fruit> {
    	ArrayList<T> list = new ArrayList<T>();
        ...
    }
    Fruit BoxにはFruitクラスのサブクラスしか含まれません.
    タイプパラメータTにオブジェクトを代入すると、すべてのタイプのオブジェクトを保存できます.
    Genericクラスでは,インタフェースを実装する際にもextendsを用いる.
    class FruitBox<T extends Fruit & Interface> {
    	ArrayList<T> list = new ArrayList<T>();
        ...
    }
    上記の例では、Fruit Boxは、Fruitのサブアイテムとして機能し、インタフェースを実装したクラスに置き換えられるしかない.
    ? (wild card)
    他のタイプを上書きするためのワイルドカードを設計しました.
    ワイルドカードは?任意のタイプです.
    ワイルドカードとextends、superを使用して上下限を制限できます.
  • <? extends T>:ワイルドカードの上限制限.Tおよびその子孫
  • <? super T>:ワイルドカードの下限.Tおよびその祖先のみ
  • <?>:無制限<? extends Object>と同じ
  • **Generickとはレベルが異なり、ワイルドカードでは「&」は使用できません.
    ジェニリック法
    メソッドの宣言セクションで「エネルギータイプ」を宣言したメソッドを「エネルギーメソッド」と呼びます.static <T> void sort(List<T> list, Comparator<? super T> c)ジェニーリックタイプの宣言位置は戻りタイプの前にあります.
    ジェニーリックメソッドはクラスではなくクラスで定義できます.
    タイプパラメータは静的メンバーには使用できませんが、メソッドの省エネタイプを宣言および使用できます.
    class FruitBox<T> {
    	static <T> void sort(List<T> list, Comparator<? super T> c) {
        ...
        }
    }
    汎用メソッドで定義したタイプパラメータは、汎用クラスで定義したタイプパラメータとは異なります.
    同じタイプの文字Tを使っても違います.
    public static <T extends Comparable<? super T>> void sort(List<T> list)
    私はジェニーンリックを再学習しました.今はこのコードを理解できるようになりました.sort(List<T> list):タイプTを要素とするListをパラメータとする.T extends Comparable:タイプTは、Compareableを実装するクラスである.Comparable<? super T>:Tまたはその祖先タイプのCompabiledを比較します.
    1行にまとめます.
    sort()は、比較Tまたはその祖先タイプの比較可能なTを要素とするリストをパラメータとする.
    ああ、気持ちいいですね.
    参考資料
  • Javaの定義
  • https://st-lab.tistory.com/153