22

5.1.10 Capture Conversionの JLS の話に気付きましたが、それらが何であるかを理解できません。

誰かが私にそれらを説明したり、例を挙げたりできますか?

4

2 に答える 2

27

Capture conversion was designed to make wildcards (in generics), ? useful.

Suppose we have the following class:

public interface Test<T> {
    public void shout(T whatever);
    public T repeatPreviousShout();

}

and somewhere on our code we have,

public static void instantTest(Test<?> test) {
    System.out.println(test.repeatPreviousShout());
}

Because test is not a raw Test and since repeatPreviousShout() in "hindsight" returns a ?, the compiler knows that there's a T that serves as a type parameter for Test. This T is for some unknown T so the compiler erases the unknown type (for wildcard, it replaces with Object)., hence repeatPreviousShout() returns an Object.

But if we had,

public static void instantTest2(Test<?> test) {
    test.shout(test.repeatPreviousShout());
}

The compiler would give us an error of something like Test<capture#xxx of ?> cannot be applied (where xxx is a number, e.g. 337).

This is because the compiler tries to do the type safety check on shout() but since it received a wildcard, it doesn't know what T represents, hence it creates a placeholder called capture of.

From here (Java theory and practice: Going wild with generics, Part 1), it clearly states:

Capture conversion is what allows the compiler to manufacture a placeholder type name for the captured wildcard, so that type inference can infer it to be that type.

Hope this helps you.

于 2010-12-13T18:13:06.673 に答える
4

ワイルドカード型引数を含むパラメーター化された型は、実際には共用体型です。例えば

List<? extends Number> = Union{ List<S> | S <: Number }

2 つのケースでは、Java は を使用する代わりにList<? extends Number>、キャプチャされたバージョン を使用しますList<S>。ここで、S は上限 を持つ作成されたばかりの型変数ですNumber

(1) http://java.sun.com/docs/books/jls/third_edition/html/expressions.html

式の種類を絞り込む。式の型が である場合、オブジェクトの実行時の型が実際には具体的な型 S ( )List<? extends Number>であることが確実にわかります。そのため、コンパイラは代わりに使用して、より正確な型分析を実行します。List<S>S <: Number>List<S>

キャプチャ変換は、各式に個別に適用されます。これにより、いくつかのばかげた結果が得られます。

<T> void test1(List<T> a){}
<T> void test2(List<T> a, List<T> b){}

List<?> x = ...;
test1(x);    // ok
test2(x, x); // error

(2) http://java.sun.com/docs/books/jls/third_edition/html/typesValues.html#4.10.2

サブタイプのチェックA :< BAは、ワイルドカード引数が含まれます。例えば、

List<? extends Number>  :< B
<=>
Union{ List<S> | S <: Number}  :< B
<=>
List<S> :< B, for all S <: Number

つまり、実際には、タイプのキャプチャされたバージョンをチェックしていますA

于 2011-09-05T23:46:57.253 に答える