Survey
* Your assessment is very important for improving the work of artificial intelligence, which forms the content of this project
* Your assessment is very important for improving the work of artificial intelligence, which forms the content of this project
Java Programming II
Annotations and Reflection
Java Programming II
1
Contents
Annotations
Annotating Elements
Restricting Annotation Applicability
Retention Policies
The Class Class
Examples
Reflection
Annotation Queries
The Modifier Class
The Member classes
Java Programming II
2
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.
Java Programming II
3
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.
Java Programming II
4
Annotations
Documentation
Annotation Type
Using Annotation
Using Comments
/*-----------------------------Created: Jan 31 2005
Created By: James Gosling
Last Modified: Feb 9 2005
Last Modified By: Ken Arnold
Revision: 3
---------------------------------*/
public class Foo {
// …..
}
How to use Annotation
1. Define Annotation Type
2. Add Annotation using the
type
@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 for the
}
class Foo
Java Programming II
5
Annotation Types
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.
@interface Revision {
int major() default 1;
int minor() default 0;
}
@interface ClassInfo {
String created();
String createdBy();
String lastModified();
String lastModifiedBy();
Revision revision();
}
Initialization expression
@ClassInfo (
created = “Jan 31 2005”,
createdBy = “James Gosling”,
lastModified = “Feb 9 2005”,
lastModifiedBy = “Ken Arnold”,
revision = @Revision(major=3)
)
public class Foo {
// …
- Marker annotation: annotation type
}
which has zero elements
(ex) public @interface Preliminary { }
Java Programming II
6
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
}
}
Java Programming II
7
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”)
Java Programming II
8
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();
This will be
String lastModified();
applied to
type
String lastModifiedBy();
declaration
Revision revision();
}
Java Programming II
9
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)
Java Programming II
10
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
Java Programming II
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.
11
Working with Annotations (I)
A simple annotation-based test
framework
“RunTests.java”
import java.lang.reflect.*;
“Foo.java”
import java.lang.annotation.*;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@interface Test { }
public class RunTests {
public static void main(String[] args) throws
Exception {
int passed = 0, failed = 0;
for (Method m :
Class.forName(args[0]).getMethods()) {
Add “Test”
if (m.isAnnotationPresent(Test.class)) {
Annotation
public class Foo {
try {
@Test public static void m1() { }
m.invoke(null);
public static void m2() { }
passed++;
@Test public static void m3() {
} catch (Throwable ex) {
throw new RuntimeException("Boom");
System.out.printf("Test %s failed: %s %n",
}
m, ex.getCause());
public static void m4() { }
failed++;
@Test public static void m5() { }
}
public static void m6() { }
}
@Test public static void m7() {
}
throw new RuntimeException("Crash");
System.out.printf("Passed: %d, Failed %d%n",
}
passed, failed);
public static void m8() { }
}
}
}
Run:
% java RunTests Foo
Java Programming II
12
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<MyFoo> 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
Java Programming II
13
Documentation Comments
A Simple Example
/**
* An <code>Attr</code> object defines an attribute as a
* name/value pair, where the name is a <code>String</code>
* and the value an arbitray <code>Object</code>.
*
* @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;
/** 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;
}
/**
* Crates a new attribute with the given name and an
* initial value of <code>null</code>.
* @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 a string of the form <code>name=value</code>.
*/
public String toString() {
return name + "='" + value + "'";
}
}
Run:
% javadoc Attr.java
Java Programming II
14
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”.
Argument:
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;
}
Attr.class
out.print("class " + type.getSimpleName());
Class superclass = type.getSuperclass();
if (superclass != null)
out.println(" extends " +
superclass.getCanonicalName());
else out.println();
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)
Method[] methods = type.getDeclaredMethods();
for (Method m : methods)
if (Modifier.isPublic(m.getModifiers()))
out.println(" " + m);
}
}
The source code is at the /home/course/java2/code/AnnotationReflection/
Java Programming II
15
The Introspection Hierarchy
Type
ParameterizedType
GenericArrayType
TypeVariable<D>
AnnotatedElement
WildcardType
AccessibleObject
GenericDeclaration
Member
Class
Constructor
Method
Java Programming II
Field
Package
16
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<String>)
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.
class literal
import java.util.*;
public class TypeTokenTest {
public static void main(String[] args) {
Class<String> c1 = String.class;
System.out.println("Result1 = " + c1.getClass());
String str = "Hello";
// Class<String> c2 = str.getClass(); // error!
Class<? extends String> c2 = str.getClass();
System.out.println("Result2 = " + c2);
try {
Class<?> c3 =
Class.forName("java.lang.String"); //valid
Class<? Extends String> 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<? extends String> c3 =
Class.forName("java.lang.String").asSubclass(String.class);
Java Programming II
17
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");
Get type
token
// 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”
Java Programming II
18
Class Inspection
Run:
% java TypeDesc
java.util.HashMap
Result:
class java.util.HashMap<K, V>
implements java.util.Map<K, V>
implements java.lang.Cloneable
implements java.io.Serializable
extends java.util.AbstractMap<K,
V>
implements java.util.Map<K, V>
extends java.lang.Object
Examining the kind of
Class object
Ask whether have a toplevel 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.
Java Programming II
19