Question

Can someone explain why this compiles in JDK 1.6, but not in JDK 1.7 from which I get the error message:

java: Example is not abstract and does not override abstract method compareTo(java.lang.Object) in java.lang.Comparable?

import java.util.concurrent.*;

public class Example implements ScheduledFuture
{
    @Override public long getDelay(TimeUnit unit){ return 0; }
    @Override public int compareTo(Delayed o) { return 0; }
    @Override public boolean cancel(boolean mayInterruptIfRunning) { return false; }
    @Override public boolean isCancelled() { return false; }
    @Override public boolean isDone() { return false; }
    @Override public Object get() throws InterruptedException, ExecutionException {  return null; }
    @Override public Object get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException { return null; }
}

For your information, the methods in this class are generated by IntelliJ after writing just the class declaration.

The error message indicates that the compiler requires that the class declare a compareTo method that takes an Object typed parameter and this class takes a Delayed. However, the ScheduledFuture interface is defined as extending Delayed which in turn extends Comparable<Delayed> so to me everything seems to be in order.

If I just change the declaration to

private class Example implements ScheduledFuture<Object>

it compiles.

I am guessing it has to do with type erasure somehow but I can't really explain it to satisfy myself.

Was it helpful?

Solution

I don't really know why the behaviour changes between Java 6 and Java 7 (have you verified that with other compilers? javac vs. Eclipse compiler vs. whatever IDEA uses?).

But I can tell you why compareTo(Delayed) does not implement compareTo(Object) when you extend ScheduledFuture:

By using ScheduledFuture, you're using a raw type, which means that all occurances of generics are pretty much ignored in your class. That means that you're now implementing Comparable (and no longer Comparable<Delayed>, which in turn means that you need to implement compareTo(Object) (the erasure of Comparable<Delayed>.compareTo()), but you implement compareTo(Delayed).

Remember: Raw types are meant only for backwards compatibility. Avoid them in new code at all costs, they do nasty things!

When you change your extends clause to ScheduledFuture<Object> you "opt-in" to the generics system and the compiler finally realizes (i.e. "is allowed to realize") that your compareTo(Delayed) is in fact the proper implementation of the Comparable<Delayed> interface.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top