- 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/
以下代码创建了一个Collector,它产生了一个UnmodifiableSortedSet: package com.stackoverflow; import java.util.Collecti
我正在使用 ECJ(一种进化算法包),我想调用扩展类中的某些变量,但我不知道如何从问题类中获取它们。 正如您在下面的问题类中看到的,我希望能够在 NetworkGene 类中调用变量 x,但它不起作用
我对 Java 的类型推断有疑问。我使用的是 javac 1.8.0_121,以下代码可以使用 Eclipse ECJ 进行编译,但不能使用 javac import java.util.functi
EJC(Eclipse 的内部 Java 编译器)中有一个错误,我不想等待官方错误修复。有没有办法将现有的 Eclipse 安装(假设是 4.6)指向 4.7 beta 的 ECJ 版本? 我知道,我
使用遗传编程 ECJ 21 ,我正在寻找有关如何序列化 ec.Individual(在成功(?)进化之后)的建议。 诀窍是,然后我需要在稍后阶段反序列化这个 GP,然后执行它......最好在 ECJ
我有一个小问题,在 eclipse 中编译的某些 java 类与由独立 ecj(来自相同的源代码)编译的类略有不同。如何找到 eclipse 正在使用的 ecj 版本? (我假设这就是区别所在) 最佳
注意:这篇文章不是关于 eclipse 创建的用于 java 的 eclipse 编译器——只是为了确保不会造成混淆。 我正在尝试让 ecj 遗传学编程系统在 Windows 上的 eclipse k
我对 elipse.jdt.core 插件做了一些更改,以支持类似于 Java 的语言(MaxJ)。我所做的更改可以在这里找到: https://github.com/maxeler/eclipse.
我有以下代码: package test; import java.util.stream.IntStream; public class A { public static void mai
考虑以下 returnsNull函数并使用泛型类型调用它: public static List returnNull(Class clazz) { return null; } publi
我有以下类(class): import java.util.HashSet; import java.util.List; public class OverloadTest extends Ha
当编译一个 Client 时,它使用接口(interface) I 的某些实现(例如 O),I 的类文件code> 也必须出现在类路径中。奇怪的是,这只是 javac 的情况,因为 Eclipse 编
Eclipse 使用它自己的编译器 (ECJ) 来编译 Java 代码。调试使用 Eclipse 编译的程序更容易,因为可以立即应用简单的代码更改(通过热代码替换)。 另一方面,Maven 使用(默认
今天遇到这个问题,花了很长时间试图重现/弄清楚发生了什么。有人可以解释为什么会发生这种情况,或者这是类型删除/默认方法/lambda/多态性的错误吗?取消对默认方法的注释使其运行良好,但我希望它能按原
我正在运行 1 个生产者线程、1 个消费者线程问题,共享缓冲区和临时缓存(包含 1000 个元素)。 eclipse 执行 (ECJ) 使用 33% 的 CPU(1 个内核用于生产者,1 个用于消费者
尝试运行 hello world grails 应用程序。 我收到此错误: | Error Failed to resolve dependencies (Set log level to 'warn
在 JRE 1.7 中运行时,我从 ECJ(版本 4.2.1)编译器获得 NPE,而同一项目在 JRE 1.6 上可以正确编译。 CompilationProgress 监视器显示总共有 2493 个
尝试运行以下组合: Maven (3.6.1) OpenJDK 11 使用 module-info.java Fails with the following error message: [ERRO
您好 friend ,我是android studio上的新手,安装后我发现问题gradle构建失败,因为 错误:无法下载ecj.jar(org.eclipse.jdt.core.compiler:e
我有一个可以通过 eclipse(ECJ)很好地构建的项目但是 Oracle javac 无法构建它(某些原因,如链接the different of ecj and javac所示)。 我想从ecl
我是一名优秀的程序员,十分优秀!