Eclipse和javac之间的奇怪编译器差异

8
以下代码片段(摘自真实代码)可以在Eclipse中编译和运行。 package1/Outer.java:
package package1;

import package1.Outer.Mid.Inner;
import package2.Bar;

public class Outer {
    final Mid mid = new Mid();

    public Outer() {
        mid.setInner(new Inner() {
            @Override public void foo() {
                System.out.println("In Outer.foo()");
            }
        });
    }

    public static class Mid implements Bar {
        private Inner inner;

        public void setInner(Inner inner) {
            this.inner = inner;
        }

        public Inner getInner() {
            return this.inner;
        }

        @Override
        public void bar() {}

        interface Inner {
            void foo();
        }
    }

}

package2/Bar.java:

package package2;

public interface Bar {
    void bar();
}

然而,使用javac编译时会出现以下错误:
package1\Outer.java:31: cannot find symbol
symbol  : class Bar
location: class package1.Outer
        public static class Mid implements Bar {
                                           ^
package1\Outer.java:42: method does not override or implement a method from a supertype
                @Override
                ^
2 errors

现在,如果我改变导入语句的顺序,像这样:
import package2.Bar;
import package1.Outer.Mid.Inner;

如果导入语句的顺序不正确,代码在Eclipse和javac中都会编译失败。那么为什么要注意导入语句的顺序呢?

注意事项:

  • 我使用Java JDK 1.6.0_30和Java JDK 1.7.0_21进行了测试。如果此问题已得到修复,则最好知道。
  • 奇怪的是,即使Inner接口嵌套在Outer.java中,package1.Outer.Mid.Inner导入语句似乎也是必需的,但Eclipse和javac都需要它。
  • 我发现这个问题是在尝试运行具有类似结构的生产代码的Ant构建时发现的。一切在Eclipse中都很好构建,但Ant脚本却无法通过。

我不确定,但很可能是Eclipse给出的编译命令与手动输入的不同。也许顺序颠倒了。另外一个可能性是Java编译器的不同版本。 - Gene
3
你能否删除代码中多余的部分,只留下最少的代码仍然可以产生相同的奇怪结果? - arshajii
@Gene Eclipse有自己的编译器。 - user207421
1
@arshaji 我删去了大部分冗余代码,这样好一些吗? - Kevin K
1个回答

4
这似乎是一个错误,正如Oracle的错误数据库这里报告的那样。
根据JLS §7.5import语句的顺序不应该有影响。

@arshaji,更新后的链接确实看起来符合我的情况,找得好。至于JLS,我没有看到任何明确提到导入语句顺序无关紧要的说明...这是一种隐含的理解还是我只是瞎了眼? - Kevin K
@KevinK JLS没有明确说明顺序很重要的事实意味着它并不重要。 - arshajii

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接