| Sign In/My Account | View Cart |
Declarative Programming in Java
Pages: 1, 2, 3
Annotations that can be applied to the package element are referred to as package-level annotations. An annotation with ElementType.PACKAGE as one of its targets is a package-level annotation. Package-level annotations are placed in a package-info.java file. This file should contain only the package statement, preceded by annotations. When the compiler encounters package-info.java file, it will create a synthetic interface, package-name.package-info. The interface is called synthetic because it is introduced by the compiler and does not have a corresponding construct in the source code. This synthetic interface makes it possible to access package-level annotations at runtime. The javadoc utility will use the package-info.java file if it is present, instead of package.html, to generate documentation.
The package-info.java file will look like this:
/**
* documentation comments...
*/
@Annotation1(...)
package sample;
Note: The JDK 1.5 beta release compiler parses the package-info.java file, but does not emit a synthetic interface as stated in the specification.
It is important to know that certain restrictions are imposed on annotation declaration:
extends clause is permitted. (Annotation types automatically extend a new marker interface, java.lang.annotation.Annotation.)String, Class, enum types, annotation types, and arrays of the preceding types.throws clause is permitted.Not all annotations need to be stored in the class files. For example, the deprecated javadoc tag used to mark a program element as obsolete and inform the compiler to emit a warning is now available as the Deprecated annotation, which is a source-level annotation. To declare an annotation to be visible only at source level, use @Retention(RetentionPolicy.SOURCE). The compiler does not store source-level annotations in the class file. Source-level annotations are expected to be used by tools such as documentation generators (javadoc), compilers, and other tools that require/have access to source files.
We can use the Doclet API to access annotations from the source files. The com.sun.javadoc package provides several new interfaces, and methods have been added to existing interfaces to support annotations. I'll walk you through an example that shows you how to access annotations using doclets.
import com.sun.javadoc.*;
public class ListAnnotations {
public static boolean start(RootDoc root) {
ClassDoc[] classes = root.classes();
for (ClassDoc clsDoc : classes) {
processAClass(clsDoc);
}
return true;
}
static void processAClass(ClassDoc clsDoc) {
System.out.println("List of annotations in " +
clsDoc.name());
list(clsDoc.annotations());
}
static void list(AnnotationDesc[] annDescs) {
for (AnnotationDesc ad : annDescs) {
AnnotationTypeDoc at = ad.annotationType();
System.out.println("----------");
System.out.println("Annotation : " + at.name());
AnnotationDesc.MemberValuePair [] members =
ad.memberValues();
for(AnnotationDesc.MemberValuePair mvp : members) {
System.out.println("Member = " +
mvp.member().name() +
", Value = "+ mvp.value() + "");
}
}
}
}
A Java class with the method public static boolean start(com.sun.javadoc.RootDoc root) is a doclet. The doclet uses the interfaces from the com.sun.javadoc package to gain access to various elements of a class from the source file. To execute a doclet, we have to use the javadoc tool. javadoc will parse the source files and call the start method, which is the entry point for a doclet, similar to the main method in a Java program.
javac -source 1.5 -cp c:\jdk15\lib\tools.jar ListAnnotations.java
javadoc -source 1.5 -doclet ListAnnotations -sourcepath . UnitTest.java
Loading source file UnitTest.java...
Constructing Javadoc information...
List of annotations in UnitTest
----------
Annotation : Retention
Member = value, Value = RUNTIME
----------
Annotation : Target
Member = value, Value = METHOD
We already saw two kinds of annotations: runtime and source. There is yet another kind of annotation: class. This is the default when the Retention meta-annotation is not present or it is present with a value RetentionPolicy.CLASS; the compiler stores annotations in the class files but the VM may not load them at runtime, so they may not be available for reflective access.
Microsoft's .NET CLR supports a feature called attributes, which is similar to annotations in Java. Let us see the similarities and differences between attributes and annotations.
| .NET Attributes | Java Annotations |
|---|---|
Attributes are classes that should extend the System.Attribute class. |
Annotations are interfaces that automatically extend the java.lang.annotation.Annotation interface. |
Types of an attribute parameter must be primitive types, object, System.Type, enum types, or arrays of the preceding types. |
Method return types are restricted to primitive types, String, Class, enum
types, annotation types, and arrays of the preceding types. |
Attribute parameters can be named or positional. Named ("name=value") parameters can be in any order. |
Supports only named ("name=value") parameters and can be in any order. Single member annotations follow the naming convention for the member type as value; can use shorthand. |
| Attributes can be applied to assembly, class, constructor, delegate, enum, event, field, interface, method, module, parameter, property, return value, and struct. | Annotations can be applied to annotation, class, constructor, enum, field (includes enum constants), interface, local variable, method, parameter, and package. |
| A declaration can have multiple attributes for the same attribute type. | A declaration cannot have multiple annotations for the same annotation type. |
| Attributes are always stored in the assembly and available at runtime. | Annotations marked with @Target(RetentionPolicy. SOURCE) meta-annotation (referred to as source-level annotations) are not stored in the class files and will not be available at runtime. |
| All attributes can be accessed at runtime using reflective APIs. | Annotations marked with @Target(RetentionPolicy.RUNTIME) meta-annotation (referred to as runtime annotations) can be accessed at runtime through reflective APIs. |
| System.CodeDOM APIs for working with attributes in source files. | Doclet API provides limited support for working with annotations at source files. |
| .NET provides standard attributes for security, transactions, language interoperability, COM integration, COM+ hosting, marshalling, serialization, components and controls, assemblies and packaging, threading, XML and web services. | Several new JSRs are in progress to define standard annotations for web services and others. |
| Context attributes provide an interception mechanism that can preprocess and postprocess class instantiation and method calls. | N/A |
For developers familiar with .NET attributes, the JDK 1.5 implementation of annotations may appear to be a limitation, but it is not. Java annotations can be used to define design-time information, such as documentation or instructions to the compiler; runtime information, such as tagging a method as a unit test; or behavioral characteristics, such as whether a member is participating in a transaction or not, similar to how attributes are used in .NET applications. Although there is no standard interception mechanism like .NET's context attributes in Java yet, AOP frameworks such as AspectJ and JBossAOP provide call interception mechanisms, and these frameworks may be reimplemented to take advantage of annotations.
In older versions of Java, javadoc custom tags are used as annotations. Many popular open source design-time tools, such as XDoclet, EJBGen, and others, generate code based on javadoc tags form the source files. Open source projects like Jakarta Commons Attributes and Attrib4j use javadoc tags to associate custom metadata and make it available at runtime. In both Commons Attributes and Attrib4j, attributes are classes more like .NET attributes, whereas JDK 1.5 treats them as interfaces. For those who can't start using JDK 1.5 as soon as the production release of Tiger is available, it's worthwhile to take a look at Retroweaver. Retroweaver transforms JDK 1.5 classes into classes that can run on older VMs; this way, you can start using JDK 1.5 features with an older version of the JRE.
Every new release of Java has introduced new features, but few warrant a new way of thinking to realize their full potential. Using annotations effectively to simplify programming in Java requires a shift in our thought processes. Even though we use declarative programming languages such as SQL and XSLT most frequently, it may take some time for us to understand how to use declarative and imperative programming together.
Here are a few things you could do with annotations to simplify or empower your programming:
Once JSRs like JSR-181: Web Services Metadata for the Java Platform and others are implemented, we will be able to appreciate the productivity gained by using annotations.
In the near future, we will see a number of existing frameworks being reimplemented using annotations, generics and other new features available in JDK 1.5, codenamed Tiger. So get ready to meet the Tiger.
Narayanan Jayaratchagan is a Sun Certified J2EE Architect with more than six years of experience with Java and Microsoft Technologies.
Return to ONJava.com.
Showing messages 1 through 3 of 3.
Deprecated annotation have a retention policy of CLASS instead of SOURCE? If not, how the compiler will warn about deprecated elements when you compiling your code againt raw .class files?
Class file format already has a way to mark elements with deprecated
attribute. You may want to check
href="http://java.sun.com/docs/books/vmspec/2nd-edition/html/ClassFile.doc.html#78232">VM
Spec for more information on the deprecated attribute.
The Deprecated annotation is intended to be used by the compiler which
has access to the source code so its marked as a source level
annotation. The compiler generates the class file with the deprecated attribute
as mentioned above.
Even the JSR 175 specification says that the deprecation facility was
implemented in an ad hoc fashion using documentation comments, but could
have been implemented atop a program annotation facility, had one
existed at the time the deprecation facility was designed.
Hope this answers your question.
Class file format already has a way to mark elements with deprecated attribute. You may want to check VM Spec for more information on the deprecated attribute.
The Deprecated annotation is intended to be used by the compiler which has access to the source code so its marked as a source level annotation. The compiler generates the class file with the deprecated attribute as mentioned above.
Even the JSR 175 specification says that the deprecation facility was implemented in an ad hoc fashion using documentation comments, but could have been implemented atop a program annotation facility, had one existed at the time the deprecation facility was designed.
Hope this answers your question.