Java8中不明确的方法,为什么?
为什么这个方法不明确?这段代码在Java7下编译成功 将方法栏更改为:Java8中不明确的方法,为什么?,java,generics,java-8,java-7,ambiguous,Java,Generics,Java 8,Java 7,Ambiguous,为什么这个方法不明确?这段代码在Java7下编译成功 将方法栏更改为: Ambiguous.java:4: error: reference to then is ambiguous then(bar()); ^ both method then(Throwable) in Ambiguous and method then(CharSequence) in Ambiguous match 1 error Java版本 Ambiguous.java:4: e
Ambiguous.java:4: error: reference to then is ambiguous
then(bar());
^
both method then(Throwable) in Ambiguous and method then(CharSequence) in Ambiguous match
1 error
Java版本
Ambiguous.java:4: error: no suitable method found for then(Float)
then(bar());
^
method Ambiguous.then(Throwable) is not applicable
(argument mismatch; Float cannot be converted to Throwable)
method Ambiguous.then(CharSequence) is not applicable
(argument mismatch; Float cannot be converted to CharSequence)
1 error
考虑以下类别:
java version "1.8.0_40"
Java(TM) SE Runtime Environment (build 1.8.0_40-b25)
Java HotSpot(TM) 64-Bit Server VM (build 25.40-b25, mixed mode)
类Foo
实现了Throwable
和CharSequence
。因此,如果将E
设置为该实例,Java编译器不知道调用哪个方法
Java7可能没有问题的原因是泛型实现较少。如果您自己不提供E
(例如(Foo)bar()
),Java将依赖E
的基本验证,即实现异常
,E
因此只被认为是异常
的一个实例
在中,E
的类型现在由then()
调用的参数派生,换句话说,编译器首先查看可能的类型then()
需要什么,问题是它们都是有效的选择。因此,在这种情况下,它变得模棱两可
概念验证: 现在,我们将稍微修改您的代码,并展示如何解决不明确的调用: 假设我们将代码修改为:
public class Foo extends Exception implements CharSequence {
//...
}
它对异常执行了回退操作,但找不到可以处理该异常的类型
如果在Java8中运行原始代码,它将由于调用不明确而出错,但是如果在Java7中运行,它将使用Throwable
方法
简而言之:编译器旨在“猜测”Java8中的E
是什么,而Java7中选择了最保守的类型。如果我说我刚刚用jdk1.8.0\u 40成功运行了您的代码,会有帮助吗?只需将其粘贴到一个全新的Idea项目中,并在导入junit注释的情况下单击“运行”。第一个很明显-在任何java版本上,带浮点的版本都是错误的,正如您看到的错误所示。@marvin82:在它失败的时候。marvin82,它在java8下用浮点编译很好,没有错误,我的错误,我的语言级别被重写了。很抱歉造成混淆。那么,在这种情况下,我们应该避免将接口与类混合使用?@MariuszS:好的,您可以显式地(例如使用(Exception)bar()
,您正在谈论的E
。但是一般来说,最大化(非最终
)class
es和interface
s以及interface
s和interface
s我想是在找麻烦。@MariuszS:不,一般来说,你应该避免声明像E bar()
这样的方法,这些方法基本上说“调用者可以决定bar()
”返回。由于唯一可以保持此承诺的有效返回值是null
,因此此类方法毫无意义。@Holger:在C中,您还可以添加一个new()
constraint。在这种情况下,您强制应该有一个可用的默认约束。在这种情况下,它变得很有用。据我所知,这在Java8中不可用,但最终它可以实现。@CommuSoft:但是当方法不明确时,C如何知道实例化哪种类型?在Java8中,您可以通过添加<代码>将Supplier
参数设置为bar()
,然后调用方可以使用then(bar(DesiredType::new))
来消除歧义,方法是同时提供适当的Supplier
…
java version "1.8.0_40"
Java(TM) SE Runtime Environment (build 1.8.0_40-b25)
Java HotSpot(TM) 64-Bit Server VM (build 25.40-b25, mixed mode)
public class Foo extends Exception implements CharSequence {
//...
}
public class Main {
public static void main(String... args){
then(bar()); // Compilation Error
}
public static <E extends Exception> E bar() {
return null;
}
public static void then(CharSequence actual) {
System.out.println("char");
}
}
/MyClass.java:18: error: method then in class MyClass cannot be applied to given types;
then(bar()); // Compilation Error
^
required: CharSequence
found: Exception
reason: actual argument Exception cannot be converted to CharSequence by method invocation conversion
1 error