静态值中的泛型和通配符。它说是相同的 class 但不编译

Generics and wildcards in static values. It says that is the same class but doesnt compile

public interface Moo<T> {
    T getValue();
}

public class Bar<T> {
}

public class Foo<T extends Moo<Long>> {
    private static Foo<?> foo;

    private Bar<T> bar;

    public Foo(Bar<T> bar) {
        this.bar = bar;
    }

    //getters and setters

    public void barfoo(List<T> list) {
        System.out.println(list);
    }

    public void foobar(T t) {
        System.out.println(t.getValue());
    }

    public void other() {
        List<? extends Moo<Long>> somelist = null;
        foo.barfoo(somelist);
    }
}

它生成错误,说我无法编译,因为 somelist 无法进入该函数。说 "Required ? extends Moo found ? extends Moo" 我不知道为什么会这样,也不知道怎么解决。

您的 class Foo 的任何实例都将使用扩展 Moo<Long> 的具体类型 T 创建。方法 barfoo 需要类型为 List<T> 的参数,其中此 T 与实例化的类型完全相同。

现在你用List<? extends Moo<Long>>调用这个方法。那个 ? extends Moo<Long> 和你的类型 T 不一样。它可以是 Moo<Long> 的任何其他子类型。所以编译器必须拒绝这个方法调用。

为了清楚起见,让我们创建一个 Moo 接口的实现:

public class MooImpl implements Moo<Long> {
    @Override
    public Long getValue() {
        return null;
    }
}

回到你的 class,在编译器的眼中,类型 Foostatic 成员有一个 unknown 泛型parameter,意思是在Runtime,这个参数可以用anything代替。我们可以很容易地用 Foo 实例实例化 static 成员,由 MooImpl 参数化(我们被允许这样做,因为 MooImpl extends Moo<Long>。我们说 MooImpl编译时 Moo<Long> 的已知子类型

现在让我们看一下other()方法。在运行时,? extends Moo<Long> 可能会导致与 T 不同的类型,这就是编译器会报错的原因。之所以这样做,是因为 ? extends Moo<Long> 代表 Moo<Long> 未知子类型 。这样它 不同于 已知子类型 (MooImpl).

为了让它生效,我们可以把barfoo()方法的参数改成List<? extends Moo<Long>>.

public class Foo<T extends Moo<Long>> {
    private static Foo<?> foo = new Foo<MooImpl>(new Bar<MooImpl>());

    private Bar<T> bar;

    public Foo(Bar<T> bar) {
        this.bar = bar;
    }

    public void barfoo(List<? extends Moo<Long>> list) {
        System.out.println(list);
    }

    public void foobar(T t) {
        System.out.println(t.getValue());
    }

    public void other() {
        List<? extends Moo<Long>> somelist = null;
        foo.barfoo(somelist);
    }
}