static final variables can be optimized by the JVM to improve
program speed. Program constants should thus be declared as static and
final.
Doclets
Although it might be a bit surprising to think of a tool that was developed for documentation support as something that helps you track down problems in your programs, doclets can be surprisingly useful. Because a doclet hooks into the javadoc parser, it has information available to that parser. With this, you can programmatically examine the class names, field names, and method signatures in your code and flag potential problems.
The process of producing the JDK documentation from the Java source files involves the parsing of the source file and the formatting of this parsed file by using the standard doclet. You can write a custom doclet to customize the formatting of your javadoc comments. However, doclets allow you to do far more than just formatting the comment because a doclet has available much of the information about the source file that’s being parsed.
You can extract information about all the members of the class: fields, constructors, methods, and the comments associated with each of the members (alas, the method code body is not available). Details about the members are encapsulated inside special objects, which contain information about the properties of the member (private, static, final etc.). This information can be helpful in detecting poorly written code, such as member variables that should be private but are public, method parameters without comments, and identifiers that do not follow naming conventions.
Javadoc may not catch all compilation errors. It will spot syntax errors, such as an unmatched brace, but it may not catch semantic errors. The safest approach is to run the Java compiler on your code before attempting to use a doclet-based tool.
The parsing mechanism provided by javadoc parses the entire source file and stores it in memory in an object of class RootDoc. The entry point for the doclet submitted to javadoc is start(RootDoc doc). It is comparable to a normal Java program’s main(String[] args). You may traverse through the RootDoc object and extract the necessary information. The following example shows how to write a simple doclet; it just prints out all the members of each class that was parsed:
//: c15:PrintMembersDoclet.java
// Doclet that prints out all members of the class.
import com.sun.javadoc.*;
public class PrintMembersDoclet {
public static boolean start(RootDoc root) {
ClassDoc[] classes = root.classes();
processClasses(classes);
return true;
}
private static void processClasses(ClassDoc[] classes) {
for(int i = 0; i < classes.length; i++) {
processOneClass(classes[i]);
}
}
private static void processOneClass(ClassDoc cls) {
FieldDoc[] fd = cls.fields();
for(int i = 0; i < fd.length; i++)
processDocElement(fd[i]);
ConstructorDoc[] cons = cls.constructors();
for(int i = 0; i < cons.length; i++)
processDocElement(cons[i]);
MethodDoc[] md = cls.methods();
for(int i = 0; i < md.length; i++)
processDocElement(md[i]);
}
private static void processDocElement(Doc dc) {
MemberDoc md = (MemberDoc)dc;
System.out.print(md.modifiers());
System.out.print(" " + md.name());
if(md.isMethod())
System.out.println("()");
else if(md.isConstructor())
System.out.println();
}
} ///:~
You can use the doclet to print the members like this:
javadoc -doclet PrintMembersDoclet -private PrintMembersDoclet.java
This invokes javadoc on the last argument in the command, which means it will parse the PrintMembersDoclet.java file. The -doclet option tells javadoc to use the custom doclet PrintMembersDoclet. The -private tag instructs javadoc to also print private members (the default is to print only protected and public members).
RootDoc contains a collection of ClassDoc that holds all the information about the class. Classes such as MethodDoc, FieldDoc, and ConstructorDoc contain information regarding methods, fields, and constructors, respectively. The method processOneClass( ) extracts the list of these members and prints them.
You can also create taglets, which allow you to implement custom javadoc tags. The JDK documentation presents an example that implements a @todo tag, which displays its text in yellow in the resulting Javadoc output. Search for “taglet” in the JDK documentation for more details.