| ページ一覧 | ブログ | twitter |  書式 | 書式(表) |

MyMemoWiki

SJC-P ジェネリックス 型パラメータ

提供: MyMemoWiki
ナビゲーションに移動 検索に移動

SJC-P ジェネリックス 型パラメータ

型パラメータ(クラス)

以下のような箇所で使用できる

  • クラスの型
  • インスタンス変数の型
  • 配列の型
  • コレクション等、他の型パラメータに渡す
  • メソッド引数
  • メソッド戻値
  • キャスト
通常
import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

public class GenericsTest4 {
    public static void main(String[] args) {
        GenericsTest4 me = new GenericsTest4();
        
        GenTypeTest<Date> gd = me.new GenTypeTest<Date>();
        for (int i=0; i<5; i++) {
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            Date d = new Date();
            gd.addMember(d);
        }
        Date[] da = gd.getMemberAry();
        for (Date d : da) {
            System.out.println(d.toString());
        }
    }
    private class GenTypeTest<T> {           // クラスの型
        private T member;                    // インスタンス変数の型
        private T[] members;                 // 配列の型
        private List<T> memList              // コレクションに渡す
            = new ArrayList<T>();
        private void addMember(T member) {   // 引数
            memList.add(member);
        }
        private T[] getMemberAry() {         // 戻値
         // members = new T[memList.size()]; // NG インスタンスの生成
            member = memList.get(0);
            members = 
             (T[])Array.newInstance(         // キャスト
                   member.getClass(), memList.size()); 
            memList.toArray(members);
            return members;
        }
    }
}
継承関係を指定
  • <T extends [Class or Interface]> で、指定クラス(インターフェース)の派生クラスであることを指定
  • Clazz<? super [Class or Interface]> で、Clazzが、指定クラス(インターフェース)の基底クラスであることを指定
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class GenericsTest5 {
   public static void main(String[] args) {
        GenericsTest5 me = new GenericsTest5();
        
        CompareUtil<Double> dc = me.new CompareUtil<Double>();
        dc.addNum(1.23);
        dc.addNum(2.34);
        dc.addNum(100.00);
        dc.addNum(-5.23);
        System.out.println(dc.getMax());
    }
    // T型の基底クラス(T型を含む)に適応する Comparable を継承した T型
    private class CompareUtil<T extends Comparable<? super T>> {
        List<T> numList = new ArrayList<T>();
        public void addNum(T num) {
            numList.add(num);
        }
        public T getMax() {
            Collections.sort(numList);
            return numList.get(numList.size()-1);
        }
    }
}

メソッドでジェネリックス型を利用する

  • 戻値より前に書く必要がある
  • ?は使えない(よく考えればわかる)
public class GenericsTest6 {
    public static void main(String[] args) {
        System.out.println(MathUtil.log10(365));
        System.out.println(MathUtil.log10(0.56789));
        
        // ボクシングと絡めて利用すると、挙動がややこしい
        // 上の例 MathUtil.log10(365) はOKだが、ここで同様にすると、エラー
        // オートボクシングにより、365 → Integer になり、戻値も Integer
        // アンボクシングにより、Integer → int で、Math.pow(double, double)に適合しなくなる
        //  (Doubleにアンボクシングできない:java.lang.ClassCastException: java.lang.Double)
        System.out.println(Math.pow(10,MathUtil.log10(365.0)));
        System.out.println(Math.pow(10,MathUtil.log10(0.56789)));
    }
}
class MathUtil {
    // メソッドで、ジェネリクス型を使う
    // いろいろバージョンをオーバーロードしなくてもよい
    public static <T extends Number> T log10(T num) {
        double ret = Math.log10(num.doubleValue());
        return  (T) new Double(ret);
    }
}

拡張forループで使用する

Messageクラスを保持するMessagesクラスを拡張forループに対応させる

  • Iterable<Message>の実装
public class Messages implements Iterable<Message> {
    private List<Message> messages;
    private List<Message> getMessages(){
        if (this.messages == null) {
            this.messages = new ArrayList<Message>();
        }
        return this.messages;
    }
    public Iterator<Message> iterator() {
        return getMessages().iterator();
    }
    public void add(int index, Message msg) {
        getMessages().add(index, msg);
    }
    public Message get(int index) {
        return getMessages().get(index);
    }
}