- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
我有这个类,它是我在从 Java 6 移植到 Java 8 的项目中找到的一些代码的简化:
public class Unification {
final class Box<A> {}
final class MyMap<A, B extends Box<? extends A>> {}
MyMap<?, ?> getMap() {
return new MyMap<Object, Box<Object>>();
}
<A, B extends Box<? extends A>> void setMap(final MyMap<A, B> m) {}
void compileError() {
setMap(getMap());
}
}
这是一个非常小的例子,只是为了展示问题,实际的代码更有意义。这个问题似乎很普遍,因此是抽象的例子。核心问题如下:出于某种原因,javac 不想接受类型为 MyMap<?, ?>
的表达式。作为 setMap()
的参数方法,尽管根据我的理解,这应该是类型良好的。
使用 javac 6 编译代码没有错误,但是当我使用 javac 8 时,我收到这条模糊的错误消息:
C:\System9\KWS_sparse\sourcesNG\Domain\src\uz\Unification.java (21:9) error: method setMap in class Unification cannot be applied to given types;
required: Unification.MyMap<A,B>
found: Unification.MyMap<CAP#1,CAP#2>
reason: inference variable A has incompatible bounds
equality constraints: CAP#1
lower bounds: Object
where A,B are type-variables:
A extends Object declared in method <A,B>setMap(Unification.MyMap<A,B>)
B extends Unification.Box<? extends A> declared in method <A,B>setMap(Unification.MyMap<A,B>)
where CAP#1,CAP#2 are fresh type-variables:
CAP#1 extends Object from capture of ?
CAP#2 extends Unification.Box<? extends CAP#1> from capture of ?
报错信息好像是MyMap
的第一个类型参数找不到统一, javac 找不到与两者统一的类型 CAP#1
, 它表示 setMap()
的实际参数中的第一个通配符参数, 和 A
,即setMap()
的形参对应的类型参数.尽管在我看来 A
和 CAP#1
应该是完全统一的,那么它们都将代表通过删除 getMap()
签名中的实际类型引入的存在类型.
谁能发现这里出了什么问题? javac 6 是否错误地接受了这段代码?此外,是否有一种不太侵入性(并且与 javac 6 兼容)的方法来引导 javac 8 实现正确的统一?
编辑:我尝试了从 stackoverflow.com/questions/23063474/引入变量的建议,但这似乎没有帮助,我得到了同样的编译错误。
EDIT2:阐明了示例代码的“意图”。
EDIT3:改名为Map
至 MyMap
, 显然定义自定义 Map
太困惑了类型。
最佳答案
这个问题可以通过引入一个中间方法来规避,从而强制 javac 分两个阶段进行类型推断。第一种方法只接受一个类型参数,将第二个类型参数保留为通配符。 Javac 能够正确地推断出此方法的单一类型参数。然后,第二个也是原始方法能够从提供的参数中正确推断出第二个类型参数。
public class Unification {
final class Box<A> {}
final class MyMap<A, B extends Box<? extends A>> {}
MyMap<?, ?> getMap() {
return new MyMap<Object, Box<Object>>();
}
<A> void setMap(final MyMap<A, ?> m) {
doSetMap(m);
}
<A, B extends Box<? extends A>> void doSetMap(final MyMap<A, B> m) {}
void worksFineNow() {
setMap(getMap());
}
}
关于使用 javac 8 编译代码时出现 Java 类型错误,但在 javac 6 中运行良好,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40088515/
我的问题是关于基本的java命令之一“javac”。我的桌面上有一个“.java”文件。我已经安装了 JDK 7 并将路径变量添加到环境变量中。这是“环境变量”的屏幕截图。 http://s13.po
我制作了我的 gitrepository 并提交了它。 插入了一个 java 文件并想编译它,但它给了我这个: Bernard@BERNARD-PC /c/users/bernard/desktop/
运行Maven时,得到以下输出: [WARNING] Unable to autodetect 'javac' path, using 'javac' from the environment. 我该
我有一个导入一些 servlet 库的类。当我从命令行编译它时它很好。 当我使用 ant compile 任务编译它时,它给出了在其路径中找不到 servlet 库的错误。 这是已知/常见的情况吗?
我试图在 maven-compiler-plugin 中指定另一个版本的 JDK .当-target和 -source参数设置为1.5,一切正常。但是当我尝试使用 1.6 JDK 时,maven 会报
我们的软件之前附带 OpenJDK JRE,但现在我们将附带 Oracle JRE。 之前我们使用 OpenJDK javac 编译器进行编译。我认为现在我们应该使用 Oracle javac 编译器
在大多数现代 IDE 中,您可以设置一个参数来确保 javac 获得足够的堆内存来进行编译。由于不值得在这里讨论的原因,我们暂时与 JBuilder 2005/2006 联系在一起,而且源代码的数量似
我在桌面上的 Notepad++ 中保存了一个名为“first.java”的文件。当我运行 cmd 命令“javac first.java”时,它给了我这个错误。 javac: file not fo
更新: See resolution here. 感谢大家的帮助! 我在尝试使用 Ant 编译项目时遇到错误,它声称“[javac] javac:无效目标版本:7”并导致构建失败。 我在 Mac OS
当我尝试在我的 gwt-maven Projekt 上进行 maven-install 时,我得到了这个错误: [ERROR] Failed to execute goal org.apache.ma
使用 maven 编译时出现编译错误。 [ERROR] COMPILATION ERROR : [INFO] ---------------------------------------------
我正在查看一些内部 javac sun 编译器 API 源代码,并在 Types 类中发现了这一点: public Boolean visitTypeVar(TypeVar var1, Type va
我正在尝试运行 java 应用程序,但出现以下错误, Unable to find a javac compiler; com.sun.tools.javac.Main is not on the c
我有这个类,它是我在从 Java 6 移植到 Java 8 的项目中找到的一些代码的简化: public class Unification { final class Box {}
首先,我要感谢你,并明确地说,我已经在这个问题上苦苦思索了好几天,并在其他类似线程中寻找解决方案,但没有成功。 我们的应用程序负责生成 java 类,其中一些可能在类名(因此文件名)中包含特殊字符,例
以下代码创建了一个Collector,它产生了一个UnmodifiableSortedSet: package com.stackoverflow; import java.util.Collecti
当我用 Maven 编译我的类时遇到问题。堆栈跟踪如下所示: [ERROR] Failure executing javac, but could not parse the error: [ERRO
这个问题在这里已经有了答案: Why Java compiler as distributed as executable and not as JVM bytecode? (1 个回答) 关闭 7
我有一些用 javac 1.8.0_92 编译的代码: public final class Either { // ... private final L l; privat
这个问题在这里已经有了答案: Lombok's access to jdk.compiler's internal packages incompatible with Java-16 (3 个回答)
我是一名优秀的程序员,十分优秀!