|
By John Zukowski, June 20, 2006
|
|
|
In This Issue
Welcome to the Core Java Technologies Tech Tips for June 20, 2006. Here you'll get tips on using core Java technologies and APIs, such as those in Java 2 Platform, Standard Edition (J2SE).
This issue covers:
» Introducing Annotations
» Tech Tips Quiz
These tips were developed using Java 2 Platform, Standard Edition Development Kit 5.0 (JDK 5.0). You can download JDK 5.0 at http://java.sun.com/j2se/1.5.0/download.jsp.
This issue of the Core Java Technologies Tech Tips is written by John Zukowski, president of JZ Ventures, Inc.
See the Subscribe/Unsubscribe note at the end of this newsletter to subscribe to Tech Tips that focus on technologies and products in other Java platforms.
J2SE 5.0 introduced many new language features. These include support for generics and the enhanced for loop. Previous Tech Tips covered generics and the enhanced for loop.
Another important new feature in J2SE 5.0 is annotations. This tip explores the annotations that are built into J2SE 5.0.
First, what is an annotation? Defined as part of JSR 175: A Metadata Facility for the Java Programming Language, annotations offer a way to associate metadata with program elements (such as classes, interfaces, and methods). They can be thought of as additional modifiers without changing the generated bytecode for those elements.
The concept of introducing metadata to source code isn't new with J2SE 5.0. You can add an @deprecated tag to a method's javadoc comments and the compiler treats this as metadata about the method. This ability has been in place since the 1.0 release of J2SE. The initial release of the platform already had deprecated methods, with the getenv() method of System (though this wasn't in the Java Language Specification until the 1.1 addendum). The concept is almost the same now, at least the @ part of the syntax. Only the location has changed -- an annotation tag goes in source, not comments. The main point here is that annotations are a systematic way to support a declarative programming model.
This leads to the first annotation that comes with J2SE 5.0: @Deprecated. Notice the capital D here. Functionally, @Deprecated in source works the same as @deprecated in the javadoc associated with a class or method. By flagging methods with the @Deprecated tag, you're alerting the compiler to warn the user when the method or class is used.
The following Main class has a method named deprecatedMethod() that is flagged with the @Deprecated annotation and a, @deprecated comment:
public class Main {
/**
* @deprecated Out of date. Use System.foobar() instead.
*/
@Deprecated
public static void deprecatedMethod() {
System.out.println("Don't call me");
}
}
You compile a class with annotations the same way as you do for one without annotations:
> javac Main.java
As expected, this produces Main.class.
If you use the deprecated method, it produces a compilation-time warning -- just like using the @deprecated tag in a javadoc. Here's an example:
public class User {
public static void main(String args[]) {
Main.deprecatedMethod();
}
}
Compile the class:
> javac User.java
and you'll see the following warning about using a deprecated method:
Note: User.java uses or overrides a deprecated API.
Note: Recompile with -Xlint:deprecation for details.
Adding the -Xlint to the compilation line shows specifically what is wrong:
> javac -Xlint:deprecation User.java
User.java:3: warning: [deprecation] deprecatedMethod() in
Main has been deprecated
Main.deprecatedMethod();
^
1 warning
The change from the @deprecated comment to the @Deprecated annotation doesn't introduce anything really new to the system. It only slightly changes the way of doing the same thing. The other two new annotations available to the J2SE 5.0 platform, @Override and @SuppressWarnings, do introduce new functionality to the platform.
The @Override annotation can be used with method declarations. As its name implies, you use the @Override annotation to flag a method that is supposed to override a method of the superclass. Why use it? To catch errors sooner. How many times have you meant to override a method, but either misspelled the method name, specified the wrong arguments, or had a different return type? In other words, how often have you defined a new method when what you really wanted to do was override an existing one? By using @Override, you'll find the problem in the following class sooner rather than later:
public class Overrode {
@Override
public int hashcode() {
return 0;
}
@Override
public boolean equals(Object o) {
return true;
}
}
The problem here is that the method name should be hashCode, not hashcode. Suppose the method declaration is buried in the source for a much larger class definition. Without the first @Override annotation, how long would it take you to realize that your hashCode() method (with camel-case for spelling, not all lowercase) is not being called, and you're getting the default behavior of the parent Object class? Thanks to the @Override annotation, compiling the class produces a compile time error, alerting you to the problem:
> javac Overrode.java
Overrode.java:2: method does not override a method from its
superclass
@Override
^
1 error
The sooner you can find errors of this nature, the cost of correction becomes drastically reduced. Note that the hashCode() method should never return a constant. For a fuller description of the proper usage of hashCode() and equals(), see Item 8 in the book Effective Java Programming Language Guide by Joshua Bloch.
The final of the three new annotations in J2SE 5.0, @SuppressWarnings, is the most interesting. It tells the compiler not to warn you about something that it would normally warn you about. Warnings belong to a category, so you have to tell the annotation what types of warnings to suppress. The javac compiler defines seven options to suppress: all, deprecation, unchecked, fallthrough, path, serial, and finally. (The language specification defines only two such types: deprecation and unchecked.)
To demonstrate, let's look at the suppression of the fallthrough option. Let's start with the following class. Notice that the class is missing a break statement for each case of the switch statement:
public class Fall {
public static void main(String args[]) {
int i = args.length;
switch (i) {
case 0: System.out.println("0");
case 1: System.out.println("1");
case 2: System.out.println("2");
case 3: System.out.println("3");
default: System.out.println("Default");
}
}
}
Compile the class with javac. You'll see that it simply creates the .class file, and displays no warnings:
javac Fall.java
If you want the compiler to warn you about switch statements that fall through (that is, one or more break statements are missing), you compile with the -Xlint:fallthrough option:
javac -Xlint:fallthrough Fall.java
This produces the following warnings:
Fall.java:6: warning: [fallthrough] possible fall-through
into case
case 1: System.out.println("1");
^
Fall.java:7: warning: [fallthrough] possible fall-through
into case
case 2: System.out.println("2");
^
Fall.java:8: warning: [fallthrough] possible fall-through
into case
case 3: System.out.println("3");
^
Fall.java:9: warning: [fallthrough] possible fall-through
into case
default : System.out.println("Default");
^
4 warnings
But what if you want to ignore the fact that the switch statement is missing a break statement for each case? That's where the @SuppressWarnings annotation comes into play. If you add the following line before the main() method declaration:
@SuppressWarnings("fallthrough")
Compiling the class with the -Xlint:fallthrough option:
javac -Xlint:fallthrough Fall.java
will just generate the .class file and display no warnings.
@SuppressWarnings annotations can also be used to suppress other warnings such as those that would be displayed if you used a collection without specifying the data type of the collection elements. Don't use the @SuppressWarnings annotation simply to avoid the compilation-time warning. Use it where an unchecked warning is unavoidable, such as when using a library that isn't built with generics in mind.
That's really about it for the built-in annotations. However one additional thing to note, annotations (with any arguments) are typically specified on a line by themselves.
There is much more that can be done when you define your own annotations, rather than using the ones already defined in J2SE 5.0. For information on defining annotations see Annotations.
Back to Top
One of the items in the September 13, 2005 issue of the Tech Tips was a Tech Tips quiz. Many people enjoyed the challenge of the quiz. Others commented about how good it was to get pointers to some of the older tips. Here's another short quiz that tests your knowledge of some topics covered in past Tech Tips. You can find the answers at the end of the quiz.
- How do you enable
JOptionPane components to play auditory cues?
- For each component to enable, create a subclass of
JOptionPane and call its setAuditoryCuesEnabled() method.
- Set the
AuditoryCues.playList property of UIManager to the cue list to use for all option panes.
- Call the static
setAuditoryCuesEnabled() method of JOptionPane to enable cues for all option panes.
- Call the static
setAuditoryCuesEnabled() method of System to enable cues for all parts of the platform.
- In the following program, what's the value of the variable printed?
public class Foo {
private static ThreadLocal<Integer> threadLocal =
new ThreadLocal<Integer>() {
protected synchronized Integer initialValue() {
return new Integer(0);
}
};
public static void main(String args[]) {
Runnable runner = new Runnable() {
public void run() {
threadLocal.set((Integer)threadLocal.get() + 1);
}
};
for (int i=0; i<3; i++) {
Thread t = new Thread(runner);
t.start();
}
System.out.println("Value is " + threadLocal.get());
}
}
- 0
- 1
- 2
- 3
- When using reflection, which class do you use to construct an instance of a class?
- Constructors
- Method
- Field
- Class
- The Image I/O library provides support for reading and writing various image formats. Which format is newly supported with J2SE 5.0?
- GIF
- WBMP
- TIF
- SVG
- When using the Java 3D API, which class is the primary class used to create a scene graph?
Graphics3D
Static3D
Canvas3D
Transform3D
Answers
- How do you enable
JOptionPane components to play auditory cues?
- Set the
AuditoryCues.playList property of UIManager to the cue list to use for all option panes. See the January 22, 2004 Tech Tip Beyond the Basics of JOptionPane to learn about this setting and how to set cues for individual actions.
- In the following program, what's the value of the variable printed?
- 0. The
ThreadLocal variable is updated in threads other than the main thread so it is always zero in the main thread. For more information on the use of ThreadLocal variables, see the December 8, 2003 Tech Tip ThreadLocal Variables for Storing Thread-Specific State Information.
- When using reflection, which class do you use to construct an instance of a class?
Class. You can use either a Constructor class (not constructors) or a Class class to construct a class. See the January 10, 2004 Tech Tip Using Reflection To Create Class Instances for more information about class construction with reflection.
- The Image I/O library provides support for reading and writing various image formats. Which format is newly supported with J2SE 5.0?
- WBMP. J2SE 5.0 includes support for the BMP and WBMP formats. Support for reading GIF files has been available since J2SE 1.0. But support for writing GIF files isn't available until Java SE 6. For more on the Image I/O library, see the February 17, 2004 Tech Tip Loading and Saving Images with the Image I/O Library.
- When using the Java 3D API, which class is the primary class used to create a scene graph?
Canvas3D. The Java 3D API is an optional J2SE API and now a community source project. For more information about the Java 3D API, see the October 14, 2003 Tech Tip An Introduction to the Java 3D API and the July 16, 2004 Tech Tip Lighting a 3D Scene.
Back to Top
Need programming advice on Java SE? Try Developer Expert Assistance.
Comments and Contact Information: To send feedback about the SDN Program News:
For comments about the content of this newsletter, fill out the Rate and Review form, above.
For technical assistance about Newsletter delivery, broken links, or subscribe/unsubscribe help, fill out the web form.
Subscribe/Unsubscribe: You can subscribe to other Sun Developer Network (SDN) publications here:
https://softwarereg.sun.com/registration/developer/en_US/subscriptions
- To subscribe, select the newsletters you want to subscribe to and click "Update."
- To unsubscribe, uncheck the appropriate checkbox, and click "Update."
|
|