Udemy 「JavaSE8 インタフェース ラムダ式 ストリーム 集中コース」セクション1、2
今更ながらJava8を本格的に勉強する。
教材URL:
https://www.udemy.com/course/javase8-h/
セクション1
コース全体の説明。割愛。
セクション2 型パラメータとジェネリクス
書き方のまとめ
//型パラメータが指定されたクラス class Base01<T>{} //境界値パラメータが指定されたクラス class Base02<T extends Super01>{} //Stringが指定されたコレクション List<String> list02 = new ArrayList<>(); //型パラメータが指定されたコレクション List<Base01> list03 = new ArrayList<>();
0201 型パラメータの種類と誤例
1. 型パラメータを表す文字の種類→処理対象
E: Element → 要素オブジェクト
K: key → キーオブジェクト
V: Value → 値を表すオブジェクト
T: Type → 一般的なクラスのオブジェクト
?: 型を指定しない → 全オブジェクト
型パラメータの使い分けに明確な判断はない。
0202 型パラメータサンプルプログラム
public class Base01<T> { private T t; public Base01(T t) { this.t = t; } public T getT() { return this.t; } public void setT(T t) { this.t = t; } @Override public String toString() { return "Base01"; } }
Tが例えばString なら全てのTをStringと読み替える。
public class Base02<T extends Super01> { private T t; public Base02(T t) { this.t = t; } public T get() { return this.t; } public void set(T t) { this.t = t; } @Override public String toString() { return "Base02"; } }
T extends Super01 → 拡張型パラメータ
意味:「Super01というクラスであっても、Super01というクラスを拡張したクラスであっても”T”として保存できる。」
例) Super0102 extends Super0101 Super0101 extends Super01
の時、Super0101もSuper0102もBase02のTになることができる。
0203 型パラメータを利用したオブジェクト生成
型パラメータの利点
- 同処理を行うクラスを、処理対象となるオブジェクトごとに作らずに済む。
- Javaの構文として利用。(後章にて解説)
public class S02L03 { public static void main(String[] args) { Base01<String> b01_1 = new Base01<>("Base01_String"); Base01<Integer> b01_2 = new Base01<>(100); Base02<Super01> b02 = new Base02<>(new Super01()); System.out.println(b01_1.get()); // Base01_String System.out.println(b01_2.get()); // 100 System.out.println(b02.get()); // Super01 System.out.println(b01_1); // Base01 System.out.println(b01_2); // Base01 System.out.println(b02); // Base02 } }
0204 型パラメータの構文
1.型パラメータ
<E> → Eのみ <K,V> → KとV
2.境界値パラメータ
Super01 //スーパークラス Sub0101 extends Super01 //サブクラス Sub0102 extends Sub0102 //サブクラスのサブクラス
の時、適用範囲は
<E super Sub0102> → Object, Super01, Sub0101, Sub0102 <E extends Super01> → Super01, Sub0101, Sub0102
0205 境界値パラメータを利用したオブジェクト生成
public class S02L05 { public static void main(String[] args) { // 事前知識 class Base02<T extends Super01> { Base02<Super01> b02_super01 = new Base02<>(new Super01()); Base02<Sub0101> b02_sub0101 = new Base02<>(new Sub0101()); Base02<Sub0101> b02_sub0102 = new Base02<>(new Sub0102()); System.out.println(b02_super01.get()); // Super01 System.out.println(b02_sub0101.get()); // Sub0101 System.out.println(b02_sub0102.get()); // Sub0102 } }
0206 コレクションの基本的な操作
コレクションの型パラメータにスーパークラスを指定すると、
そのスーパクラス、および、スパークラスを継承するクラスのオブジェクトがコレクションに保存できる。
public class S02L06 { public static void main(String[] args) { List<Super01> list01 = new ArrayList<>(); list01.add(new Super01()); list01.add(new Sub0101()); list01.add(new Sub0102()); System.out.println(list01.get(0)); // Super01 System.out.println(list01.get(1)); // Sub0101 System.out.println(list01.get(2)); // Sub0102 System.out.println(list01); // [Super01, Sub0101, Sub0102] Super01 s01 = list01.get(2); // 取り出すときはスーパークラス } }
JavaAPIドキュメントを見るとArrayList< E>のようにちゃんと「E」と書いてある。
意味:Super01をスーパークラスにもつ要素は全て保存できる。
取り出す際(s01)はスーパークラスを書いておけば、
継承している全てのクラスを記述する必要がなくなる。
0207 ジェネリックス型に型パラメータを利用したプログラム
目的:以下のようなコレクションを一個のクラスで実現したい
・ArrayList<String>
・ArrayList<Integer>
・ArrayList<Super01>
注意点:万能ではない。三つで共有できるメソッドのみを実装できる場合のみに有効。
public class BaseList01<E> { private List<E> e; // 新規作成 public void create() { this.e = new ArrayList<E>(); } public List<E> get() { return this.e; } // boolean add(E e) public void add(E element) { e.add(element); } // 初期化 // static<T> List<T> asList(T...a) public void setArray(E[] array) { this.e = Arrays.asList(array); } @Override public String toString() { return e.toString(); } }
これらのメソッドはString, Integer, Super01三つどれでも使えるメソッド
0208 型パラメータを持つコレクションのオブジェクト生成および要素表示
public class S02L08 { public static void main(String[] args) { // 1. Stringのみを保存するArrayListの生成 BaseList01<String> list01 = new BaseList01<>(); list01.create(); list01.add("DOG"); list01.add("CAT"); System.out.println(list01); // [DOG, CAT] // 2. Super01およびSuper01を継承するオブジェクトを保存するArrayListの生成 BaseList01<Super01> list02 = new BaseList01<>(); list02.create(); list02.add(new Super01()); list02.add(new Sub0101()); list02.add(new Sub0102()); System.out.println(list02); // [Super01, Sub0101, Sub0102] } }
こうすることで複数のクラスを作る必要がなくなる
ちなみに一つのlistで複数の型を持てるわけではない。
BaseList01<String> list01 = new BaseList01<>(); list01.create(); list01.add("DOG"); list01.add("CAT”); list01.add(1);
は最初に
BaseList01<String> list01 = new BaseList01<>();
のように初期化しているからString縛り。
BaseList01<E> list01 = new BaseList01<>();
も思いつくが、「E」というクラスは存在しないため、コンパイルエラー。
同じBaseList01というクラスでStringもIntegerもSuper01も扱えたのが注目ポイント。
0209 型パラメータ(?)を利用したプログラム
0208からの続きで、list01とlist02を同時に引数として扱えるようにする方法。
public class S02L09 { public static void main(String[] args) { BaseList01<String> list01 = new BaseList01<>(); list01.create(); String[] Data01 = { "DOG", "CAT" }; list01.setArray(Data01); printList(list01); // [DOG, CAT] BaseList01<Super01> list02 = new BaseList01<>(); list02.create(); Super01[] Data02 = { new Super01(), new Sub0101(), new Sub0102() }; list02.setArray(Data02); printList(list02); // [Super01, Sub0101, Sub0102] } public static void printList(BaseList01<?> pData) { System.out.println(pData); } }
ちなみに
public static void printList(BaseList01<E> pData) {
は同様にコンパイルエラー。
0210 メソッドの構文について
なし