Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/309.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java8中不明确的方法,为什么?_Java_Generics_Java 8_Java 7_Ambiguous - Fatal编程技术网

Java8中不明确的方法,为什么?

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

为什么这个方法不明确?这段代码在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: 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