Annotations are used as "machine-readable metadata" - they describe the fields, methods and classes they label in a way that the compiler and runtime can parse, and possibly even understand. If you are familiar with .NET's attributes, you'll find that Java annotations are used similarly.
For example, the TileNetworkData
annotation defined in your example is itself decorated with an annotation Retention(RetentionPolicy.RUNTIME)
. This tells the compiler to embed the TileNetworkData annotation into the bytecode for the fields it annotates. The same annotation also tells the Java runtime that, when it loads classes with TileNetworkData-annotated fields, it should retain the TileNetworkData annotation for runtime reflection.
Now, your code can reflect over fields of an object to find the TileNetworkData annotations and do something with fields so annotated:
// I haven't even compiled this code, and even if it works, it's still insane.
// (others who know annotations better should feel free to edit or replace)
public void copyTileNetworkDataToCache (Object data, Cache<?> cache) {
for (Field f : data.getClass().getFields()) {
if (f.isAnnotationPresent(TileNetworkData.class)) {
cache.save(f.get(data));
}
}
}
You can even write code that teaches the Java compiler how to interpret your annotations at compile time, using the apt
front end in JDK 5 and javac
switches in JDK 6 and later. To make up another lame example, accessing the tile network might take so long that you want to avoid using data from it whenever possible. Hence, you might want to make a list of all classes that include TileNetworkData-annotated fields, so you can review them all and possibly rewrite the ones that don't absolutely need to access the tile network. To do this, you might write an annotation processor that prints out all matching classes, then point apt
at the processor when you compile.