What is a capture conversion in Java and can anyone give me examples?

前端 未结 2 1188
小蘑菇
小蘑菇 2020-12-01 10:56

I\'ve noticed JLS talks of 5.1.10 Capture Conversion, but I fail to understand what they are.

Can anyone explain them to me/give examples?

相关标签:
2条回答
  • 2020-12-01 11:32

    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.

    0 讨论(0)
  • 2020-12-01 11:36

    A parameterized type involving wildcard type arguments is really a union type. For example

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

    In 2 cases, instead of using List<? extends Number>, Java uses the captured version List<S>, where S is a just-created type variable with upper bound Number.

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

    To narrow the type of an expression. If an expression's type is List<? extends Number>, we know for sure that the runtime type of the object is actually a List<S> for some concrete type S (S <: Number>). So compiler uses List<S> instead, to perform more accurate type analysis.

    Capture conversion is applied to each expression individually; this leads to some dumb results:

    <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

    In subtype checking A :< B where A involves wildcard arguments. For example,

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

    So in effect, we are checking the captured version of type A

    0 讨论(0)
提交回复
热议问题