4

Java の Generics、つまりワイルドカードの使用について質問があります。次のようなクラス GenClass の例があります。

public class GenClass<E> {

    private E var;

    public void setVar(E x) {
        var = x;
    }

    public E getVar() {
        return var;
    }
}

私は別の単純なクラスを持っています:

public class ExampleClass {

}

次のテストクラスを作成しました。

public class TestGenClass {

    public static void main(String[] str) {

        ExampleClass ec = new ExampleClass();

        GenClass<ExampleClass> c = new GenClass<ExampleClass>();

        c.setVar(ec);
        System.out.println(c.getVar());  // OUTPUT: ExampleClass@addbf1
    }

}

ここで、ワイルドカードを使用してテスト クラスに次のように記述します。

GenClass<?> c = new GenClass<ExampleClass>();

の場所に:

GenClass<ExampleClass> c = new GenClass<ExampleClass>();

コンパイラはこの新しいステートメントに問題はありませんが、

c.setVar(ec);

「メソッド(setVar())は引数(ExampleClass)には適用されません」と書かれています。このメッセージが表示されるのはなぜですか?

私がワイルドカードを使用した方法では、参照変数 c が GenClass 型になり、パラメーターとして任意のクラスを受け入れるようになると思いました-EI の代わりに任意のクラスがあります。これは単なる変数の宣言です。次に、それを初期化します

new GenClass<ExampleClass>()

これは、タイプ ExampleClass のクラスをパラメータとして持つ、タイプ GenClass のオブジェクトを作成することを意味します。したがって、GenClass の E は ExampleClass になり、メソッド setVar() を使用して、引数として ExampleClass 型の何かを与えることができると思います。これは私の仮定と理解でしたが、Java はそれを好まないようで、正しくありません。どんなコメントでも大歓迎です、ありがとう。

4

2 に答える 2

14

この正確な状況は、Java Generics Tutorialで説明されています。

[ワイルドカードを使用して]、[ジェネリックCollection] から要素を読み取り、それらに type を与えることができることに注意してくださいObject。コレクションの実際のタイプが何であれ、オブジェクトが含まれているため、これは常に安全です。ただし、任意のオブジェクトを追加するのは安全ではありません。

Collection<?> c = new ArrayList<String>();
c.add(new Object()); // Compile time error

の要素型が何を表しているのかわからないcため、オブジェクトを追加することはできません。このメソッドは、コレクションの要素add()の型である type の引数を取ります。E実際の型パラメーターが の?場合、それは未知の型を表します。渡すパラメータはadd、この未知の型のサブタイプでなければなりません。型がわからないので、何も渡すことができません。唯一の例外はnull、すべての型のメンバーである です。

(私のものを強調)

于 2009-02-02T16:12:47.730 に答える
2

mmyers には正しい答えがありますが、質問のこの部分についてコメントしたかっただけです (ワイルドカードを使用したい理由のように聞こえます):

私がワイルドカードを使用した方法では、参照変数 c が GenClass 型になり、パラメーターとして任意のクラスを受け入れるようになると思いました-EI の代わりに任意のクラスがあります。これは単なる変数の宣言です。次に、それを初期化します

本当にこれを達成したい場合は、コンパイルエラーなしで次のようにすることができます:

GenClass<Object> gc = new GenClass<Object>();
gc.setVar(new ExampleClass());

しかし、繰り返しになりますが、任意の型を含むことができる のインスタンスを宣言したい場合、GenClassジェネリックを使用する理由がまったくわかりません-生のクラスを使用できます。

GenClass raw = new GenClass();
raw.setVar(new ExampleClass());
raw.setVar("this runs ok");
于 2009-02-02T16:30:51.687 に答える