Generic<?>
Generic<? extends BaseType>
List<Generic<?>>
List<Generic<? extends BaseType>>
考虑到这一点,我会假设这些是等价的。generic
指定类型参数A
具有baseType
作为上限。
因此,通配符应该始终由basetype
“自动”或“隐式”限定,不管我是否显式指定它。
下面,我试图将我的陶醉与JLS协调起来。
>
D
,其中D
是泛型类型,它是泛型类型C
的直接超型,θ是替换[f1:=t1,...,fn:=tn]。
C
,其中Si含有Ti(1≤i≤n)(§4.5.1)。
(强调我的)
据我所知,“通配符”在JLS中不被视为“类型”。因此,这不能应用于前两个示例,但可以应用于列表
的两个示例。
相反,这应该适用:
由于1是baseType
,因此fresh变量的上限为baseType
。
对于第二种情况,通过
如果Ti是表单的通配符类型参数?扩展Bi,则Si是一个新的类型变量,其上界为glb(Bi,UI[a1:=S1,...,an:=SN]),其下界为null类型。
对于嵌套通配符,我将使用“contains”规则:
一个类型参数T1被称为包含另一个类型参数T2,写为T2<=T1,如果由T2表示的类型集在以下规则的自反和传递闭包下是由T1表示的类型集的可证子集(其中<:表示子类型(§4.10)):
>
?扩展T<=?如果T<:S
则扩展S
<代码>?扩展T<=?
<代码>?超级T<=?super S if S<:t
结合
C
从上面,我得到:
从字面上理解您最初的问题,在generic<?>
和generic<之间“是否有显著的区别”?扩展basetype>
,答案肯定是,它们不等价。
JLS§4.5.1明确规定:
通配符?扩展对象
等效于无界通配符?
。
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;
我们甚至可以在没有实际类型的情况下实现它,使用()->null
扩展number
和charsequence
NumberSupplier<? extends String> s5;
因此,如果我们有类似list
、list
或列表
,并希望根据§4.5.1的contains规则(唯一可以应用的规则)来推断其中任何一个是否是其他类型的子类型,当类型参数是相同类型(t<=t
)时,但是,我们不需要子类型规则,因为所有这些列表类型都是相同的类型:
如果两个引用类型具有相同的二进制名称(§13.1),并且它们的类型参数(如果有的话)是相同的,则它们是相同的编译时类型,递归地应用这个定义。
contains规则仍然很有用,例如,它允许推断映射
是map
的子类型,因为对于第一个类型参数string<=string
,第二个类型参数的类型参数由通配符特定的包含规则覆盖。
所以剩下的问题是,哪个规则允许我们得出numbersuppliver<?>
,numbersuppliver<?扩展对象>
或NumberSupplier<?扩展number>
是相同的类型,因此列表
、列表
或列表
是可相互分配的。
它似乎不是捕获转换,因为捕获转换意味着计算有效的边界,但也为每个绝对是不同类型的通配符创建“新类型变量”。但是没有其他规则涵盖通配符兼容性。或者我没找到。尝试将规范与javac
的实际行为相匹配,得到了一些非常有趣的结果:
给定
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
问题内容: 该问题的答案表明,当方法采用通配符通用类型时,可以访问或修改集合,但不能同时访问或修改集合。(凯西和伯特) 这是什么意思?“ 当方法采用通配符通用类型时,可以访问或修改集合,但不能同时访问两者 ”? 据我所知,方法do1具有d2只能访问但不能修改。d2的方法使c2可以被访问和修改,并且没有编译错误。 通用准则 问题答案: 该问题的答案表明,当方法采用通配符通用类型时,可以访问或修改集合
问号(?)代表通配符,代表泛型中的未知类型。 有时您可能希望限制允许传递给类型参数的类型。 例如,对数字进行操作的方法可能只想接受Number或其子类的实例。 要声明一个上限的Wildcard参数,请列出?,后跟extends关键字,后跟其上限。 例子 (Example) 以下示例说明了如何使用extends来指定上限通配符。 package com.wenjiangs; import java.
类型参数T不应由最终的类型整数限定。不能进一步扩展Final类型 为什么使用final类型作为通配符的上限完全可以,但对类型参数抛出警告?为什么Java甚至允许通配符被最终的上层类型所约束?
问题内容: 有没有一种方法可以使用querySelector或进行通配符元素名称匹配querySelectorAll?我看到属性查询中支持通配符,但不支持元素本身。 我要解析的XML文档基本上是一个简单的属性列表,我需要查找名称中包含某些字符串的元素。 我意识到,如果我需要的话,XML文档可能需要进行重组,但这不会发生。 除了返回使用显然不推荐使用的XPath(IE9删除了它)之外,任何解决方案都
我的问题是,如果我的进程(在linux机器上)需要更多的5 GB(我有30 GB RAM),当我没有指定任何显式堆大小(Xms和Xmx)参数时,我的进程是否会被分配5 GB内存。
这个问题的答案表明,当方法采用通配符泛型类型时,可以访问或修改集合,但不能同时访问或修改集合。(凯西和伯特) 据我所知,方法do1有,因此d2只能被访问,不能被修改。方法d2具有,因此可以访问和修改c2,并且没有编译错误。 通用指南