此类在Java 7中可以编译,但在Java 8中不能编译:
public class Foo {
public static void main(String[] args) throws Exception {
//compiles fine in Java 7 and Java 8:
Class<? extends CharSequence> aClass = true ? String.class : StringBuilder.class;
CharSequence foo = foo(aClass);
//Inlining the variable, compiles in Java 7, but not in Java 8:
CharSequence foo2 = foo(true ? String.class : StringBuilder.class);
}
static <T> T foo(Class<T> clazz) throws Exception {
return clazz.newInstance();
}
}
编译错误:
错误:(9,29)java:类Foo中的方法foo无法应用于给定类型;必需:java.lang.Class找到:true吗?str […]类
原因:推断的类型不符合相等的约束推断的:java.lang.StringBuilder相等约束:java.lang.StringBuilder,java.lang.String
为什么这在Java 8中停止了工作?它是否是故意的/其他功能的副作用,还是仅仅是编译器错误?
在赋值或调用上下文中,参考条件表达式是多边形表达式。这意味着表达式的类型不是将捕获转换应用于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 <= T
StringBuilder <= T
同样从JLS-18.2.3开始,我们有:
形式为‹S <= T›的约束公式,其中S和T是类型实参(第4.5.1节),可简化为:
…
- 如果T是类型:
- 如果S是类型,则约束条件减小为‹S = T›。
因此,我们最终得到了T的这些约束:
String = T
StringBuilder = T
最后在JLS-18.2.4中,我们有:
形式为‹S = T›(其中S和T为类型)的约束公式可简化为:
…
- 否则,如果T是一个推断变量α,则约束条件减小到边界S =α。
并且对于类型变量T没有溶液界限T = String
和T = StringBuilder
。满足这两个限制的编译器没有任何类型可以替代T。因此,编译器显示错误消息。
因此,根据当前规范,javac可以,但是规范在此正确吗?好吧,应该研究7与8之间的兼容性问题。因此,我已提交了JDK-8044053,因此我们可以跟踪此问题。
问题内容: 我在编写一些Java代码时遇到了编译失败,我将其简化为以下测试用例: 上面的代码无法使用JDK 1.7.0_45 进行编译: 但是,使用JDK 1.8.0_05编译时不会出现任何错误。 这是Java 7实现中的错误吗?还是对Java 8中的Java语言规范进行了增强以开始允许这样做-如果是这样,有什么变化? 问题答案: JLS SE 8在(§15.2)中说: 当某些表达式出现在某些上下
请考虑此类: null
问题内容: 为什么会产生错误,应如何写? 错误是“找不到<接受提供的参数的重载” 问题答案: 您的三元运算符在那里不工作的 原因 是由于各种中缀运算符的优先级。您可以在此处查看运算符优先级列表。如果您看一下,会发现底部的运算符通常是放置在较大代码段之间的运算符。优先级越高,它将越紧紧抓住左侧(或右侧)的表达式。因此,您通常希望您的运算符具有非常低的关联性,因此在类似以下的表达式中: 该会抢在它两侧
问题内容: 我一直不得不放置没有任何其他条件的其他条件。反正周围有吗?例如 基本上,有什么方法可以做: 现在它显示为语法错误 仅供参考,这是一些真实的示例代码: 问题答案: 首先,三元表达式不能替代if / else构造-它等同于 返回 值的if / else构造。也就是说,if / else子句是code,三元表达式是 expression ,表示它返回一个值。 这意味着几件事: 仅当在变量的左
我有一个maven项目,并将intellij配置为使用Java8。我的一个同事推了一个更改,在界面中使用默认关键字。自从我同步了他的更改后,我的编译每次都失败了。 我目前被难住了,在网上找不到答案。
据我所知,PowerShell似乎没有一个针对所谓三元运算符的内置表达式。 例如,在支持三元运算符的C语言中,我可以编写如下内容: 如果PowerShell中并不存在这种情况,那么实现相同结果的最佳方法(即易于阅读和维护)是什么呢?