多级泛型类型中的Java通配符

Cyk*_*ker 7 java generics wildcard

为什么Bar.goOK有争论f2,但不与论证f1

public class HelloWorld {
    public static void main(String[] args) {
        Foo<Foo<?>> f1 = new Foo<Foo<?>>();
        Foo<Foo<String>> f2 = new Foo<Foo<String>>();
        Bar.go(f1);     // not OK
        Bar.go(f2);     // OK
    }

    public static void p(Object o) {
        System.out.println(o);
    }
}

class Foo<E> {
}

class Bar {
    public static <T> void go(Foo<Foo<T>> f) {
    }
}
Run Code Online (Sandbox Code Playgroud)

不应编译器自动推断类型Tcapture of ?在这两种情况下?

Jud*_*tal 2

好问题!

E(在下面的注释中,对于like中的类泛型Foo< E >,将“协变方法”定义为一种E使用 不带任何参数返回 的方法E,而“逆变方法”则相反:它采用类型的形式参数,E但不使用任何参数。不返回涉及 的类型E。[这些术语的真正定义更复杂,但现在不用介意。])

编译器似乎试图在 的情况下T绑定,因为如果你这样做Objectf1

class Bar0 {
    public static < T > void go( Foo< Foo< ? extends T > > f ) {
        // can pass a Foo< T > to a contravariant method of f;
        // can use any result r of any covariant method of f,
        // but can't pass T to any contravariant method of r
    }
}
Run Code Online (Sandbox Code Playgroud)

然后go(f1)有效,但现在go(f2)不行,因为即使如此Foo< String > <: Foo< ? extends String >,这并不意味着Foo< Foo< String > > <: Foo< Foo< ? extends String > >

f1以下是针对和进行编译的一些修改f2

class Bar1 {
    public static < T > void go( Foo< ? super Foo< T > > f ) {
        // can't properly type the results of any covariant method of f,
        // but we can pass a Foo< T > to any contravariant method of f
    }
}

class Bar2 {
    public static < T > void go( Foo< ? extends Foo< ? extends T > > f ) {
        // can't pass a Foo< T > to a contravariant method of f;
        // can use result r of any covariant method of f;
        // can't pass a T to a contravariant method of r;
        // can use result of covariant method of r
    }
}
Run Code Online (Sandbox Code Playgroud)