- 追加された行はこのように表示されます。
- 削除された行は
このように表示されます。
!!!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);
}
}