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

MyMemoWiki

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

提供: MyMemoWiki
2020年2月15日 (土) 08:05時点におけるPiroto (トーク | 投稿記録)による版
ナビゲーションに移動 検索に移動

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

型パラメータ(クラス)

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

  • クラスの型
  • インスタンス変数の型
  • 配列の型
  • コレクション等、他の型パラメータに渡す
  • メソッド引数
  • メソッド戻値
  • キャスト
通常
  1. import java.lang.reflect.Array;
  2. import java.util.ArrayList;
  3. import java.util.Date;
  4. import java.util.List;
  5.  
  6. public class GenericsTest4 {
  7. public static void main(String[] args) {
  8. GenericsTest4 me = new GenericsTest4();
  9. GenTypeTest<Date> gd = me.new GenTypeTest<Date>();
  10. for (int i=0; i<5; i++) {
  11. try {
  12. Thread.sleep(500);
  13. } catch (InterruptedException e) {
  14. e.printStackTrace();
  15. }
  16. Date d = new Date();
  17. gd.addMember(d);
  18. }
  19. Date[] da = gd.getMemberAry();
  20. for (Date: da) {
  21. System.out.println(d.toString());
  22. }
  23. }
  24. private class GenTypeTest<T> { // クラスの型
  25. private T member; // インスタンス変数の型
  26. private T[] members; // 配列の型
  27. private List<T> memList // コレクションに渡す
  28. = new ArrayList<T>();
  29. private void addMember(T member) { // 引数
  30. memList.add(member);
  31. }
  32. private T[] getMemberAry() { // 戻値
  33. // members = new T[memList.size()]; // NG インスタンスの生成
  34. member = memList.get(0);
  35. members =
  36. (T[])Array.newInstance( // キャスト
  37. member.getClass(), memList.size());
  38. memList.toArray(members);
  39. return members;
  40. }
  41. }
  42. }
継承関係を指定
  • <T extends [Class or Interface]> で、指定クラス(インターフェース)の派生クラスであることを指定
  • Clazz<? super [Class or Interface]> で、Clazzが、指定クラス(インターフェース)の基底クラスであることを指定
  1. import java.util.ArrayList;
  2. import java.util.Collections;
  3. import java.util.List;
  4.  
  5. public class GenericsTest5 {
  6. public static void main(String[] args) {
  7. GenericsTest5 me = new GenericsTest5();
  8. CompareUtil<Double> dc = me.new CompareUtil<Double>();
  9. dc.addNum(1.23);
  10. dc.addNum(2.34);
  11. dc.addNum(100.00);
  12. dc.addNum(-5.23);
  13. System.out.println(dc.getMax());
  14. }
  15. // T型の基底クラス(T型を含む)に適応する Comparable を継承した T型
  16. private class CompareUtil<T extends Comparable<? super T>> {
  17. List<T> numList = new ArrayList<T>();
  18. public void addNum(T num) {
  19. numList.add(num);
  20. }
  21. public T getMax() {
  22. Collections.sort(numList);
  23. return numList.get(numList.size()-1);
  24. }
  25. }
  26. }

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

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

拡張forループで使用する

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

  • Iterable<Message>の実装
  1. public class Messages implements Iterable<Message> {
  2. private List<Message> messages;
  3. private List<Message> getMessages(){
  4. if (this.messages == null) {
  5. this.messages = new ArrayList<Message>();
  6. }
  7. return this.messages;
  8. }
  9. public Iterator<Message> iterator() {
  10. return getMessages().iterator();
  11. }
  12. public void add(int index, Message msg) {
  13. getMessages().add(index, msg);
  14. }
  15. public Message get(int index) {
  16. return getMessages().get(index);
  17. }
  18. }