Java Reference
In-Depth Information
As an example of the benefits of a compile-time annotation, consider the common error
made when overriding: as shown in
Example 23-13
,
a small error in the method signature
can result it an overload when an override was intended.
Example 23-13. MyClass.java: Why annotations?
public class MyClass {
public boolean equals(MyClass object2) {
// compare, return boolean
}
The code will compile just fine on any release of Java, but it is incorrect. The standard con-
an equals method whose solitary argument is of type
java.lang.Object
. The preceding ver-
sion creates an accidental overload. Because the main use of
equals()
(and its buddy meth-
classes (see
Chapter 7
), this overloaded method will never get called, resulting both in dead
code and in incorrect operation of your class within Sets and Maps.
The solution is very simple: using the annotation
java.lang.Override
, as in
Example 23-14
,
informs the compiler that the annotated method is required to be overriding
a method inherited from a supertype (either a superclass or an interface). If not, the code will
not compile.
Example 23-14. MyClass.java: @Override Annotation
public class MyClass {
@Override
public boolean equals(MyClass object2) {
// compare, return boolean
}
This version of
equals()
, while still incorrect, will be flagged as erroneous at compile time,
potentially avoiding a lot of debugging time. This annotation, on your own classes, will help
both at the time you write new code and as you maintain your codebase; if a method is re-
moved from a superclass, all the subclasses that still attempt to override it
and
have the
@Override
annotation, will cause an error message, allowing you to remove a bunch of dead
code.
The second major use of annotations is to provide metatdata at runtime. For example, the
Java Persistence API (JPA, see
Easy Database Access with JPA and/or Hibernate
) uses its