Generic


1.Genericとは?


インスタンス変数のタイプを決定するために、instanceofという予約語を使用してタイプをチェックすることができる.
しかし、このような欠点を補うためにJava 5から제네릭(Generic)が新たに追加された.
ジェニーリックは「辞書」でタイプ変換で発生する可能性のある問題をチェックするために作った.ここでいう「辞書」とは、処理実行時に異常が発生するのではなく、コンパイル時にチェックすることを意味します.
サンプルコード
package d.generic;

import java.io.Serializable;

public class CastingDTO implements Serializable{
    private Object object;
    public void setObject(Object object){
        this.object = object;
    }
    public Object getObject{
    	return object;
    }
}    
これにより、任意のタイプのオブジェクトを使用できます.このクラスをJENERICと宣言します.次のようにします.
package d.generic;

import java.io.Serializable;

public class CastingGenericDTO<T> implements Serializable{
    private T object;
    public void setObject(T obj){
        this.object = obj;
    }
    public T getObject{
    	return object;
    }
}
何の変化もない.ただし、クラス宣言では、鉄のロックが開いたり閉じたりしています(<および>).中にはアルファベットTと書いてあるだけです.そして、前のソースではObjectのタイプが発表されていましたが、今回JENERICソースを見ると、タイプ部分がすべてTになっていることがわかります.
ここでTは,コンパイルに関係なく任意の名前を指定する.
このように、鉄牛の中には現在存在する類を使用してもよいし、存在しない類を使用してもよい.ただし、できるだけクラス名の命名規則と同じようにすることが望ましい.鉄牛に宣言されている名前は、クラスの中で一つのタイプのように使えばいいです.鉄牛の中の名前は가상의 타입 이름だと思っています.
では、このような宣言のクラスをどのように使用しますか?
サンプルコード
package d.generic;

public class GenericSample {
    public static void main(String[] args) {
        GenericSample sample = new GenericSample();
        sample.checkGenericDTO();
    }
    
    public void checkGenericDTO(){
        CastingGenericDTO<String> dto1 = new CastingGenericDTO<String>();
        dto1.setObject(new String());
        CastingGenericDTO<StringBuffer> dto2 = new CastingGenericDTO<StringBuffer>();
        dto2.setObject(new StringBuffer());
        CastingGenericDTO<StringBuilder> dto3 = new CastingGenericDTO<StringBuilder>();
        dto3.setObject(new StringBuffer());
一見大差ない.逆に、オブジェクトを宣言する場合、ハンマー内に各タイプが明記されているため、面倒になる可能性があります.ただし、オブジェクトのgetObject()メソッドを使用してオブジェクトをインポートする場合、このdto 1からdto 3を使用すると非常に簡単になります.
String temp1 = dto1.getObject();
StringBuffer temp2 = dto2.getObject();
StringBuilder temp3 = dto3.getObject();
ソースコードをよく見ると、変換する必要はありません.このオブジェクトに宣言されているdto 1~dto 3のジェネリックタイプは、それぞれString、StringBuffer、StringBuilderであるため、エラータイプに変換するとコンパイル自体ができなくなる.したがって、「ランタイム」では、他のタイプに変換したために例外は発生しません.つまり、タイプを明確に指定する際に使われるのがJENICです.

2.ネーミングジェニーンリックタイプ


ジェニーンリックタイプだと宣言したとき、等級を宣言したとき、鉄牛にはどんな単語があっても関係ありません.しかしjavaではいくつかの基本ルールが定義されています.
  • E:主に要素(Element、Javaコレクション)
  • に使用する
  • K:身長
  • N:
  • T:タイプ
  • V:値
  • S、U、V:第2、第3、第4の宣言されたタイプ
  • 3.ジェニーン・リックアンの?


    ジェニーンリックを使う場合、<>に入るタイプは基本的にどんなタイプでも構わない.
    サンプルコード
    package d.generic;
    
    public class WildcardGeneric<W> {
        W wildcard;
        public void setWildCard(W wildcard) {
            this.wildcard = wildcard;
        }
        public W getWildcard() {
            return wildcard;
        }
    }
    このクラスを使用するクラスは次のとおりです.
    package d.generic;
    
    public class WildcardSample {
    
        public static void main(String[] args) {
            WildcardSample sample = new WildcardSample();
            sample.callWildcardMethod();
        }
        
        public void callWildcardMethod() {
            WildcardGeneric<String> wildcard = new WildcardGeneric<String>();
            wildcard.setWildcard("A");
            wildcardStringMethod(wildcard);
        }
        
        public void wildcardStringMethod(WildcardGeneric<String c>{
            String value = c.getWildcard();
            System.out.println(value);
        }
    }
    WildCardStringMethod()を表示する場合、このメソッドのパラメータはStringを使用するWildCardGenericオブジェクトのみを受け入れる必要があります.他のタイプとして宣言されたWildcardGenericオブジェクトを受信する場合は、どうすればいいですか?たとえば、WildcardGenericです.
    この場合、これまで学んだ方法には答えがありません.1つのレベルのタイプを変更するだけではOverridingはできません.したがって、この場合、以下のように宣言することができる.
    public void wildcardStringMethod(WildcardGeneric<?> c) {
        Object value = c.getWildcard();
        System.out.println(value);
    }
    Stringの代わりに?書いておけば、どのタイプがジェニーリックタイプでも大丈夫です.ただし,メソッド内部ではこのタイプが不明であるため,先に用いたようにString受容値を用いることはできず,オブジェクトと見なすべきである.ここにありますか.英語で明示されているタイプをwildcardタイプと呼びます.
    3つのタイプがあれば、方法内でinstanceof予約語を使うことができます.
    public void wildcardStringMethod(WildcardGeneric<?> c) {
        Object value = c.getWildcard();
        if(value instance String) {
            System.out.println(value);
        }
    }
    また,ワイルドカードのみをメソッドのパラメータとして用いることが望ましい.WildCardStringMethod()のcallWildCardMethod()を呼び出します.
    public void callWildcardMethod() {
        WildcardGeneric<?> wildcard = new WildcardGeneric<String>();
        wildcard.setWildcard("A");
        wildcardStringMethod(wildcard);
    }
    このコードは次のエラーメッセージを発行します.正常にコンパイルできません.
    java: incompatible types: lang.WildcardGeneric<capture#2 of ?> cannot be converted to lang.WildcardGeneric<java.lang.String>
    つまり、未知のタイプにStringを指定することはできません.すなわち、オブジェクトをワイルドカードとして宣言し、そのオブジェクトの値を取得できますが、ワイルドカードを使用してオブジェクトを宣言する場合は、この例に示すように、「不可能」は特定のタイプの値を指定します.

    4.ジュネーブ宣言で使用されるタイプの範囲を指定することもできます。


    JENERICを使うときは、<>の中のどのタイプでも大丈夫と言っていますが、ワイルドカードを使うタイプを制限することができます.先に方法を教えてくれたら「?」"? extends 타입"を選択します.
    サンプルコード:
    package d.generic;
    
    public class Car {
        protected String name;
        public Car(String name) {
            this.name = name;
        }
        public String toString() {
            return "Car name="+name;
        }
    }
    package d.generic;
    
    public class Bus extends Car {
        public Bus(String name) {
            super(name);
        }
        public String toString() {
            return "Bus name="+name;
        }
    }
    package d.generic;
    
    public class CarWildcardSample{
        public static void main(String[] args) {
            CarWildcardSample sample = new CarWildcardSample();
            sample.callBoundedWildcardMethod();
        }
        
        public void callBoundedWildcardMethod() {
            WildcardGeneric<Car> wildcard = new WildcardGeneric<Car>();
            wildcard.setWildcard(new Car("Mustang"));
            boundedWildcardMethod(wildcard);
        }
        
        public void boundedWildcardMethod(WildcardGeneric<? extends Car> c) {
            Car value = c.getWildcard();
            System.out.println(value);
        }
    }
    前に使った「?」このようなワイルドカードはどんなタイプでも関係ありません.しかし、boundedWildCardMethod()は「?」代わりに「?extends car」です.このように定義されるのは、JennicタイプでCarを継承するすべてのクラスを使用することができることを意味する.したがって、boundedWildCardMethod()のパラメータは、他のタイプをJENNERICタイプとして宣言するオブジェクトを超えてはいけません.つまり,コンパイル時にエラーが発生するため,Carクラスに関連する継承クラスをスキップしなければならない.
    実行結果

    今回、callbusBoundedWildCardメソッド()を追加し、このメソッドを実行し、再コンパイルして実行します.
    public void callBusBoundedcardMethod() {
        WildcardGeneric<Bus> wildcard = new WildcardGeneric<Bus>();
        wildcard.setWildcard(new Bus("6900"));
        boundedWildcardMethod(wildcard);
    }
    実行結果
    "? extends 타입"과 같은 것을 "Bounded Wildcards"라고 부른다. Boundという言葉にも「境界」という意味があるので、パラメータ化されたJENNERICタイプを指定するための境界と解釈できる.前節で見た「?」使用するワイルドカードと同様に、Bounded WildCardsとして宣言されたタイプに値を割り当てることはできません.したがって、조회용 매개 변수を使用する必要があります.

    5.自分のやり方をアピールする


    ワイルドカード宣言方法の使用方法について説明しました.しかし、この方法には大きな欠点がある.つまり、パラメータとして使用するオブジェクトに値を追加することはできません.それなら仕方ないですか?いいえ.方法がある.
    サンプルコード
    package d.generic;
    
    public class GenericWildcardSample {
        public static void main(String[] args) {
            GenericWildcardSample sample = new GenericWildcardSample();
        }
        
        public <T> void genericMethod(WildcardGeneric<T> c, T addValue) {
            c.setWildcard(addValue);
            T value = c.getWildcard();
            System.out.println(value);
        }
    }
    方法宣言本をよく見て、リターンタイプの前に「>英雄連盟」タイプを発表しました.また、パラメータでは、JENERICタイプを含むオブジェクトを受信して処理していることがわかります.また,メソッドの最初の文からsetWildCard()メソッドで値を割り当てた.
    このコードは本当にコンパイルできますか?
    意外によくできている.このメソッド宣言では、タイプを返す前にJENICタイプを宣言しますが、パラメータでこのタイプを使用している場合、コンパイル時にはまったく問題ありません.しかも値段も割り勘できます.このメソッドが正常に動作しているかどうかを確認するには、次のメソッドを呼び出すメソッドを作成します.
    public void callGenericMethod() {
        WildcardGeneric<String> wildcard = new WildcardGeneric<String>();
        genericMethod(wildcard, "Data");
    }
    実行結果

    ?使用するWildCardのようにタイプを曖昧にするよりも、この方法で宣言するときにタイプを明確に指定すると、より堅牢なコードを書くことができます.もちろん、Bounded WildCardsのように使用することもできます.
    public <T extends Car> void boundedGenericMethod(WildcardGeneric<T> c, T addValue)
    では、ジェニーンリックタイプが2つの場合はどうすればいいのでしょうか.1つ以上のジュネーブタイプの宣言はカンマで区切ることができます.
    public <S, T extends Car> void multiGenericMethod(WildcardGeneric<T> c, T addValue, S another)
    これにより,メソッドにSとTというJENICタイプを用いることができる.
    リファレンス
  • ジャワの神