Eclipse 在 javac 和 IDEA 成功的地方失败
Eclipse fails where javac and IDEA succeed
考虑以下独立示例:
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
.
我有 14.1 版的 IntelliJ IDEA。在 Project Structure/SDKs
下,我只有指向 C:\Program Files\Java\jdk1.8.0_40
的“1.8”,在 Project Structure/Modules
下,特定模块配置为使用 "Project SDK (1.8)",它列为 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
下,它也被检查为 "Compatible JRE" of "JavaSE-1.8"。在我的 Project/Properties/Java Build Path/Libraries
中 "JRE System Library" 是 [jdk1.8.0_40]
.
更多值得注意的事实:
不只是我;它在同事的(非常相似的)eclipse 安装上也失败了。
IntelliJ IDEA 说 lambda 表达式 a -> a.annotationType()
可以用方法引用替换,但如果要求这样做,它会 不是转换成Annotation::annotationType
;相反,它将其转换为 (Converter<Class<? extends Annotation>, Annotation>) Annotation:: annotationType
.
所以,问题:
是什么导致了 Eclipse 与其他 Eclipse 之间的这些差异,如何消除这些差异?
(显然,目标是消除不幸的过于频繁发生的情况,即一个开发人员提交的代码无法在另一个开发人员的 IDE 上编译。)
编辑:当我最初发布这个问题时,我认为 IDEA 使用 Eclipse
编译器也编译得很好,但我错了。原来是可以通过选择Eclipse
编译器让IDEA编译上面的代码失败。不过,问题是为什么 eclipse 和 javac 之间存在差异。
"why is there a discrepancy" 的答案很简单,但可能不是很令人满意:因为编译器有错误,而且对非常复杂的语言规范的解释持开放态度。确定它是 javac 还是 Eclipse 中的错误是一项艰巨的任务;我已经看到这种差异最终以两种方式声明,有时作为 Eclipse 编译器错误,有时作为 javac 错误。这种决定,尤其是当它涉及泛型和新的语言特性(如 lambda)时,可能会变得非常乏味和神秘。例如,看看这个结果是 javac 错误但确实在 Eclipse 的编译器中发现了一个相关问题:https://bugs.eclipse.org/bugs/show_bug.cgi?id=456459
最好的办法是像我一样将它报告为 Eclipse 错误,看看 Eclipse 编译器团队 can/will 是否能找到它。
考虑以下独立示例:
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
.
我有 14.1 版的 IntelliJ IDEA。在 Project Structure/SDKs
下,我只有指向 C:\Program Files\Java\jdk1.8.0_40
的“1.8”,在 Project Structure/Modules
下,特定模块配置为使用 "Project SDK (1.8)",它列为 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
下,它也被检查为 "Compatible JRE" of "JavaSE-1.8"。在我的 Project/Properties/Java Build Path/Libraries
中 "JRE System Library" 是 [jdk1.8.0_40]
.
更多值得注意的事实:
不只是我;它在同事的(非常相似的)eclipse 安装上也失败了。
IntelliJ IDEA 说 lambda 表达式
a -> a.annotationType()
可以用方法引用替换,但如果要求这样做,它会 不是转换成Annotation::annotationType
;相反,它将其转换为(Converter<Class<? extends Annotation>, Annotation>) Annotation:: annotationType
.
所以,问题:
是什么导致了 Eclipse 与其他 Eclipse 之间的这些差异,如何消除这些差异?
(显然,目标是消除不幸的过于频繁发生的情况,即一个开发人员提交的代码无法在另一个开发人员的 IDE 上编译。)
编辑:当我最初发布这个问题时,我认为 IDEA 使用 Eclipse
编译器也编译得很好,但我错了。原来是可以通过选择Eclipse
编译器让IDEA编译上面的代码失败。不过,问题是为什么 eclipse 和 javac 之间存在差异。
"why is there a discrepancy" 的答案很简单,但可能不是很令人满意:因为编译器有错误,而且对非常复杂的语言规范的解释持开放态度。确定它是 javac 还是 Eclipse 中的错误是一项艰巨的任务;我已经看到这种差异最终以两种方式声明,有时作为 Eclipse 编译器错误,有时作为 javac 错误。这种决定,尤其是当它涉及泛型和新的语言特性(如 lambda)时,可能会变得非常乏味和神秘。例如,看看这个结果是 javac 错误但确实在 Eclipse 的编译器中发现了一个相关问题:https://bugs.eclipse.org/bugs/show_bug.cgi?id=456459
最好的办法是像我一样将它报告为 Eclipse 错误,看看 Eclipse 编译器团队 can/will 是否能找到它。