4

私が理解している限り、Java Genericsは、ジェネリックメソッド(またはジェネリッククラス)のパラメーター型Tに関するすべての情報を消去します。だから使えない

などの新しい表現

new T()

などの式のインスタンス

if(obj instanceof T)

ジェネリックメソッド内。

私の質問は、キャストに関して、パラメーター型Tがジェネリックメソッド内でどのように機能するかです。たとえば、ここには3つの簡単なクラスがあります。

public class People {

    String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public People(String name) {
        super();
        this.name = name;
    }

    @Override
    public String toString() {
        return "People [name=" + name + "]";
    }

}

public class GenericClass<T> {

    public T getCast(People p) {
        return (T)p;
    }
}

public class App 
{
    public static void main( String[] args )
    {
        People p = new People("Kewei");

        GenericClass<Integer> genericClass = new GenericClass<Integer>();
        Object p_object = genericClass.getCast(p);

        System.out.println(p_object);
    }
}

(T)pジェネリックメソッドでを実行する場合getCast(People p)。タイプTをオブジェクトとして使用するだけですか?(T)または、コンパイル時にキャスト全体を削除するだけですか?ブルース・エッケルの「Thinking in Java」を読んだことがありますが、大まかに次のように理解しています。

Javaコンパイラは、コンパイル時にメソッドのエントリ/リーブポイントをチェックして、ジェネリックメソッドの内部整合性を確認し、(コンパイル時に)キャストコードを挿入します。

それは正しい理解ですか?

ありがとう。

4

2 に答える 2

4

コンパイラーがジェネリックスを含むコードをジェネリックスを含まないコードに「再書き込み」することを頭の中で考えることができます。

ジェネリッククラスでは、Tはその上限(この場合はObject)が消去されるまで消去されますが、他の何かである可能性があります。TへのキャストはTの上限へのキャストになります(この場合はObjectであるため、冗長であり、コンパイラーはそれをスキップする可能性があります)。このメソッドは、同様にTの上限(オブジェクト)を返します。したがって、キャストがメソッド内で有効であるという実行時チェックはありません。

public class GenericClass {

    public Object getCast(People p) {
        // In this case the cast to T is removed because T's upper bound is Object.
        // But if T's upper bound was, say, Number, then there would still be a cast
        // to the upper bound. e.g. "(Number)p", and the return type would also be Number
        return p;
    }
}

Tを返すメソッドを呼び出す場所で、コンパイラはTの実際の型にキャストを挿入します。この場合、mainメソッドにはがありますGenericClass<Integer>。したがって、getCastTを返すと、整数にキャストされます。したがって、この場合、ランタイムチェックは、キャストのあるメソッドではなく、呼び出し元のメソッドに「移動」されます。

// somewhere else
GenericClass genericClass = new GenericClass();
p_object = (Integer)genericClass.getCast(p);

呼び出し元がGenericClass<S>(スコープ内の一部の型パラメーターSの)参照を保持している可能性もあります。そのため、結果は特定の型ではなくSにキャストされます。次に、再書き込みプロセス全体を再度繰り返します(つまり、Sへのキャストは上限へのキャストに再書き込みされ、そのメソッドを呼び出す場所は結果を実際の型引数にキャストします)。これは、ランタイムチェックがさらに別の場所に延期される可能性があることを意味します。

于 2012-07-06T01:14:32.877 に答える
-1

Javaは何もキャストしません。実行時には、単に「オブジェクトとして」扱われます。JREはそのオブジェクトのメソッドを呼び出そうとしますが、コンパイル時に存在することが証明されているため、機能します。

実行時のクラスTへの参照はありません。なし。したがって、キャストは行われません。

于 2012-07-05T23:06:51.010 に答える