Open5
Recursive Generics and Java's Type Erasure

モチベーション
"Effective Java Third Edition" [1] のBuilder
パターン
// Builder pattern for class hierarchies
public abstract class Pizza {
public enum Topping {
HAM, MUSHROOM, ONION, PEPPER, SAUSAGE
}
final Set<Topping> toppings;
abstract static class Builder<T extends Builder<T>> {
EnumSet<Topping> toppings = EnumSet.noneOf(Topping.class);
public T addTopping(Topping topping) {
toppings.add(Objects.requireNonNull(topping));
return self();
}
abstract Pizza build();
// Subclasses must override this method to return "this"
protected abstract T self();
}
Pizza(Builder<?> builder) {
toppings = builder.toppings.clone(); // See Item 50
}
}
-
Bloch, J. (2017). Effective java. Addison-Wesley Professional. ↩︎

abstract static class Builder<T extends Builder<T>> {...}
この再帰ジェネリクスが気になる.

TypeMirror erasure(TypeMirror t)
型の消去を返します。

interface
しか定義してない.
どうやらjavac
側でコンパイラの実装はやってるらしい.
例えば
javax.lang.model.util.Types
インターフェースのスケルトン実装: https://github.com/fschopp/java-types

深掘りしすぎて理論と実装が渋滞し始めた感じ
ここまでの流れをざっくり整理すると:
🧵 話題のざっくりマップ
-
Javaの型システムとErasure
- 再帰ジェネリクス(
Builder<T extends Builder<T>>
) - 実行時にはただの
Builder
になる理由(型消去)
- 再帰ジェネリクス(
-
Kotlinとの違い
-
Builder
パターン =命名引数
+デフォルト引数
-
reified
型パラメータで型情報を保持できる
inline fun <reified T> inject(): T { // リフレクションなしでTのクラスが取れる return T::class.java.newInstance() } inline fun <reified T> createInstance(): T { return T::class.java.getDeclaredConstructor().newInstance() }
呼び出し時
val foo: Foo = createInstance<Foo>()
-
-
型検査のアルゴリズム
- 名前ベース vs 構造ベース vs 型推論 vs サブタイプ判定
-
アノテーションと型引数
-
@Composable
の思想と、Javaにおける型アノテーションの可能性
-
-
IntelliJの内部
- PSI型システムとSwingベースのUI設計
-
Joshua Blochの影響力
-
Enum
,Optional
,ImmutableList
が好きなのも納得
-