为什么 eclipse java 编译器 (ecj) 不能编译它?
Why can't the eclipse java compiler (ecj) compile this?
我有以下代码:
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);
}
}
此代码在使用 javac 1.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;
}
}
这是 ecj 中的一个错误,最近也被报告为 Bug 535969。
简而言之:为了避免技术难题,编译器在类型推断期间删除了匿名 class,用它的超级 class 替换它(在特定情况下,并非总是如此)。有了这个, mapToObj()
的结果被视为 Stream<Object>
,实际上应该使用匿名 class 。最初的评估,这种信息丢失是可以的(因为没有人可以提及匿名class)被这个问题中的例子证明是错误的。
编辑:错误已通过预先存在的报告修复Bug 477894
我有以下代码:
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);
}
}
此代码在使用 javac 1.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;
}
}
这是 ecj 中的一个错误,最近也被报告为 Bug 535969。
简而言之:为了避免技术难题,编译器在类型推断期间删除了匿名 class,用它的超级 class 替换它(在特定情况下,并非总是如此)。有了这个, mapToObj()
的结果被视为 Stream<Object>
,实际上应该使用匿名 class 。最初的评估,这种信息丢失是可以的(因为没有人可以提及匿名class)被这个问题中的例子证明是错误的。
编辑:错误已通过预先存在的报告修复Bug 477894