Java 显式指定通配符的上限时是否有差异?

Java 显式指定通配符的上限时是否有差异?,java,generics,language-lawyer,wildcard,jls,Java,Generics,Language Lawyer,Wildcard,Jls,假设我有一个generic类generic,它说: 给定泛型类型声明C(n>0),参数化类型C,的直接超类型,其中Ti(1≤ 我≤ n) 是一种类型,具有以下所有功能: D,其中D是泛型类型,它是泛型类型C的直接超类型,θ是替换[F1:=T1,…,Fn:=Tn] C,其中Si包含Ti(1≤ 我≤ n) (§4.5.1) (强调矿山) 据我所知,“通配符”在JLS中不被视为“类型”。因此,这不能应用于前两个,但它将应用于两个列表示例 相反,这应适用于: 给定泛型类型声明C(n>0),参数化类型

假设我有一个generic
类generic,它说:

给定泛型类型声明
C
(n>0),参数化类型
C
的直接超类型,其中Ti(1≤ 我≤ n) 是一种类型,具有以下所有功能:

  • D
    ,其中
    D
    是泛型类型,它是泛型类型
    C
    的直接超类型,θ是替换[F1:=T1,…,Fn:=Tn]

  • C
    ,其中Si包含Ti(1≤ 我≤ n) (§4.5.1)

(强调矿山)

据我所知,“通配符”在JLS中不被视为“类型”。因此,这不能应用于前两个,但它将应用于两个
列表
示例

相反,这应适用于:

给定泛型类型声明
C
(n>0),参数化类型
C
的直接超类型,其中至少有一个Ri(1≤ 我≤ n) 是通配符类型参数,是参数化类型
C
的直接超类型,该参数化类型是将捕获转换应用于
C
()的结果

(强调矿山)


应用于
Generic
Generic
Generic>
List
的直接超类型,包含
Generic>
List从字面上理解您最初的问题,在
Generic
Generic>
List
NumberSupplier>
列表无法解释原因,但您可以将原始类型的
泛型
值添加到
列表。我花了一段时间才意识到您实际上有两个问题。第一个基本上是自应答的,在捕获转换后,
List>
List@Holger在某种程度上,是的。子类型“问题”是我想如何回答我的“第一个/原始问题”。但也许它也可以回答没有子类型和捕获转换等。你的意思是用我的第二个例子写这篇文章吗?根据我对JLS的解释,捕获转换根本不适用于这些嵌套通配符。这是个好问题。我花了几天时间。即使搜索了这么长的时间,也很难相信规范中缺少了什么,特别是对于一个似乎不那么模糊的构造。根据本文,如果以下情况之一为真,则两个类型参数是可证明不同的:每个类型参数是一个类型变量或通配符,上界(从捕获转换,如果需要)为S和T;也不是| S |@Klaimmore,但关于“可证明的不同”规则是否以及何时应适用于作业,目前还没有明确的声明。您知道,您可以为Supplier@scottb这是矛盾吗?规范中说“
”扩展对象
等同于无界通配符
”,但事实并非如此。这就是关键所在。如果它确实完全等效,
供应商
Generic<?>
Generic<? extends BaseType>
List<Generic<?>>
List<Generic<? extends BaseType>>
boolean b1 = new Object() instanceof Supplier<?>; // valid code
boolean b2 = new Object() instanceof Supplier<? extends Object>; // invalid

Supplier<?>[] array1; // valid declaration
Supplier<? extends Object>[] array1; // invalid
interface NumberSupplier<N extends Number> extends Supplier<N> {}
NumberSupplier<? extends Object> s1;
NumberSupplier<? extends Serializable> s2;
NumberSupplier<? extends BigInteger> s3;
NumberSupplier<? extends CharSequence> s4;
NumberSupplier<? extends String> s5;
interface MySupplier<S extends CharSequence&Appendable> extends Supplier<S> {}
List<MySupplier<? extends CharSequence>> list1 = Collections.emptyList();
List<MySupplier<? extends Appendable>>   list2 = Collections.emptyList();
list1 = list2; // compiler error
list2 = list1; // dito
list1.set(0, list2.get(0)); // no problem
list2.set(0, list1.get(0)); // no problem
List<MySupplier<?>> list3;
list3 = list1;
list2 = list3; // no problem
// or
list3 = list2;
list1 = list3; // again no problem
List<MySupplier<? extends Object>> list4;
list4 = list1; // compiler error
list2 = list4; // dito
// or
list4 = list2; // dito
list1 = list4; // dito
list4 = list3 = list1; // works
list1 = list3 = list4; // works
list4 = list3 = list2; // works
list2 = list3 = list4; // works