为什么通配符类型参数不在自引用类型的包装器中的边界内



我有一个接口,其中包含返回或需要 imlementing 类型实例的方法。为此,我创建了一个形式U extends I<U>的类型变量以用作返回类型。当然,目的是U是实现类:

interface SelfReferringInterface<U extends SelfReferringInterface<U>> {
}

现在我有一个包含不相关类型变量的实现类:

class RestrictingType<T> implements SelfReferringInterface<RestrictingType<T>> {
}

以及一个环绕SelfReferringInterface实例的类:

class Wrapper<T extends SelfReferringInterface<T>> {
}

不知何故,对于采用RestrictingType通配符实例的Wrapper类型,我得到了一个类型推断错误:

public class Main {
public static void main(String... args) {
// This type checks
SelfReferringInterface<?> test1;
// This too
RestrictingType<?> test2;
// And this
Wrapper<RestrictingType<Object>> test3;
// This fails
Wrapper<RestrictingType<?>> test4;
// Interestingly this does succeed
Wrapper<? extends RestrictingType<?>> test5;
}
}

编译此值会给出以下错误:

Main.java:23: error: type argument RestrictingType<?> is not within bounds of type-variable T
Wrapper<RestrictingType<?>> test4;
^
where T is a type-variable:
T extends SelfReferringInterface<T> declared in class Wrapper
1 error

为什么RestrictingType<?>不在T范围内?为什么功能相似? extends RestrictingType<?>没有问题?

Wrapper<RestrictingType<T>>适用于任何给定类型的T,因为我们知道Restricting<T>实现了SelfReferringInterface<RestrictingType<T>>。但是,Wrapper<RestrictingType<?>>不起作用,因为Restricting<? #1>可能无法实现SelfReferringInterface<RestrictingType<? #2>>。通配符?表示未知类型,它们在这两个地方可能是两种不同的未知类型

这是另一种了解为什么必须这样做的方法:假设您的Wrapper<T>类可以容纳包装类型的多个项目T。然后绑定<T extends SelfReferringInterface<T>>意味着任何一个项目的类型应该实现SelfReferringInterface<type of any other item>,就像class SortedList<T extends Comparable<T>>意味着列表中的任何一个项目都应该与列表中的任何其他项目进行比较一样。但是,如果您有Wrapper<RestrictingType<?>>,您将能够在其中添加RestrictingType<String>RestrictingType<Integer>项目,因为这两种类型都是RestrictingType<?>的子类型。但是,RestrictingType<String>没有实现SelfReferringInterface<RestrictingType<Integer>>,所以契约被破坏了。

至于为什么Wrapper<? extends RestrictingType<?>>有效,我不太确定,但? extends通配符意味着你不能在其中添加任何项目,所以你不能用它来破坏合同。

最新更新