複数のインターフェイスを実装したクラスのみ受け付ける型パラメータの指定
クラスやメソッドの型パラメータ指定では、"&"を使って受け付けるクラスの条件を結合することができます。これを使用して、「インターフェイスA,インターフェイスBの両方を実装したクラスのみ受け付ける」といった制約を行うことができます。
- "&"で結合できるのはインターフェイスのみです。複数のクラスは結合できません。(当たり前といえば当たり前ですが。)
- 「1つのクラス + 複数のインターフェイスを実装」という制約は実現可能です。このとき、クラスは左端(extendsの直後に書く必要があります。)
以下はサンプルです。まずはインターフェイス定義。
static interface A { void a(); } static interface B { void b(); } static class AImpl implements A { public void a() {}; public void ai() {}; } static class BImpl implements B { public void b() {}; public void bi() {}; } static class ABImpl implements A, B { public void a() {}; public void b() {}; public void ab() {}; } static class CImpl extends AImpl implements B { public void b() {}; public void c() {}; }
"&"を使った制約指定がされたクラス。
// AImpl派生でBを実装したオブジェクトのみ受け付ける型パラメータの制約指定がされたクラス // クラスは左端に1つだけ指定できる。 // X<T extends AImpl & BImpl> や // X<T extends A & BImpl> はコンパイルエラーになる。 class X<T extends AImpl & B> { void set( T obj ) { obj.a(); // AImpl と BのAPIが使える。 obj.b(); obj.ai(); } T get( ) { return null; } } //X<A> x = new X<A>(); //X<AImpl> x = new X<AImpl>(); //X<BImpl> x = new X<BImpl>(); //X<ABImpl> x = new X<ABImpl>(); X<CImpl> x = new X<CImpl>(); // これ以外はコンパイルエラー
JDKのAPIでは、java.util.Collectionsなどで使われています。
public static <T extends Object & Comparable<? super T>> T min(Collection<? extends T> coll) { ...