Presentation is loading. Please wait.

Presentation is loading. Please wait.

1 Java Programming II Annotations and Reflection.

Similar presentations


Presentation on theme: "1 Java Programming II Annotations and Reflection."— Presentation transcript:

1 1 Java Programming II Annotations and Reflection

2 2 Java Programming II Contents  Annotations  Annotating Elements  Restricting Annotation Applicability  Retention Policies  The Class Class  Examples  Reflection  Annotation Queries  The Modifier Class  The Member classes

3 3 Java Programming II Annotations  The source code for our program is usually accompanied by copious amounts of informal documentation that typically is contained within comments in the source code Many organizations have a standard preamble: copyright information, the programmers name, the date the class was created, etc. Other comments by external tools: version control in a source code management system, or deployment descriptors on how a class should be managed by an application server. Comments based annotation  A better way to document the many annotations: to annotate the program elements directly using annotation types  Another motivation: many APIs require a fair amount of boilerplate code. (For example, in order to write a JAX-RPC web service, you must provide a paired interface and implementation. ) This boilerplate could be generated automatically by a tool if the program were “decorated” with annotations indicating which methods were remotely accessible.

4 4 Java Programming II Annotations  Provide data about a program that is not part of the program itself.  Using annotation type to describe the form of the annotations.  Uses of Annotation Information for the compiler — Annotations can be used by the compiler to detect errors or suppress warnings. Compiler-time and deployment-time processing — Software tools can process annotation information to generate code, XML files, and so forth. Runtime processing — Some annotations are available to be examined at runtime.

5 5 Java Programming II Annotations /*------------------------------ Created: Jan 31 2005 Created By: James Gosling Last Modified: Feb 9 2005 Last Modified By: Ken Arnold Revision: 3 ---------------------------------*/ public class Foo { // ….. } @interface ClassInfo { String created(); String createdBy(); String lastModified(); String lastModifiedBy(); int revision(); } @ClassInfo( created = “Jan 31 2005”, createdBy = “James Gosling”, lastModified =“Feb 9 2005”, lastModifiedBy =“Ken Arnold”, revision =3 ) public class Foo { // class definition… } Annotation Type Documentation Using Comments Using Annotation Annotation for the class Foo How to use Annotation 1. Define Annotation Type 2. Add Annotation using the type

6 6 Java Programming II Annotation Types @interface Revision { int major() default 1; int minor() default 0; } @interface ClassInfo { String created(); String createdBy(); String lastModified(); String lastModifiedBy(); Revision revision(); } @ClassInfo ( created = “Jan 31 2005”, createdBy = “James Gosling”, lastModified = “Feb 9 2005”, lastModifiedBy = “Ken Arnold”, revision = @Revision(major=3) ) public class Foo { // … }  Constraint rules of the methods declared in an annotation type (elements of annotation type) The type of the element can only be a primitive type, String, enum, another annotation type, Class, or an array of the preceding types. Cannot declare any parameters. Cannot have a throws clause. Cannot define a type parameter, i.e cannot be a generic method. Initialization expression - Marker annotation: annotation type which has zero elements (ex) public @interface Preliminary { }

7 7 Java Programming II Annotation Used by Complier  @Deprecated—the @Deprecated annotation indicates that the marked element is deprecated and should no longer be used. When an element is deprecated, it should also be documented using the Javadoc @deprecated tag. // Javadoc comment follows /** * @deprecated * explanation of why it was deprecated */ @Deprecated static void deprecatedMethod() { } }  @Override—the @Override annotation informs the compiler that the element is meant to override an element declared in a superclass (overriding methods will be discussed in the the lesson titled "Interfaces and Inheritance").  @SuppressWarnings—the @SuppressWarnings annotation tells the compiler to suppress specific warnings that it would otherwise generate. In the example of the right site, a deprecated method is used and the compiler would normally generate a warning. In this case, however, the annotation causes the warning to be suppressed. @SuppressWarnings(deprecation) void useDeprecatedMethod() { objectOne.deprecatedMethod(); // deprecation warning suppressed }

8 8 Java Programming II Annotating Elements and Restricting Annotation Applicability  Marker annotation or all its elements have default values @Deprecated public void badMethod() {/* … */}  (an empty list of initializers) @Deprecated() public void badMethod() {/* … */}  Array initializer expression @interface BugsFixed { String[] bugIds(); }  @BugsFixed(bugIDs = {“1234”, “4567”}) or @BugsFixed(bugIDs = “4567”)  When has only a single element (naming of the element is value), it allows for additional shorthand: @inteface BugsFixed { String[] value(); }  @BugsFixed({“1234”,”4567”}) @BugsFixed(“4567”)

9 9 Java Programming II Retention Policies  Annotation can serve many different purposes and may be intended for different readers (programmers, or a development tool, compiler, some tool that may need to extract the annotations from a binary representation of a class, and to be inspected at runtime)  The Target annotation type Enum constant of ElementType : Represents the different kinds of program elements to which annotations can be applied.  ANNOTATION_TYPE : Annotation type declaration  CONSTRUCTOR : Constructor declaration  FIELD : Field declaration (includes enum constants)  LOCAL_VARIABLE : Local variable declaration  METHOD : Method declaration  PACKAGE : Package declaration  PARAMETER : Parameter declaration  TYPE : Class, interface (including annotation type), or enum declaration Example @Target (ElementType.TYPE) @interface ClassInfo { String created(); String createdBy(); String lastModified(); String lastModifiedBy(); Revision revision(); } This will be applied to type declaration

10 10 Java Programming II Retention Policies  Three Retention Policies Can be applied when the annotation can be accessed. (Used by @Retention type, Defined by the RetentionPolicy enum) SOURCE: Annotations exist only in the source file CLASS: preserved in the binary representation of the class, but not available at run time RUNTIME: must be available at runtime via the reflection mechanism  Example @Retention(RetentionPolicy.RUNTIME)

11 11 Java Programming II The “Class” class  The Class class defines these methods: getName – returns the (class) name getFields – returns all the public fields getMethods – returns all the public methods getPackage – returns the class’ package getSuperclass – returns the class’ superclass getConstructors – returns all the public constructors static Class forName(String className) - returns Class object Annotation[] getAnnotations() - returns all annotations present on this element.

12 12 Java Programming II Working with Annotations (I)  A simple annotation-based test framework “Foo.java” import java.lang.annotation.*; @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) @interface Test { } public class Foo { @Test public static void m1() { } public static void m2() { } @Test public static void m3() { throw new RuntimeException("Boom"); } public static void m4() { } @Test public static void m5() { } public static void m6() { } @Test public static void m7() { throw new RuntimeException("Crash"); } public static void m8() { } } “RunTests.java” import java.lang.reflect.*; public class RunTests { public static void main(String[] args) throws Exception { int passed = 0, failed = 0; for (Method m : Class.forName(args[0]).getMethods()) { if (m.isAnnotationPresent(Test.class)) { try { m.invoke(null); passed++; } catch (Throwable ex) { System.out.printf("Test %s failed: %s %n", m, ex.getCause()); failed++; } System.out.printf("Passed: %d, Failed %d%n", passed, failed); } Run: % java RunTests Foo Add “Test” Annotation

13 13 Java Programming II Working with Annotations (II)  BugsFixedExample: Using Class and getAnnotation method of the “ClassInfo” class “MyFoo.java” import java.lang.annotation.*; @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) @interface BugsFixed { String[] value(); } @BugsFixed( {"1234", "5678"} ) public class MyFoo { } “BugsFixedExample.java” public class BugsFixedExample { public static void main(String[] args) { Class cls = MyFoo.class; BugsFixed bugsFixed = (BugsFixed) cls.getAnnotation(BugsFixed.class); System.out.println(bugsFixed); String[] bugIds = bugsFixed.value(); for (String id : bugIds) System.out.println(id); } Run: % java BugsFixedExample

14 14 Java Programming II Documentation Comments  A Simple Example /** * An Attr object defines an attribute as a * name/value pair, where the name is a String * and the value an arbitray Object. * * @version 1.1 * @author Plago * @since 1.0 */ public class Attr { /** The attribute name. */ private final String name; /** The attribute value. */ private Object value = null; /** * Crates a new attribute with the given name and an * initial value of null. * @see Attr#Attr(String,Object) */ public Attr(String name) { this.name = name; } /** * Creates a new attribute with the given name and * inital value. * @see Attr#Attr(String) */ public Attr(String name, Object value) { this.name = name; this.value = value; } /** Returns this attribute's name. */ public String getName() { return name; } /** Returns this attribute's value. */ public Object getValue() { return value; } /** * Sets the value of this attribute. Changes the * value returned by calls to {@link #getValue}. * @param newValue The new value for the attribute. * @return The Original value. * @see #getValue() */ public Object setValue(Object newValue) { Object oldVal = value; value = newValue; return oldVal; } /** * Returns a string of the form name=value. */ public String toString() { return name + "='" + value + "'"; } Run: % javadoc Attr.java

15 15 Java Programming II Reflection  The reflection is to examine a type in detail. The reflection package : java.lang.reflect Reflection starts with a Class object  A simple example of a “type browser”. import java.lang.reflect.*; import static java.lang.System.out; import static java.lang.System.err; public class SimpleClassDesc { public static void main(String[] args) { Class type = null; try { type = Class.forName(args[0]); } catch(ClassNotFoundException e) { err.println(e); return; } out.print("class " + type.getSimpleName()); Class superclass = type.getSuperclass(); if (superclass != null) out.println(" extends " + superclass.getCanonicalName()); else out.println(); Method[] methods = type.getDeclaredMethods(); for (Method m : methods) if (Modifier.isPublic(m.getModifiers())) out.println(" " + m); } Run: % java SimpleClassDesc Attr Result: class Attr extends java.lang.Object public java.lang.String Attr.getName() public java.lang.String Attr.toString() public java.lang.Object Attr.getValue() public java.lang.Object Attr.setValue(java.lang.Object) The source code is at the /home/course/java2/code/AnnotationReflection/ Argument: Attr.class

16 16 Java Programming II The Introspection Hierarchy Class Type ParameterizedType GenericArrayType TypeVariable WildcardType AnnotatedElement GenericDeclaration Member ConstructorMethodFieldPackage AccessibleObject

17 17 Java Programming II Type Tokens  Type Token Each Class object for a reference type is of a parameterized type corresponding to the class it represents. (Ex: the type of String.class is Class ) A parameterized Class type is known as the type token for a given class The easiest way to obtain a type token is to use a class literal. import java.util.*; public class TypeTokenTest { public static void main(String[] args) { Class c1 = String.class; System.out.println("Result1 = " + c1.getClass()); String str = "Hello"; // Class c2 = str.getClass(); // error! Class c2 = str.getClass(); System.out.println("Result2 = " + c2); try { Class c3 = Class.forName("java.lang.String"); //valid Class c3 = Class.forName("java.lang.String"); //invalid System.out.println("Result3 = " + c3); } catch(ClassNotFoundException e) { System.err.println(e); return; } Exact type token How about this? Class c3 = Class.forName("java.lang.String").asSubclass(String.class); class literal

18 18 Java Programming II Class Inspection import java.lang.reflect.*; public class TypeDesc { public static void main(String[] args) { TypeDesc desc = new TypeDesc(); for (String name : args) { try { Class startClass = Class.forName(name); desc.printType(startClass, 0, basic); } catch (ClassNotFoundException e) { System.err.println(e); // report the error } // by default print on standard output private java.io.PrintStream out = System.out; // used in printType(U) for labeling type names private static String[] basic = {"class", "interface", "enum", "annotation"}, supercl = {"extends", "implements"}, iFace = {null, "extends"}; private void printType( Type type, int depth, String[] labels) { if (type == null) // stop recursion -- no supertype return; // turn the Type into a Class object Class cls = null; if (type instanceof Class ) { cls = (Class ) type; } else if (type instanceof ParameterizedType) { cls = (Class ) ((ParameterizedType)type).getRawType(); } else throw new Error("Unexpected non-class type"); // print this type for (int i = 0; i < depth; i++) out.print(" "); int kind = cls.isAnnotation() ? 3 : cls.isEnum() ? 2 : cls.isInterface() ? 1 : 0 ; out.print(labels[kind] + " "); out.print(cls.getCanonicalName()); // print generic type parameters if present TypeVariable [] params = cls.getTypeParameters(); if (params.length > 0) { out.print('<'); for(TypeVariable param : params) { out.print(param.getName()); out.print(", "); } out.println("\b\b>"); } else out.println(); // print out all interfaces this class implements Type[] interfaces = cls.getGenericInterfaces(); for (Type iface : interfaces) { printType(iface, depth + 1, cls.isInterface() ? iFace : supercl); } // recurse on the superclass printType(cls.getGenericSuperclass(), depth + 1, supercl); } // end of main } // end of clss The source is at the “/home/course/java2/code/ByTopics/AnnotationReflection/Reflection” Get type token

19 19 Java Programming II Class Inspection Run: % java TypeDesc java.util.HashMap Result: class java.util.HashMap implements java.util.Map implements java.lang.Cloneable implements java.io.Serializable extends java.util.AbstractMap implements java.util.Map extends java.lang.Object  Examining the kind of Class object  Ask whether have a top- level type or a nested type, and if nested, some information about which kind of nested type  Find out where a type fits in the type hierachy  Apply to a subset of those different kinds.


Download ppt "1 Java Programming II Annotations and Reflection."

Similar presentations


Ads by Google