While the three annotation types you've seen are useful, they hardly cover all the types of annotations you may want to make on your source code. In fact, you may get so into annotations that you want to define some of your own. Fortunately, Tiger lets you do this with the @interface keyword, along with a few other oddball syntactical constructs new to the language.
Annotation types are, at their most basic level, Java interfaces. As such, they look similar to a normal Java interface definition, but you use the @interface keyword instead of interface, which tells the compiler that you're writing an annotation type instead of a normal interface. Example 6-4 is a very simple marker interface.
package com.oreilly.tiger.ch06; /** * Marker annotation to indicate that a method or class * is still in progress. */ public @interface InProgress { }
You can use this on any method or class you like:
@com.oreilly.tiger.ch06.InProgress public void calculateInterest(float amount, float rate) { // Need to finish this method later }
NOTE
In this example, you don't need to prefix "InProgress" with its package, but it illustrates that these are used just like other Java classes.
You can define an annotation type with a member nearly as easily, as Example 6-5 illustrates.
package com.oreilly.tiger.ch06; /** * Annotation type to indicate a task still needs to * be completed. */ public @interface TODO { String value( ); }
NOTE
Oddly enough, the Java folks didn't go with the tried-and-true JavaBeans conventions, with methods like setXXX( ) and getXXX( ).
The declaration of the member is simple enough, but the parenthesis at the end probably looks a little oddthat's because it's not just a member declaration, but also a method declaration. You're actually defining a method called value( ), and the compiler then automatically creates a member variable with the same name. Along the same lines, since annotation types function like interfaces, the methods are all implicitly abstract, and have no bodies.
The variable name value is used, which lets source code that references this type use the shorthand notation @TODO(stringValue). This is a nice feature, and one you should strive to allow for. You see all of this in play in the following:
@com.oreilly.tiger.ch06.InProgress @TODO("Figure out the amount of interest per month") public void calculateInterest(float amount, float rate) { // Need to finish this method later }
Adding an extra member (or two) is equally simple, as Example 6-6 demonstrates.
NOTE
This is really an amped-up version of "TODO", shown in Example 6-5.
package com.oreilly.tiger.ch06; public @interface GroupTODO { public enum Severity { CRITICAL, IMPORTANT, TRIVIAL, DOCUMENTATION }; Severity severity( ) default Severity.IMPORTANT; String item( ); String assignedTo( ); }
Here, an enumerated type is added to spice up the mix, and then used by the severity member. item still holds the item that needs to be handled, and assignedTo provides the person the TODO item is assigned to:
Chapter 3 covers enumerated types.
@com.oreilly.tiger.ch06.InProgress @GroupTODO( severity=GroupTODO.Severity.CRITICAL, item="Figure out the amount of interest per month", assignedTo="Brett McLaughlin" ) public void calculateInterest(float amount, float rate) { // Need to finish this method later }
As a final note, you can set member values to defaults, although the syntax looks more than a little odd; Example 6-7 is an updated version of Example 6-6.
package com.oreilly.tiger.ch06; import java.util.Date; public @interface GroupTODO { public enum Severity { CRITICAL, IMPORTANT, TRIVIAL, DOCUMENTATION }; Severity severity( ) default Severity.IMPORTANT; String item( ); String assignedTo( ); String dateAssigned( ); }
This is probably even stranger for me to type than the new generics syntax, so it may take some time to get used to. Still, it's nice to be able to set these defaults, even if it is a little syntactically strange.
...extending other interfaces, or even annotation types? You can't. The @interface keyword implicitly indicates an extension of java.lang.annotation.Annotationand you can't compile an annotation type that explicitly tries to extend anything else. However, you can extend and implement annotation types, although these extensions and implementations are not treated as annotation types.