Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java 7 but not Java 6: "is not abstract and does not override abstract method"

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.

like image 568
Thomas Larsson Avatar asked Jul 29 '13 10:07

Thomas Larsson


People also ask

What if we dont override the abstract method?

Extending an abstract class If you don't, a compile time error will be generated for each abstract method (that you don't override) saying “subclass_name is not abstract and does not override abstract method abstractmethod_name in classname”.

Can we override non-abstract method of abstract class in Java?

"Is it a good practice in Java to override a non-abstract method?" Yes.

Do we need to override abstract method in Java?

A subclass must override all abstract methods of an abstract class. However, if the subclass is declared abstract, it's not mandatory to override abstract methods.


1 Answers

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.

like image 180
Joachim Sauer Avatar answered Sep 20 '22 12:09

Joachim Sauer