Much has been written about the new language features in J2SE 1.5, Tiger. Many, such as the introduction of enums, generics, and metadata, involve changing bytecode. These additions to the language require modifications to existing APIs. One of the APIs most radically affected by these changes is the Reflection API. Reflection has existed since JDK 1.1, and many frameworks, libraries, and utilities have been built upon it. This article examines the modifications to the Reflection API that are now available to the public as part of JDK 1.5 beta 1, and shows how you can take advantage of them in your code.
New Kids on the Hierarchy
A few interfaces and exceptions have been added to java.lang.reflect, as well as to java.lang. Some "old classes" -- such as Class, Method, Constructor, and others -- have been retrofitted to implement them. In this section we will look at these added interfaces.
Reflections on Metadata
The AnnotatedElement interface is implemented by any class that represents an element that may contain annotations (also known as metadata), as specified by JSR-175. The Class, Constructor, Field, Method, and Package each have been modified to implement AnnotatedElement. The interface specifies methods to retrieve all annotations, annotations by type, annotations declared only in a particular class (i.e., not including superclasses), and also a method to query whether or not a class contains an annotation of a specific type. The following code snippets demonstrate the use of these methods. Note that you must have some knowledge about how annotations work to fully understand this example.
First, create a custom annotation that we will later examine with reflection.
package net.java.reflection;import java.lang.annotation.Retention;import static java.lang.annotation.RetentionPolicy.*;@Retention(RUNTIME)public @interface SampleAnnotation { public String value();}
Next, create a class AnnotatedElementTest and mark it and an instance method aMethod() as being annotated with the SampleAnnotation class you just created:
@SampleAnnotation("AnnotatedElementTest") public class AnnotatedElementTest { @SampleAnnotation("aMethod") @Deprecated public void aMethod() { }//...}
You can detect and get a handle to the Class annotations by creating a Class object and invoking the methods is AnnotationPresent() and getAnnotations(). You can repeat the process for the annotated method. The getAnnotations() method is used to retrieve all of the annotations this method has that are retained until runtime. When you compile and run AnnotatedElementTest, you will notice that @Deprecated is not shown. That is because it's only part of the source code and it's not present, even in the class file. Here's the listing for AnnotatedElementTest.
package net.java.reflection;import java.lang.annotation.Annotation;import java.lang.reflect.Method;@SampleAnnotation("AnnotatedElementTest")public class AnnotatedElementTest { @SampleAnnotation("aMethod") @Deprecated public void aMethod() { } public static void main(String[] args) throws Exception { Class<AnnotatedElementTest> clazz = AnnotatedElementTest.class; System.out.println(clazz.isAnnotationPresent(SampleAnnotation.class)); System.out.println(clazz.getAnnotation(SampleAnnotation.class)); Method method = clazz.getMethod("aMethod"); for (Annotation a : method.getAnnotations()) { System.out.println(a); } }}





