how come Eclipse compiles this Java code but not Ant?

This compiles find using 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();
        }   
    }

but it fails to compile when using Ant:

error: KeySet is not abstract and does not override abstract method toArray(T[]) in Set

I can see why the code would compile using Eclipse: KeySet already inherits the implementation of the toArray(T[]) method from CollectionView.

But why does it fail when I compile using Ant?

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

There are several cases where eclipse compiles fine and javac doesn't. If you do not mind, there are three ways that I know to build using the eclipse compiler.

  • Package eclipse pre-compiled classes (hacky, NOT recommended)

  • Use the eclipse compiler adapter with Ant. When you specify the property build.compiler, all javac tasks henceforth will be affected on your Ant build. You can set it to "org.eclipse.jdt.core.JDTCompilerAdapter". Note that you will have to include this class (and classes it depends on) in your ant build classpath. The most straightforward way is to add the necessary jars to the lib folder of your Ant installation

  • When building with maven configure this

            <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>
    
  • in the plugins section of the build section of your pom.xml


    First we should note the exact signature of the method expected to be implemented is:

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

    And both javac and Eclipse do warn you about this 'Type safety' issue. And if you change the signature to be the expected one, javac is happy.

    If you put an @Override to the method toArray, even with the signature which use raw Object type, both Eclipse and javac correctly see it as an override of the method declared by Collection . So this issue is not there.

    The inconsistency, and I think the bug of javac , is that is any subclass implementation, javac doesn't recognize the super method Object[] toArray(Object[] o) to implement <T> T[] toArray(T[] a) . If it did for the abstract class, i should also do it for every subclass.

    It is not the first time javac has a bug about this. See this thread for instance. I have searched the Oracle bug database, I found nothing reported about what you have found.

    Then there are a work around: in the abstrcat class, use the expected signature; Or do the override 'manually` in the subclasss:

    public Object[] toArray(Object[] o) {
        return super.toArray(o);
    }
    
    链接地址: http://www.djcxy.com/p/14038.html

    上一篇: 如何减少来自VisualVM的堆使用影响?

    下一篇: Eclipse如何编译这个Java代码,但不是Ant?