在带有jdk 1.7的Eclipse Kepler 4.2中,我在Eclipse中遇到以下错误:
The method or(capture#2-of ?) in the type Optional<capture#2-of ?> is not applicable for the arguments (Object)
虽然它在运行mvn compile
时成功编译。
类看起来如下:
package testit;
import java.util.Map;
import java.util.Map.Entry;
import com.google.common.base.Optional;
public class Test {
private static final Object NO_VALUE = new Object();
public void method(Map<String, ?> map) {
for (Entry<String, ?> entry : map.entrySet()) {
Optional.fromNullable(entry.getValue()).or(NO_VALUE);
// ^^ error here
}
}
}
的pom.xml:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>my.test</groupId>
<artifactId>testit</artifactId>
<version>0.0.1-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>13.0.1</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<source>1.7</source>
<target>1.7</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
类似的代码在生产中运行很长一段时间没有错误(在这个领域)。它在Maven,Jenkins,Intelij中编译,但在Eclipse中不编译。问题是为什么它不能在Eclipse中编译?
答案 0 :(得分:6)
经过Eclipse团队的深入分析(非常感谢!)他们对这个问题的回答如下:
来自Eclipse Bugzilla的Stephan Herrmann:
此行不适用于以下原因:
类型推断首先解析此表达式:
Optional.fromNullable(entry.getValue())
在此表达式中,可以按上述方式键入所有元素:
条目:条目entry.getValue:
capture#2-of ? fromNullable(..) : (capture#2-of ?) ->
Optional<capture#2-of ?>
简而言之:T被推断为&#34;
capture#2-of ?
&#34;。推理成功。只有在所有这些决定之后,才能解决问题 检查.or(..)方法调用。没有理由填写未推断的 使用&#34; Object&#34;。
推理变量使用Optional类型的接收器,我们有这三个 过度的&#34;或&#34;:
可选或(可选)
capture#2-of ? or(Supplier<? extends capture#2-of ?> supplier)
capture#2-of ? or(capture#2-of ? defaultValue)
这些方法都不适用于Object类型的参数。 ecj任意选择第一种错误报告方法:
&#34;方法或类型中的(可选) 可选不适用于参数(对象)&#34;
ecj和javac之间的区别肯定是由 提到了javac bug:https://bugs.openjdk.java.net/browse/JDK-8016207
如该bug中所述,未来可能会更新JLS 采用当前javac行为的一部分。直到这样的规格更新 发布后,ecj唯一可靠的参考点是JLS。在 这个规范我认为没有理由改变ecj的行为 这方面。
顺便说一下,规范修正(不需要演员)是:
Optional.<Object>fromNullable(entry.getValue()).or(NO_VALUE);
现在这将是结论。
答案 1 :(得分:1)
你没有提出问题,所以我假设了一个问题:&#34;谁是对的,以及如何使代码有效?&#34;
我说Eclipse是对的。
fromNullable
的结果具有类型参数?
,即存在类型T
但我们不知道它。
Optional
返回的or
必须与调用它的Optional
具有相同的类型参数,这也意味着它采用相同的未知类型T
作为参数。但Object
可能与该类型兼容,也可能不兼容,因此失败是正确的。
为了解决这个问题,我认为以下更改应该有效:
Optional.fromNullable((Object)entry.getValue()).or(NO_VALUE);
强制转换将其他未知类型参数绑定到Object
,这显然与Object
的调用中的or
兼容。
答案 2 :(得分:1)
Eclipse编译器不是标准的javac 。它使用ECJ Compiler这绝对是Eclipse编译器中的一个错误,因为maven使用标准的javac来编译它的原因。