为什么可以';EclipseJava编译器(ecj)没有编译这个吗?
我有以下代码:为什么可以';EclipseJava编译器(ecj)没有编译这个吗?,java,javac,ecj,Java,Javac,Ecj,我有以下代码: package test; import java.util.stream.IntStream; public class A { public static void main(String[] args) { IntStream.range(0, 10).mapToObj(n -> new Object() { int i = n; }).mapToInt(o -> o.i).forEachOrd
package test;
import java.util.stream.IntStream;
public class A {
public static void main(String[] args) {
IntStream.range(0, 10).mapToObj(n -> new Object() {
int i = n;
}).mapToInt(o -> o.i).forEachOrdered(System.out::println);
}
}
当使用javac1.8.0_101编译时,此代码运行良好,并按预期生成数字0到9
但是当我在eclipse中使用此代码时,它告诉我在o.I
:
i cannot be resolved or is not a field
并在执行此操作时产生错误:
Exception in thread "main" java.lang.Error: Unresolved compilation problem:
i cannot be resolved or is not a field
at test.A.main(A.java:9)
为什么我需要使用javac来编译此代码?我该如何让eclipse表现出来 编辑: 我做了一些测试,只要不在lambda中创建实例,它就可以在ecj中工作:
package test;
import java.util.Optional;
import java.util.function.Supplier;
public class B {
public static void main(String[] args) {
// This works fine:
System.out.println(new Object() {
int j = 5;
}.j);
// This also
System.out.println(trace(new Object() {
int j = 5;
}).j);
// Also no problem
System.out.println(unwrapAndTrace(Optional.of(new Object() {
int j = 5;
})).j);
// Lambdas work:
System.out.println(((Supplier & Serializable) () -> new Object()).get());
// This doesn't work.
System.out.println(invokeAndTrace(() -> new Object() {
int j = 5;
}).j);
}
public static <T> T trace(T obj) {
System.out.println(obj);
return obj;
}
public static <T> T invokeAndTrace(Supplier<T> supplier) {
T result = supplier.get();
System.out.println(result);
return result;
}
public static <T> T unwrapAndTrace(Optional<T> optional) {
T result = optional.get();
System.out.println(result);
return result;
}
}
封装测试;
导入java.util.Optional;
导入java.util.function.Supplier;
公共B级{
公共静态void main(字符串[]args){
//这很好:
System.out.println(新对象(){
int j=5;
}(j);
//这也
System.out.println(跟踪(新对象(){
int j=5;
})(j);
//也没问题
System.out.println(unwapandtrace(可选)of(新对象(){
int j=5;
}))(j);
//兰博达斯作品:
System.out.println(((Supplier&Serializable)(->newobject()).get());
//这不管用。
System.out.println(invokeAndTrace(()->新对象(){
int j=5;
})(j);
}
公共静态T跟踪(T obj){
系统输出打印项次(obj);
返回obj;
}
公共静态T invokeAndTrace(供应商){
T result=supplier.get();
系统输出打印项次(结果);
返回结果;
}
公共静态T UnwapandTrace(可选){
T result=optional.get();
系统输出打印项次(结果);
返回结果;
}
}
这是ecj中的一个bug,最近也被报道为
简而言之:为了避免一个棘手的技术问题,编译器在类型推断过程中删除匿名类,用它的超类替换它(在特定情况下,并不总是这样)。这样,mapToObj()
的结果被视为Stream
,其中确实应该使用匿名类。最初的评估是,这种信息丢失是可以的(因为没有人可以提到匿名类),但这个问题中的示例证明这是错误的
编辑:该错误已通过预先存在的报告修复我知道,我可以使用
整数
,但这不是重点。而且i
是可见的-不是私有的,相同的包。但是如果你愿意,你当然可以把i
公开。没关系。当你创建一个新的Object()类时,变量i不是基本对象类的一部分。它不是一个类变量。创建一个名为B的新类,类变量i作为B类中的int。然后,您可以在传入时分配n。不知道为什么以前编译过,但是看起来基类对象中没有任何类变量可供分配。您正在创建的object实例似乎只有大括号范围内的int i。基本上int i是一个局部方法变量。eclipse的版本是什么??开普勒和prev-使用Java1.7,因此它不会编译。您需要Luna或最新的(Mars)Eclipse来编译lambdas,没有问题。如果我将o.I
更改为123
,Eclipse将对其进行编译。@SergeBreusov,请注意:虽然Luna确实引入了对Java 8的支持,但您提到的所有版本都不是2018年的最新版本。事实上,Oxygen.3a是最新发布的版本——直到下周光子将发布。编译器错误?好。。。我总是被告知“这不是编译器的错,这是你的错。编译器经过了战斗测试,很可能是你做错了什么”。是的,当然。我相信我问题的底部是一个很好的测试用例。顺便说一句,光子会修复它吗?它已经修复了,对光子来说太晚了,但别担心,下一个版本离发布只有3个月了。谢谢你的跟进。我期待着做这种事情(C#可以做一段时间——使用var
事情变得更疯狂)。