Java 8中的歧义方法,为什么?

MariuszS:
public static void main(String... args){
    then(bar()); // Compilation Error
}

public static <E extends Exception> E bar() {
    return null;
}

public static void then(Throwable actual) { }

public static void then(CharSequence actual) { }

编译结果(从命令行javac Ambiguous.java

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 7下成功编译!

将方法栏更改为:

public static <E extends Float> E bar() {
    return null;
}

编译没有任何问题,但是在IntelliJ Idea中报告为错误(无法解析method then(java.lang.FLoat))。

此代码在Java 7下失败- javac -source 1.7 Ambiguous.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版本

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)
威廉·范昂塞姆(Willem Van Onsem):

考虑以下类别:

public class Foo extends Exception implements CharSequence {
    //...
}

该类同时Foo实现ThrowableCharSequence因此,如果E将其设置为该实例,则Java编译器将不知道调用哪个方法。

Java7可能没有问题的原因是泛型的实现较少。如果您不提供E自己的信息(例如(Foo) bar()),则Java会退回其基本版本Eimplements ExceptionE因此仅被视为的实例Exception

Java8中类型推断得到了改进E现在的类型是从by所调用的参数派生的then(),换句话说,编译器首先查找可能then()需要的类型,问题在于它们都是有效的选择。因此,在这种情况下,它变得模棱两可。


概念证明

现在,我们将稍微修改您的代码,并显示如何解决歧义调用:

假设我们将代码修改为:

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");
    }
}

如果您在Java8中运行它,那么就不会有问题(它会打印char),因为Java8只是假设存在此类Foo(它为这两个类派生了某种“内部”类型)。

Java7中运行它产生问题:

/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

它进行了回退,Exception找不到可以处理的类型。

如果您在运行原始代码Java8,它将错误,因为暧昧通话,如果你在运行它Java7但是,它会使用Throwable方法。


简而言之:编译器旨在“猜测” EJava8中的内容,而在Java7中则选择了最保守的类型。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

Java ArrayList中Remove方法的歧义

为什么JCF接口中的许多方法未在Java 8中设为默认方法?

为什么Java 8接口方法中不允许使用“最终”?

为什么在Java8的Functional Interface中不使用多个抽象方法?

为什么允许Java 8中的接口具有main方法?

为什么在Java 8中转换类型的reduce方法需要组合器

在Java 8中,为什么不为Array提供Iterable的forEach方法?

为什么我不能在ColdFusion 8中调用java-apns getInactiveDevices()方法?

在Java 8中,为什么不能调用当前类正在实现的接口静态方法

为什么main方法在Java中是静态的

Java8:lambda和重载方法的歧义

Java8:为什么禁止为java.lang.Object中的方法定义默认方法

为什么Java 8中的新java.util.Arrays方法没有对所有原始类型都重载?

为什么Java 8中没有BooleanConsumer?

为什么在Java 8中按顺序收集并行流

为什么在Java 8中编译此通用代码?

为什么Java8不在yum中?

为什么在参数中不使用Java 8的Optional

为什么Java 8中没有原始BiConsumer?

为什么在Java 8中使用@FunctionalInterface批注

此Java方法调用中的歧义在哪里?

Java:为什么主方法中的整数与方法结合

Java:通用方法重载歧义

Java 中的类型转换歧义

为什么Java中的Object类包含受保护的方法?

为什么我们需要Java中的默认方法?

为什么ArrayList中的排序方法比阵列在Java快?

为什么Java 9中不推荐使用finalize()方法?

为什么它的声明之前在Java中可用的方法?