在赋值或调用上下文中,参考条件表达式是多边形表达式。这意味着表达式的类型不是将捕获转换应用于lub(T1,T2)的结果,有关T1和T2的详细定义,请参见JSL-15.25.3。相反,根据规范的这一部分,我们还具有:
当多引用条件表达式出现在目标类型为T的特定种类的上下文中时,其第二和第三操作数表达式类似地出现在目标类型为T的相同种类的上下文中。
多边形引用条件表达式的类型与其目标类型相同。
因此,这意味着将目标类型下推到引用条件表达式的两个操作数,并且两个操作数都针对该目标类型。因此,编译器最终从两个操作数收集约束,从而导致无法解决的约束集并因此导致错误。
好的,但是为什么我们在这里得到T的相等边界?
让我们从通话中详细了解一下:
foo(true ? String.class : StringBuilder.class)
foo在哪里:
static <T> T foo(Class<T> clazz) throws Exception { return clazz.newInstance();}当我们
foo()使用表达式调用方法时,我们有了它
true ? String.class :StringBuilder.class。此引用条件表达式在类型为的松散调用上下文中应兼容
Class<T>。表示为,请参阅JLS-18.1.2:
true ? String.class : StringBuilder.class → Class<T>
如下来自JLS-18.2.1的那样:
形式‹表达式→T›的约束公式可简化为:
…
- 如果该表达式是e1形式的条件表达式?e2:e3,约束条件简化为两个约束条件公式:‹e2→T›和‹e3→T›。
这意味着我们获得以下约束公式:
String.class → Class<T>StringBuilder.class → Class<T>
要么:
Class<String> → Class<T>Class<StringBuilder> → Class<T>
从JLS-18.2.2以后,我们有了:
形式为‹S→T›的约束公式如下所示:
…
- 否则,约束将减小为‹S <:T›。
我只包括相关部分。因此,我们现在有:
Class<String> <: Class<T>Class<StringBuilder> <: Class<T>
从JLS-18.2.3开始,我们有:
形式为‹S <:T›的约束公式可简化为:
…
- 否则,根据T的形式减少约束:
*如果T是参数化的类或接口类型,或者参数化的类或接口类型的内部类类型(直接或间接),则让A1,…,An为T的类型参数。在S的超类型中,a使用类型参数B1,…,Bn标识相应的类或接口类型。如果不存在这样的类型,约束将减少为false。否则,约束将减少为以下新约束:对于所有i(1≤i≤n),‹Bi
<= Ai›。
因此
Class<T>,
Class<String>和
Class<StringBuilder>是参数化类,这意味着现在我们的约束减少为:
String <= TStringBuilder <= T
同样从JLS-18.2.3开始,我们有:
形式为‹S <= T›的约束公式,其中S和T是类型实参(第4.5.1节),可简化为:
…
- 如果T是类型:
- 如果S是类型,则约束条件减小为‹S = T›。
因此,我们最终得到了T的这些约束:
String = TStringBuilder = T
最后在JLS-18.2.4中,我们有:
形式为‹S = T›(其中S和T为类型)的约束公式可简化为:
…
- 否则,如果T是一个推断变量α,则约束条件减小到边界S =α。
并且对于类型变量T没有溶液界限
T = String和
T =StringBuilder。满足这两个限制的编译器没有任何类型可以替代T。因此,编译器显示错误消息。
因此,根据当前规范,javac可以,但是规范在此正确吗?好吧,应该研究7与8之间的兼容性问题。因此,我已提交了JDK-8044053,因此我们可以跟踪此问题。



