web-dev-qa-db-ja.com

Java複数のクラスでのジェネリックワイルドカード

Classオブジェクトが必要ですが、それが表すクラスを強制的にクラスAを拡張し、インターフェイスBを実装します。

できます:

Class<? extends ClassA>

または:

Class<? extends InterfaceB>

しかし、私は両方を行うことはできません。これを行う方法はありますか?

351
Alex Beardsley

実際に、あなたはcanあなたが望むことをすることができます。複数のインターフェイスまたはクラスとインターフェイスを提供する場合は、ワイルドカードを次のようにする必要があります。

<T extends ClassA & InterfaceB>

Sun.comの Generics Tutorial 、特にページの下部にある Bounded Type Parameters セクションを参照してください。必要に応じて、実際に複数のインターフェイスをリストできます。必要なインターフェイスごとに& InterfaceNameを使用します。

これはarbitrarily意的に複雑になる可能性があります。実証するには、JavaDocの Collections#max の宣言を参照してください。これは(2行にラップされています):

public static <T extends Object & Comparable<? super T>> T
                                           max(Collection<? extends T> coll)

なぜそんなに複雑なのですか? Java Generics FAQで述べたように: バイナリ互換性を保つため

これは変数宣言では機能しないように見えますが、クラスに汎用境界を設定する場合は機能します。したがって、必要なことを行うには、いくつかのフープをジャンプする必要があります。しかし、あなたはそれをすることができます。クラスに一般的な境界を設定して、次のようなことを行うことができます:

class classB { }
interface interfaceC { }

public class MyClass<T extends classB & interfaceC> {
    Class<T> variable;
}

必要な制限があるvariableを取得します。詳細と例については、3ページの Generics in Java 5. をご覧ください。 <T extends B & C>では、クラス名が最初に来る必要があり、その後にインターフェースが続くことに注意してください。そしてもちろん、1つのクラスのみをリストできます。

558
Eddie

「匿名」タイプのパラメーター(つまり、?を使用するワイルドカード)ではできませんが、「名前付き」タイプのパラメーターではできます。メソッドまたはクラスレベルで型パラメーターを宣言するだけです。

import Java.util.List;
interface A{}
interface B{}
public class Test<E extends B & A, T extends List<E>> {
    T t;
}
15
user2861738

型パラメーターには複数の境界を設定できます。例えば

public static <T extends Number & Comparable<T>> T maximum(T x, T y, T z)

Tは、ジェネリッククラスBoxに渡される型パラメーターであり、Numberクラスのサブタイプである必要があり、Comparableインターフェイスを実装する必要があります。クラスがバインドされて渡される場合、インターフェイスの前に最初に渡される必要があります。そうでないと、コンパイル時エラーが発生します。

public static <T extends Number & Comparable<T>> T maximum(T x, T y, T z) {
    T max = x;      
    if(y.compareTo(max) > 0) {
        max = y;   
    }

    if(z.compareTo(max) > 0) {
        max = z;                    
    }
    return max;      
}

続きを読む こちら

0
yoAlex5