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)
考虑以下类别:
public class Foo extends Exception implements CharSequence {
//...
}
该类同时Foo
实现Throwable
和CharSequence
。因此,如果E
将其设置为该实例,则Java编译器将不知道调用哪个方法。
Java7 可能没有问题的 原因 是泛型的实现较少。如果您不提供E
自己的信息(例如(Foo) bar()
),则Java会退回其基本版本E
为implements Exception
,E
因此仅被视为的实例Exception
。
在 Java8中 , 类型推断
得到了改进
,E
现在从调用的参数派生了的类型,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
方法。
简而言之: 编译器旨在“猜测”E
Java8中的内容,而在Java7中则选择了最保守的类型。
有人能告诉我这些方法模棱两可的原因吗?提前谢谢你。
问题内容: 默认方法是Java工具箱中一个不错的新工具。但是,我试图编写一个定义方法版本的接口。Java告诉我,这是禁止的,因为in中声明的方法可能无法编辑。为什么会这样呢? 我知道有一个“基类始终获胜”规则,因此默认情况下(pun;),方法的任何实现都会被该方法覆盖。但是,我认为没有理由为什么规范中的方法不应有例外。特别是因为它具有默认实现可能非常有用。 那么,Java设计者决定不允许方法覆盖方
问题内容: 今天就去旅行。我注意到我可以将结构文字传递给与指向结构的指针关联的方法,反之亦然。为什么允许这样做? 输出: 问题答案: 请参阅方法集: 一个类型可能具有与之关联的方法集(§接口类型,§Method声明)。接口类型的方法集是其接口。其他任何类型T的方法集都包含接收者类型T的所有方法。相应指针类型 T的方法集是接收者 T或T的所有方法的集合(也就是说,它还包含T)。进一步的规则适用于包含
默认方法是Java工具箱中一个很好的新工具。然而,我试图编写一个接口,定义方法的版本。Java告诉我这是禁止的,因为方法是在可能不是默认值。为什么会是这种情况? 我知道有“基类总是赢”的规则,所以默认情况下(双关语;),方法的任何实现都将被中的方法覆盖。但是,我看不出规范中的中的方法不应该有例外的原因。特别是对于来说,拥有一个默认实现可能非常有用。 那么,Java设计人员决定不允许方法重写中的方法
本文向大家介绍Java Varargs中的方法重载和歧义,包括了Java Varargs中的方法重载和歧义的使用技巧和注意事项,需要的朋友参考一下 在Java中使用变量参数时存在歧义。发生这种情况是因为两种方法绝对可以有效地被数据值调用。因此,编译器不知道该调用哪种方法。 示例 输出结果 名为Demo的类定义了一个名为“ my_fun”的函数,该函数采用可变数量的浮点值。使用“ for”循环将这些
问题内容: 我想做一个简单的循环,像这样: 但是,如果有type ,则此循环是无限的。如果可以的话。 如果没有检查类型,我怎么能打破这个循环? 问题答案: 是类型的,因此一旦达到最大值,再次递减将导致最大值。更改循环条件以进行检查: 在Go Playground上尝试一下。 或使用常数: 或使用表达式(运算符为按位补码运算符)应用于,将为您提供一个值,其中所有位均为1:的最大值。 尽管如果您看一下