代码之家  ›  专栏  ›  技术社区  ›  Johannes Kuhn

为什么eclipse java编译器(ecj)不能编译这个?

  •  9
  • Johannes Kuhn  · 技术社区  · 8 年前

    我有以下代码:

    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;
        }    }
    
    1 回复  |  直到 7 年前
        1
  •  8
  •   Stephan Herrmann    8 年前

    这是ecj中的一个bug,最近也有报道称 Bug 535969 是的。

    简而言之:为了避免一个棘手的技术问题,编译器在类型推断期间删除匿名类,并用它的超级类替换它(在特定情况下,并不总是这样)。有了这个,结果 mapToObj() 被视为 Stream<Object> 其中确实应该使用匿名类。最初的评估是,这个信息丢失是可以的(因为没有人可以 提到 匿名类)被这个问题的例子证明是错误的。

    编辑 :已通过预先存在的报告修复错误 Bug 477894

    推荐文章