简体   繁体   English

传递给方法的无界通配符

[英]Unbounded wildcard passed to method

public class ColTest {
static<T> T wildSub(ArrayList<? extends T> holder, T arg){
        T t=holder.get(0);
        return t;
    }

    public static void main(String[] args) {
        ArrayList<?> list=new ArrayList<Long>(Arrays.asList(2L,3L,7L));
        Long lng=1L;
        ColTest.wildSub(list, lng);
    }
}

Really interested why this snippet is legal, because the signature of wildSub takes only ArrayList of T or derived from T , and arg of type T . 真的很感兴趣为什么这个片段是合法的,因为wildSub的签名只接受T ArrayList或从T派生,并且类型为T arg。 But <?> means - some specific type, not known, and how it can satisfy the compiler? <?>意味着 - 某些特定类型,未知,以及它如何满足编译器? After all type <?> doesn't mean <? extends Long> 毕竟类型<?>并不意味着<? extends Long> <? extends Long> ... <? extends Long> ...

The compiler is free to infer anything that is compatible with the types of the arguments and return type. 编译器可以自由地推断出与参数类型和返回类型兼容的任何内容。 In your case it can always infer T as Object . 在你的情况下,它总是可以推断TObject Which turns the signature into 这将签名转化为

static Object wildSub(ArrayList<?> holder, Object arg)

Which means it can take any ArrayList as first argument and anything as second. 这意味着它可以将任何ArrayList作为第一个参数,任何东西作为第二个参数。 Since you don't do anything with the return value, Object will be okay. 由于您没有对返回值执行任何操作,因此Object将没问题。

If you think about it as the compiler using Object where ? 如果你把它当作编译器使用Object在哪里? is used, it makes sense why it would compile. 使用它,它编译的原因是有道理的。 That is all there is to it. 这就是它的全部。

If you are doing any operations dependent on ? 如果您正在做任何依赖的操作? being a certain class, you will get a cast exception at run time if the wrong class is passed in. 作为某个类,如果传入了错误的类,您将在运行时获得强制转换异常。

As an addition to existing (correct) answers to make it more clear: 作为对现有(正确)答案的补充,使其更加清晰:

    ...
        Object result1 = ColTest.wildSub(list, lng); //compiles fine with Sun's javac
//      Long result2 = ColTest.wildSub(list, lng);   //does not compile without explicit casting
        Long result2 = (Long) ColTest.wildSub(list, lng);   //compiles fine 
    ...

This is due to capture conversion . 这是由于捕获转换 Internally, compiler converts the type of an expression Foo<?> to Foo<X> , where X is a specific albeit unknown type. 在内部,编译器将表达式Foo<?>的类型转换为Foo<X> ,其中X是特定的未知类型。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM