8

私は何かと少し混乱しています。

コレクションではないクラスがありますが、ジェネリック オブジェクトを参照しています。

    public class XClass<E extends AnInterface>{

        E instanceobject;

        public void add(E toAdd){}
    }

    public interface AnInterface{}

    public class A implements AnInterface{}

    public class B implements AnInterface{}

<? extends AnInterface>ジェネリックオブジェクトに複数のサブタイプタイプが同時に必要な場合は、(XClassのインスタンスを宣言するときに)使用される場所を読んだと思います<T extends AnInterface>が、ジェネリッククラスには単一のタイプのサブタイプしか持てません一気に?

ただし、次のものを使用できます。

    XClass<AnInterface> xc = new XClass<AnInterface>();

    A a = new A();
    B b = new B();

    xc.add(a);
    xc.add(b);

このようにして、スーパータイプの複数のサブタイプをジェネリック クラスに渡すことができます......

「?」を使用する目的がわかりません。インターフェイスをジェネリック パラメータとして使用することに何か問題がありますか?

4

4 に答える 4

8

A両方のタイプのオブジェクトを追加できる理由はB、XClassをインターフェイスでパラメータ化したためです。したがって、そのインターフェイスを実装する2つの異なるクラスを追加しても問題はありません。

一方、XClassを次のように定義した場合:

XClass<A> xc = new XClass<A>();

xc.add(b);追加されたすべてのオブジェクトは宣言されたものと同じタイプ(この場合はA)でなければならないため、式はコンパイルエラーを出します。

たとえば、次のように宣言xcした場合:

XClass<? extends AnInterface> xc = new XClass<AnInterface>();

a次に、またはを追加することはもはや合法ではありませんb。なぜなら、xcは未知であるが固定されたサブタイプでありAnInterface、その未知のタイプがAまたは他のものであるかどうかを知る方法がないためBです。

ただし、以前に追加された要素を反復処理できるXClass型を受け入れるメソッドを作成しているとします。(例のために)唯一の制限は、アイテムが拡張されるAnInterfaceことです。実際のタイプが何であるかは関係ありません。

このメソッドは次のように宣言できます。

public static void dummyMethod(XClass<? extends AnInterface> dummy){
//do stuff here, all the elements extend (implement in this case), AnInterface, go wild.
}

そして今、あなたはこのメソッドに、、またはのようなものを渡すことができXClass<A>XClass<B>それXClass<AnInterface>はすべて有効になります。

上記と同じ理由で、渡すオブジェクトに追加できないことに注意してください。未知のタイプが何であるかわかりません!

public static void dummyMethod(XClass<? extends AnInterface> dummy){
//do stuff here, all the elements extend (implement in this case), AnInterface, go wild.
    dummy.add(new A()); //you can't do this, we have no idea what type ? stand for in this case
}
于 2012-08-14T15:26:53.063 に答える
0

EXClass のインスタンスで のサブクラスを 1 つだけ使用し、拡張/実装しAnInterfaceない他のクラスを実装したくない場合に使用できます。AnInterfaceE

たとえば、与えられ public class ClassOne implements AnInterface {}public class ClassTwo implements AnInterface {}

を使用する場合 、追加メソッドでは のオブジェクトのみを使用できpublic class XClass<E extends AnInterface>ます。を使用していますか?またはoのいずれかを実装する任意のクラスを渡すことができます。<ClassOne>XClass xc = new <ClassOne>XClass()ClassOneClassTwoAnInterfaceClassOneClassTw

識別子を使用Eするということは、「このオブジェクトにはタイプ E と任意のサブクラスを使用したい」という意味です。「式に一致する任意の型を使用したい」という意味です

于 2012-08-14T15:30:11.323 に答える
0

あなたの例では、メソッド「add」で型消去が必要なので、クラスでワイルドカードを使用しないでください。

ワイルドカードは、型の消去が必要ない場合 (つまり、.. のサブクラスである限り型を気にしない場合) と、ジェネリック自体のサブタイプが必要な場合にのみ使用します。

于 2012-08-14T15:36:03.640 に答える
0

ワイルドカードは単に、その基準を満たすクラスになることを意味します。そう ?extends AnInterface は、AnInterface を拡張する 1 つの (そして唯一の) クラスになることを意味します。

したがって、次のようになります。

XClass<Impl1>
XClass<Impl2>

等...

ただし、実行時には、そのクラスがどうなるかわかりません。このため、実際の型をパラメーターとして受け取るメソッドの呼び出しは、本質的に安全ではありません。これは、パラメーターが実際にインスタンス化されたインスタンスに適しているかどうかをコンパイラーが知ることができないためです。

リストを例に取ります。次のように何かを宣言できます。

List<? extends Number> list = new ArrayList<Integer>();

次のいずれかを実行しようとするとどうなりますか。

list.add(new Double(0));
list.add((Number) new Long(1L));

コンパイル時にジェネリック パラメーターの型が不明であるため、コンパイルされません。したがって、コンパイラは、Double または Number が実際のインスタンス (この場合はArrayList<Integer>) に渡すのに適しているかどうかを判断できません。これは、悪名高いキャプチャ オブ コンパイル エラーが発生した場合です。

ただし、リストが Number の任意のインスタンス (サブクラスを含む) を取得できることがコンパイル時に確実にわかっているため、これは許容されます。

List<Number> list = new ArrayList<Number>();
list.add(new Double(0));
list.add((Number) new Long(1L));
于 2012-08-14T15:40:29.947 に答える