Core Java Technologies Tech Tips Tips, Techniques, and Sample Code 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. (http://www.jzventures.com). You can view this issue of the Tech Tips on the Web at http://java.sun.com/mailers/techtips/corejava/2006/tt0620.html 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. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - INTRODUCING ANNOTATIONS J2SE 5.0 introduced many new language features. These include support for generics and the enhanced for loop. Previous Tech Tips covered generics (http://java.sun.com/developer/JDCTechTips/2005/tt0315.html#1) and the enhanced for loop (http://java.sun.com/developer/JDCTechTips/2005/tt0505.html#2). 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, (http://www.jcp.org/en/jsr/detail?id=175), 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" (http://java.sun.com/docs/books/effective/) 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 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" (http://java.sun.com/j2se/1.5.0/docs/guide/language/annotations.html). - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - TECH TIPS QUIZ One of the items in the September 13, 2005 issue of the Tech Tips (http://java.sun.com/developer/JDCTechTips/2005/tt0913.html) 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. 1) How do you enable JOptionPane components to play auditory cues? a) For each component to enable, create a subclass of JOptionPane and call its setAuditoryCuesEnabled() method. b) Set the AuditoryCues.playList property of UIManager to the cue list to use for all option panes. c) Call the static setAuditoryCuesEnabled() method of JOptionPane to enable cues for all option panes. c) Call the static setAuditoryCuesEnabled() method of System to enable cues for all parts of the platform. 2) In the following program, what's the value of the variable printed? public class Foo { private static ThreadLocal threadLocal = new ThreadLocal() { 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()); } } a) 0 b) 1 c) 2 d) 3 3) When using reflection, which class do you use to construct an instance of a class? a) Constructors b) Method c) Field d) Class 4) The Image I/O library provides support for reading and writing various image formats. Which format is newly supported with J2SE 5.0? a) GIF b) WBMP c) TIF d) SVG 5) When using the Java 3D API, which class is the primary class used to create a scene graph? a) Graphics3D b) Static3D c) Canvas3D d) Transform3D Answers 1) How do you enable JOptionPane components to play auditory cues? b) 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" (http://java.sun.com/developer/JDCTechTips/2004/tt0122.html#1) to learn about this setting and how to set cues for individual actions. 2) In the following program, what's the value of the variable printed? a) 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 (http://java.sun.com/developer/JDCTechTips/2003/tt1208.html#2). 3) When using reflection, which class do you use to construct an instance of a class? d) 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" (http://java.sun.com/developer/JDCTechTips/2003/tt0110.html#2) for more information about class construction with reflection. 4) The Image I/O library provides support for reading and writing various image formats. Which format is newly supported with J2SE 5.0? b) 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 (http://java.sun.com/developer/JDCTechTips/2004/tt0217.html#1). 5) When using the Java 3D API, which class is the primary class used to create a scene graph? c) Canvas3D. The Java 3D API is an optional J2SE API and now a community source project (https://java3d.dev.java.net/). For more information about the Java 3D API, see the October 14, 2003 Tech Tip "An Introduction to the Java 3D API" (http://java.sun.com/developer/JDCTechTips/2003/tt1014.html#1) and the July 16, 2004 Tech Tip "Lighting a 3D Scene" (http://java.sun.com/developer/JDCTechTips/2004/tt0716.html#2). - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - DEVELOPER ASSISTANCE Need programming advice on Java SE? Try Developer Expert Assistance (http://developers.sun.com/services/expertassistance/) . . . . . . . . . . . . . . . . . . . . . . . If you have your own Tech Tip that you would like to share with others, you're encouraged to post it in an appropriate Sun Developer Network forum (http://forum.java.sun.com/index.jspa). IMPORTANT: Please read our Terms of Use, Privacy, and Licensing policies: http://www.sun.com/share/text/termsofuse.html http://www.sun.com/privacy/ http://developers.sun.com/dispatcher.jsp?uid=6910008 * FEEDBACK Comments? Please enter your feedback on the Tech Tips at: http://developers.sun.com/contact/feedback.jsp?category=sdn * SUBSCRIBE/UNSUBSCRIBE Subscribe to other Java developer Tech Tips: - Enterprise Java Technologies Tech Tips. Get tips on using enterprise Java technologies and APIs, such as those in the Java 2 Platform, Enterprise Edition (J2EE). - Wireless Developer Tech Tips. Get tips on using wireless Java technologies and APIs, such as those in the Java 2 Platform, Micro Edition (J2ME). To subscribe to these and other JDC publications: - Go to the Sun Developer Network - Subscriptions page, (https://softwarereg.sun.com/registration/developer/en_US/subscriptions), choose the newsletters you want to subscribe to and click "Submit". - To unsubscribe, go to the Subscriptions page, (https://softwarereg.sun.com/registration/developer/en_US/subscriptions), uncheck the appropriate checkbox, and click "Submit". - To use our one-click unsubscribe facility, see the link at the end of this email: - ARCHIVES You'll find the Core Java Technologies Tech Tips archives at: http://java.sun.com/developer/TechTips/index.html - COPYRIGHT Copyright 2006 Sun Microsystems, Inc. All rights reserved. 4150 Network Circle, Santa Clara, California 95054 USA. This document is protected by copyright. For more information, see: http://java.sun.com/developer/copyright.html Core Java Technologies Tech Tips June 20, 2006 Trademark Information: http://www.sun.com/suntrademarks/ Java, J2SE, J2EE, J2ME, and all Java-based marks are trademarks or registered trademarks of Sun Microsystems, Inc. in the United States and other countries.