When
annotations were added to the language in release 1.5, several annotation types
were added to the libraries [JLS, 9.6.1]. For the typical programmer, the most
important of these is Override. This
annotation can be used only on method declarations, and it indicates that the
annotated method declaration overrides a declaration in a supertype. If you
consistently use this annotation, it will protect you from a large class of
nefarious bugs. Consider this program, in which the class Bigram represents a bigram, or ordered
pair of letters:
// Can you spot the bug?
public class Bigram {
private final char first;
private final char second;
public Bigram(char first, char second) {
this.first = first;
this.second = second;
}
public boolean equals(Bigram b) {
return b.first == first && b.second == second;
}
public int hashCode() {
return 31 * first + second;
}
public static void main(String[] args) {
Set<Bigram> s = new HashSet<Bigram>();
for (int i = 0; i < 10; i++)
for (char ch = 'a'; ch <= 'z'; ch++)
s.add(new Bigram(ch, ch));
System.out.println(s.size());
}
}
Clearly, the
author of the Bigram class intended
to override the equals method (Item 8)
and even remembered to override hashCode in tandem (Item
9). Unfortunately, our hapless programmer failed to override equals, overloading it instead (Item 41). To
override Object.equals, you must
define an equals method whose
parameter is of type Object.
Luckily, the
compiler can help you find this error, but only if you help the compiler by
telling it that you intend to override Object.equals. To do this,
annotate Bigram.equals with @Override, as shown below:
@Override public boolean equals(Bigram b) {
return b.first == first && b.second == second;
}
If you insert
this annotation and try to recompile the program, the compiler will generate an
error message like this:
Bigram.java:10: method does not override or implement a
method
from a supertype
@Override public boolean equals(Bigram b) {
^
You will
immediately realize what you did wrong, slap yourself on the forehead, and
replace the broken equals implementation
with a correct one (Item 8):
@Override public boolean equals(Object o)
{
if (!(o instanceof Bigram))
return false;
Bigram b = (Bigram) o;
return b.first == first && b.second == second;
}
Therefore, you
should use
the Override annotation on
every method declaration that you believe to override a superclass declaration. There is one
minor exception to this rule. If you are writing a class that is not labeled
abstract, and you believe that it overrides an abstract method, you needn’t
bother putting the Override annotation on
that method. In a class that is not declared abstract, the compiler will emit
an error message if you fail to override an abstract superclass method.
Modern IDEs
provide another reason to use the Override
annotation
consistently. Such IDEs have automated checks known as code inspections. If you enable the appropriate code
inspection, the IDE will generate a warning if you have a method that doesn’t
have an Override annotation but
does override a superclass method.
If you are
using release 1.6 or a later release, the Override
annotation
provides even more help in finding bugs. In release 1.6, it became legal to use
the Override annotation on
method declarations that override declarations from interfaces as well as
classes. In a concrete class that is declared to
implement an interface, you needn’t annotate methods that you believe to
override interface methods, because the compiler will emit an error message if
your class fails to implement every interface method. Again, you may choose to
include these annotations simply to draw attention to interface methods, but it
isn’t strictly necessary.
For example,
the Set interface adds no new methods to
the Collection interface, so
it should include Override annotations on
all of its method declarations, to ensure that it does not accidentally add any
new methods to the Collection interface.
In summary,
the compiler can protect you from a great many errors if you use the Override annotation on every method declaration that
you believe to override a supertype declaration, with one exception. In
concrete classes, you need not annotate methods that you believe to override
abstract method declarations (though it is not harmful to do so).
Reference: Effective Java 2nd Edition by Joshua Bloch