为什么Eclipse能够编译这段Java代码,但Ant不能?

7

这段代码在Eclipse中编译顺利:

abstract class CollectionView implements Collection<Object> {

...
        public Object[] toArray(Object[] o) {
            if (fast) {
                return get(map).toArray(o);
            } else {
                synchronized (map) {
                    return get(map).toArray(o);
                }
            }
        }
...
}

    class KeySet extends CollectionView implements Set<Object> {

        protected Collection<Object> get(Map<Object, Object> map) {
            return map.keySet();
        }

        protected Object iteratorNext(Map.Entry entry) {
            return entry.getKey();
        }   
    }

但是在使用Ant编译时无法通过:

错误:KeySet不是抽象的,并且没有覆盖Set中的抽象方法toArray(T[])

我可以理解为什么在Eclipse中代码可以编译:因为KeySet已经从CollectionView继承了实现toArray(T[]) 方法的实现。

但是为什么使用Ant编译会失败呢?

    <javac srcdir="src" destdir="bin" debug="on"> 
        <compilerarg value="-Xlint:unchecked"/>
        <compilerarg value="-Xlint:deprecation"/>
    </javac>

封装类是否实现了 toArray() 方法? - Ted Hopp
1
@JSmith:你能为我们提供一个简短但完整的示例(SSCCE),以便我们可以重现您遇到的错误吗? - jlordo
3
在Eclipse中,您设置了哪个编译器兼容性级别(工作区首选项或项目属性->Java->编译器),使用了哪个JRE系统库以及调用了哪个javac? - nitind
添加@Override是否有任何影响? - Joop Eggen
1
你确定在Eclipse和Ant中使用的是相同的JDK版本吗?此外,众所周知,Eclipse编译器和JDK编译器并不总是对正确语法达成一致。 - user330315
显示剩余5条评论
2个回答

2

首先,我们应该注意实现的方法的确切签名是:

<T> T[] toArray(T[] a);

同时,javac和Eclipse都会警告您存在“类型安全”问题。如果您更改签名以符合预期的签名,javac就可以正常工作。

如果您在使用原始的Object类型的签名下添加了@override到方法toArray中,那么Eclipse和javac都会正确地将其视为Collection声明的方法的重写。因此,这个问题就不存在了。

不一致的是,我认为javac存在一个bug,即在任何子类实现中,javac都无法识别超级方法Object[] toArray(Object[] o)以实现<T> T[] toArray(T[] a)。如果对于抽象类它能够实现,那么每个子类也应该能够实现。

这不是javac第一次出现这样的问题。例如,请参见此线程。我已经搜索了Oracle bug数据库,但没有找到有关您发现的问题的任何报告。

然后有一个解决方法:在抽象类中使用期望的签名;或在子类中手动进行覆盖。

public Object[] toArray(Object[] o) {
    return super.toArray(o);
}

1

有几种情况下,eclipse可以编译通过而javac不能。如果你不介意的话,我知道三种使用eclipse编译器构建的方法。

  1. 打包eclipse预编译类(hacky,不推荐)

  2. 使用Ant的eclipse编译器适配器。当您指定build.compiler属性时,所有的javac任务都将受到影响。您可以将其设置为"org.eclipse.jdt.core.JDTCompilerAdapter"。请注意,您必须在ant构建classpath中包含此类(及其依赖项)。最简单的方法是将所需的jar添加到Ant安装的lib文件夹中。

  3. 使用maven进行构建时,请配置以下内容:

            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.1</version>
                <configuration>
                    <compilerId>eclipse</compilerId>
                    <compilerVersion>1.6</compilerVersion>
                    <source>1.6</source>
                    <target>1.6</target>
                    <optimize>true</optimize>
                </configuration>
                <dependencies>
                    <dependency>
                        <groupId>org.codehaus.plexus</groupId>
                        <artifactId>plexus-compiler-eclipse</artifactId>
                        <version>2.2</version>
                    </dependency>
                </dependencies>
            </plugin>
    
在pom.xml文件的构建部分的插件部分。

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