8

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.

Raedwald
  • 46,613
  • 43
  • 151
  • 237
Thomas Larsson
  • 697
  • 1
  • 8
  • 17
  • 1
    I in your place would look up the javadoc for ScheduledFuture from 1.6 and 1.7 and check what has changed. – Ingo Jul 29 '13 at 10:44
  • It happened to me that Java 6 does not prevent raw type inheritance from parametrized classes while 7 does – fglez Dec 27 '13 at 19:17

1 Answers1

10

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.

Community
  • 1
  • 1
Joachim Sauer
  • 302,674
  • 57
  • 556
  • 614