考虑以下自包含样本:
package bloopers;
import java.lang.annotation.Annotation;
public final class Blooper5
{
interface Converter<T,F>
{
T convert( F from );
}
interface Identifier<T>
{
}
static class ConvertingIdentifier<F,T> implements Identifier<F>
{
ConvertingIdentifier( Converter<T,F> converter )
{
}
}
static final class AnnotationIdentifier
{
Identifier<Annotation> I1 = new ConvertingIdentifier<>(
a -> a.annotationType() );
Identifier<Annotation> I2 = new ConvertingIdentifier<>(
Annotation::annotationType ); //<-- ERROR
Identifier<Annotation> I3 = new ConvertingIdentifier<>(
(Converter<Class<? extends Annotation>,Annotation>)
Annotation::annotationType );
}
}
上面的代码在以下内容下编译得很好:
javac
来自命令行。IntelliJ IDEA
配置为使用javac
编译器。但它无法编译以下内容:
Eclipse
IntelliJ IDEA
配置为使用Eclipse
编译器。 Eclipse无法编译标有<-- ERROR
的行,并显示以下消息:
The constructor Blooper5.ConvertingIdentifier<Annotation,Class<capture#5-of ? extends Annotation>>(Blooper5.Converter<Class<? extends Annotation>,Annotation>) is undefined
不可否认,这段代码确实推动了编译器的泛型参数类型推理功能,但我仍然想知道差异是什么,无论多小。
我的方法有些暴露,以防有人设法看到我看不到的错误:
我用javac编译的命令是"c:\Program Files\Java\jdk1.8.0_40\bin\javac" Blooper5.java
。
我有IntelliJ IDEA的14.1版。在Project Structure/SDKs
下我只有&#34; 1.8&#34;指向C:\Program Files\Java\jdk1.8.0_40
且Project Structure/Modules
下的特定模块配置为使用&#34; Project SDK(1.8)&#34;列为1.8 (java version "1.8.0_40")
。
至于Eclipse,我正在使用Eclipse for RCP and RAP Developers - Version: Luna Release (4.4.0) - Build id: 20140612-0600
。在Preferences/Java/Installed JREs
下我只有jdk1.8.0_40,这是默认值。在Execution Environments
下,它也会被检查为&#34;兼容的JRE&#34; &#34; JavaSE-1.8&#34;。在我的Project/Properties/Java Build Path/Libraries
&#34; JRE系统库&#34;是[jdk1.8.0_40]
。
更值得注意的事实:
这不仅仅是我;它也失败了同事的(非常相似的)eclipse安装。
IntelliJ IDEA表示lambda表达式a -> a.annotationType()
可以替换为方法引用,但如果要求这样做,则 不 将其转换为Annotation::annotationType
;相反,它会将其转换为(Converter<Class<? extends Annotation>, Annotation>) Annotation:: annotationType
。
所以,问题是:
导致Eclipse与其他人之间存在这些差异的原因是什么,以及如何消除这些差异?
(显然,目标是消除不幸发生的情况,即一个开发人员提交无法在另一个开发人员的IDE上编译的代码。)
编辑:当我最初发布这个问题时,我认为使用Eclipse
编译器的IDEA也编译得很好,但我错了。事实证明,通过选择Eclipse
编译器,IDEA可能无法编译上述代码。不过,问题是为什么eclipse和javac之间存在差异。
答案 0 :(得分:4)
&#34>答案为什么会出现差异&#34;很简单,但也许不是很令人满意:因为编译器有错误,而且对于非常复杂的语言规范的解释更加开放。确定它是否是javac或Eclipse中的错误是一项艰巨的任务;我已经看到这种差异最终被双重声明,有时候是Eclipse编译器错误,有时候是javac错误。这种决心,特别是涉及泛型和新语言特征(如lambdas)时,可能会变得相当乏味和神秘。例如,看看这个被证明是javac bug的那个,但确实发现了Eclipse编译器中的一个相关问题:https://bugs.eclipse.org/bugs/show_bug.cgi?id=456459
最好的办法是像我一样将它报告为Eclipse错误,看看Eclipse编译器团队是否可以/将跟踪它。