● 複数のメソッド間の引数・戻り値の
型の関係性
● 公開されているフィールド
● 内部クラス
new するタイミングで型変数の具体的
な型を指定する(型変数のバインド)
インスタンス単位で別のバインド
new ArrayList();
new ArrayList();
インスタンススコープのジェネリクス
Slide 16
Slide 16 text
java.util.ArrayListの例
public boolean add(E e)
public E get(int index)
複数のメソッド間で型の関連性を表現している
ジェネリックなインスタンスの例
Slide 17
Slide 17 text
ArrayList の iterator() はエンクロージング内部クラス Itr を返す
public Iterator iterator() {
return new Itr();
}
内部クラス Itr の宣⾔はこんな感じ。ArrayListの を
Iterator としてバインドして使っている
public class ArrayList /** いろいろ略 */ {
private class Itr implements Iterator { … }
}
インスタンスに紐づく内部クラスへの波及
ArrayList
Itr
implements
発展的内容
Slide 18
Slide 18 text
public class Syntax
implements Iterable {
public void hoge(X x) {
List list = new ArrayList();
list.add(x);
}
@Override
public Iterator iterator() {
return null;
}
}
似て非なる<>を色分けしてみました
⽂法の話
Slide 19
Slide 19 text
型変数の宣⾔
class Hoge{} // インスタンススコープ
public void hoge() {} // メソッドスコープ
型変数のバインド
new ArrayList(); // new でのバインド
class StringList extends ArrayList {} // 継承でのバインド
Collections. replaceAll(list, "hoge", "piyo"); // メソッドでのバインド
パラメータ化された型 (parameterized type)
List list;
3種の<>
Slide 20
Slide 20 text
ジェネリッククラスの例 java.util.ArrayList より
宣⾔側
public class ArrayList /*略*/ {}
利⽤側でバインド
List list = new ArrayList();
推論
List list = new ArrayList<>();
型変数の宣⾔とバインド
Slide 21
Slide 21 text
継承によるバインド
class StringList extends ArrayList
継承の際に型変数をバインドすることもできる
class StringKeyMap extends HashMap
型変数の宣⾔とバインド
Slide 22
Slide 22 text
ジェネリックメソッドの例 java.util.Collections より
宣⾔側
public static boolean replaceAll
(List list, T oldVal, T newVal)
利⽤側
Collections.replaceAll(list, "hoge", "piyo");
推論
Collections.replaceAll(list, "hoge", "piyo");
型変数の宣⾔とバインド
Slide 23
Slide 23 text
ジェネリックメソッド、複数型変数の例 java.util.Collections より
宣⾔側
public static Map singletonMap(K key, V value)
利⽤側
Collections.singletonMap("hoge", 123);
推論
Collections.singletonMap("hoge", 123);
型変数の宣⾔とバインド
Slide 24
Slide 24 text
インスタンススコープとメソッドスコープ併⽤の例 java.util.Optional
宣⾔側
public Optional map(Function super T, ? extends U> mapper)
利⽤側
Optional optI = Optional.of(123);
Optional optS = optI.map( (Integer i) -> i.toString());
推論
var optI = Optional.of(123);
var optS = optI.map( (i) -> i.toString());
型変数の宣⾔とバインド
発展的内容
Slide 25
Slide 25 text
「パラメータ化された型」§4.5. Parameterized Types
変数宣⾔時の型で出てくる<>
List stringList = List.of("甲","⼄","丙");
パラメタライズドタイプではワイルドカードが使える
List> someList;
List extends Hoge> extendsList;
List super Hoge> superList;
詳細は後ほど
パラメタライズドタイプ
Slide 26
Slide 26 text
T 型のオブジェクト x に関して真となる属性を
q(x) とする。
このとき S が T の派⽣型であれば、
S 型のオブジェクト y について q(y) が真となる。
端的に⾔えば、親クラスは⼦クラスで代替できる。
⼦クラスは親クラスの機能を全て代替できなけれ
ばならない。
リスコフの置換原則
計算機科学博⼠
バーバラ・リスコフ
1939年〜
Slide 27
Slide 27 text
Javaは変数の代⼊は共変(covariant)なので
Integer integer = Integer.valueOf(123456);
Number number = integer;
といったように、親の型の変数に⼦の型の変数を代⼊することができる
逆は無条件ではできなくて明⽰的なキャストが必要、
かつ実⾏時例外も出る
Number number = Integer.valueOf(123456);
Integer integer = (Integer) number;// 常に成功するとは⾔えない
Javaの変数は基本的に共変
Slide 28
Slide 28 text
このパターンはOK
ArrayList arrayList = new ArrayList<>();
List list = arrayList;
このパターンはNG
List integerList = List.of(123);
List numberList = integerList; // NG
パラメタライズドタイプと共変・⾮変
なんでだろう?
型の不⼀致: List から
List には変換できません
Slide 29
Slide 29 text
パラメタライズドタイプの型変数部分が共変だとダメな例
飲⽤ボトル<粉ミルク> 哺乳瓶 = new 飲⽤ボトル<粉ミルク>();
飲⽤ボトル<飲料> ボトル = 哺乳瓶; // 実際はNG
ボトル.add (new ウイスキー());
パラメタライズドタイプと共変・⾮変
Slide 30
Slide 30 text
このパターンはOK 型識別⼦部分は共変(covariant)
ArrayList arrayList = new ArrayList<>();
List list = arrayList;
このパターンはNG 型変数部分は⾮変(invariant)
List integerList = List.of(123);
List numberList = integerList; // NG
§4.10. Subtyping
パラメタライズドタイプと共変・⾮変
public class Hoge
型変数を宣⾔する際に型変数Tの上限境界を指定することが出来る。
ここでは extends は使えるが super は使えない。
パラメタライズドタイプのワイルドカードと紛らわしい
public class Hoge
& を⽤いて interface を implements していることを表すこともできる
型変数の境界
ジェネリクス関連のJEPはいくつか存在している
● JEP 218: Generics over Primitive Types (2014 / 2017 updated)
● JEP 300: Augment Use-Site Variance with Declaration-Site
Defaults (2014 / 2016 updated)
● JEP 402: Enhanced Primitive Boxing (Preview) (2021 / 2024
updated)
● JEP draft 8261529: Universal Generics (Preview) (2021 / 2023
updated)
● JEP draft 8303099: Null-Restricted and Nullable Types (Preview)
(2023 / 2024 updated)
未来のジェネリクス
Slide 52
Slide 52 text
2014年の古株のJEP
Project Valhalla の管轄
プリミティブ型をジェネリクスで扱えるようにする
内容としては JEP 402 と被っていて 402 で進められていそう
JEP 218: Generics over Primitive Types
Slide 53
Slide 53 text
更新が⽌まっているので活きているのかどうなのか
Java の型変数は 利⽤側で変性を宣⾔する⽅式(use-site
variance annotations)
C#やKotlinは型変数の宣⾔側で変性を指定(declaration-site
variance annotations)
宣⾔側でデフォルトの変性を指定できるようにしようという試み
JEP 300: Augment Use-Site Variance
with Declaration-Site Defaults
Slide 54
Slide 54 text
Java / Java VM のリファクタリングをする巨⼤プロジェクト
Value Type を導⼊してVMの効率をアップする⽬論み
既存のものも含め Value Type / 参照型 に整理
そのどちらでも同様にジェネリクスを適⽤
Codes like a class, works like an int.
Project Valhalla
Slide 55
Slide 55 text
Valhalla 関連 JEP
Valhallaで導⼊予定のValue Typeもジェネリクスで⽤いること
が出来るように。
Valhalla⾃体が検証中であるため、⽅針が⼆転三転。
最近、ステータスが Closed / Withdrawn になった。
後述のJEPに置き換わった模様
JEP draft: Universal Generics (Preview)
Slide 56
Slide 56 text
Valhalla 関連 JEP
プリミティブ型を参照型っぽく使えるように。
この⼀環としてプリミティブ型を型変数に⽤いることができるよ
うにする。
JEP 402: Enhanced Primitive Boxing (Preview)
int i = 12;
int iSize = i.SIZE;
double iAsDouble = i.doubleValue();
Supplier iSupp = i::toString;
Slide 57
Slide 57 text
Valhalla 関連 JEP
Javaの参照型を強化し、nullがある型かどうか表現できるように
する。
型変数にもnull許容 / null制限 を表現できるように拡張する
● T ! - null 制限型
● T ? - null 許容型
● Box - null制限型のパラメタライズドタイプ
● Box - null許容型のパラメタライズドタイプ
JEP draft: Null-Restricted and Nullable Types
(Preview)
Slide 58
Slide 58 text
Radu Grigore (2016). Java Generics are Turing Complete
絶対にIDEに貼り付けてはいけない。
絶対にバージョン管理システムに
コミットしてはいけない。
絶対にCIを回してはいけない。
Javaのジェネリクスはチューリング完全?
コードなコピペそ
Slide 59
Slide 59 text
l Java⾔語仕様
l The Java® Language Specification Java SE 21 Edition
https://docs.oracle.com/javase/specs/jls/se21/html/
l Java標準APIのjavadoc
l Java® Platform, Standard Edition & Java Development Kit バージョン21 API仕様
https://docs.oracle.com/javase/jp/21/docs/api/
l JEP 各種
l https://openjdk.org/jeps/0
l Project Valhalla
l https://openjdk.org/projects/valhalla/
l Radu Grigore (2016). Java Generics are Turing Complete
l 五⼗嵐淳 (2002). On Variance-Based Subtyping for Parametric Types
l @nagiseの過去の資料
l Project Valhalla 2023
https://nagise.hatenablog.jp/entry/2023/04/17/210648
l Java Generics Hell Advent Calendar 2017
https://adventar.org/calendars/2751
l OpenJDK の duke ギャラリー
l https://wiki.openjdk.org/display/duke/Gallery
l いらすとや
l https://www.irasutoya.com/
参考⽂献リスト
Duke Duchess