- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我有以下类(class):
import java.util.HashSet;
import java.util.List;
public class OverloadTest<T> extends HashSet<List<T>> {
private static final long serialVersionUID = 1L;
public OverloadTest(OverloadTest<? extends T> other) {}
public OverloadTest(HashSet<? extends T> source) {}
private OverloadTest<Object> source;
public void notAmbigious() {
OverloadTest<Object> o1 = new OverloadTest<Object>(source);
}
public void ambigious() {
OverloadTest<Object> o2 = new OverloadTest<>(source);
}
}
这在 JDK 7 的 javac 和 eclipse(合规性设置为 1.7 或 1.8)下编译良好。但是,尝试在 JDK 8 的 javac 下编译时,出现以下错误:
[ERROR] src/main/java/OverloadTest.java:[18,35] reference to OverloadTest is ambiguous
[ERROR] both constructor <T>OverloadTest(OverloadTest<? extends T>) in OverloadTest and constructor <T>OverloadTest(java.util.HashSet<? extends T>) in OverloadTest match
请注意,此错误仅适用于 ambiguous()
方法中的构造函数调用,而不适用于 notAmbiguous()
方法中的构造函数调用。唯一的区别是 ambiguous()
依赖于菱形运算符。
我的问题是:JDK 8 下的 javac 是否正确标记了不明确的解决方案,或者 JDK 7 下的 javac 未能捕捉到歧义?根据答案,我需要提交 JDK 错误或 ecj 错误。
最佳答案
在调用中,当显式设置 T 调用构造函数时,没有歧义:
OverloadTest<Object> o1 = new OverloadTest<Object>(source);
因为 T 是在构造函数调用时定义的,所以 Object 通过 ?在编译时扩展对象检查就好了,没有问题。当 T 显式设置为 Object 时,两个构造函数的选择变为:
public OverloadTest(OverloadTest<Object> other) {}
public OverloadTest(HashSet<Object> source) {}
而且在这种情况下,编译器很容易选择第一个。在另一个示例中(使用菱形运算符)T 未明确设置,因此编译器首先尝试通过检查实际参数的类型来确定 T,而第一个选项不需要这样做。
如果更改第二个构造函数以正确反射(reflect)我想象的所需操作(因为 OverloadTest 是 T 列表的哈希集,那么应该可以传入 T 列表的哈希集),如下所示:
public OverloadTest(HashSet<List<? extends T>> source) {}
...那么歧义就解决了。但就目前而言,当您要求编译器解决该不明确的调用时,将会发生冲突。
编译器将看到菱形运算符,并将尝试根据传入的内容和各种构造函数的期望来解析 T。但是HashSet构造函数的写法会保证无论传入哪个类,两个构造函数都保持有效,因为删除后,T总是被Object替换。当 T 为 Object 时,HashSet 构造函数和 OverloadTest 构造函数具有类似的删除,因为 OverloadTest 是 HashSet 的有效实例。而且因为一个构造函数没有覆盖另一个(因为 OverloadTest
这只是因为使用 T 作为边界,您强制编译器进行类型检查。如果您只是将它设为 而不是 它会编译得很好。 Java 8 编译器对类型和删除比 Java 7 更严格,部分原因是 Java 8 中的许多新特性(如接口(interface)保护方法)要求它们对泛型更加迂腐。 Java 7 没有正确报告这些事情。
关于java - Java8 中的模棱两可的重载——ECJ 还是 javac 正确?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26222510/
我从一所大学获得了一些示例代码,导入了项目并尝试运行测试:方法 assertThat(Integer, Matcher) 对于 MyClass 类型是不明确的 每个 assertThat 都被标记为红
关于将 iOS 应用程序迁移到 Swift 3.0 的过程。这是我面临的一个问题。 先上相关代码: let calendar = NSCalendar.current, calendCompo = c
我刚开始研究 Java 8 Lambda 功能。我在 Java 7 中编写了这段代码,并尝试在 lamdas 中执行它。请注意,最后一行会产生编译错误,因为重载的函数不明确。我明白原因。如何使用 la
如何优先(告诉编译器)使用“函数接收引用”(#B)而不是“函数接收值”(#A)? #include using namespace std; class Heavy{/* ...... */}; /
我正在使用 Google Map API V3 显示车辆行驶路径及其路线方向。但是通过谷歌方向图标,很难找到方向。下图解释更多 我看到了每个图标,它是 source 我找到了图片路径,是 http:/
我是一名优秀的程序员,十分优秀!