Developer

Java Programming: Explore the advanced coding features of JDK 1.5

The Java programming language is getting a much needed upgrade to the Java Development Kit 1.5. Examine several Java coding specifications and features of JDK 1.5 and get ahead of the programming curve.


Sun is planning to release a major revision of the Java programming language in summer 2004. This release is code named "Tiger," but it will receive the official designation of JDK 1.5.

This version of the Java language will incorporate Java Specification Requests 14 and 175 (JSR-14, JSR-175). It will also have major enhancements for runtime performance, scalability, manageability, and monitoring.

In this article, we'll discuss several of the new language features of JDK 1.5, including:
  • Generics—Provides compile-time type safety for collections and eliminates the need for casting every time you get an object out of Collections.
  • Enhanced For loop—Eliminates error-proneness of iterators.
  • Autoboxing/unboxing—Eliminates need of manual conversion between primitive types (such as double) and wrapper types (such as Double).
  • Typesafe enumsProvides all benefits of the Typesafe enum pattern.
  • Static import—Eliminates the need for using class names prior to using the static member variables of other classes. This will make the code a bit neater.
  • Metadata—Allows programmers to avoid writing boiler plate code and gives the opportunity for declarative programming.

Let's discuss each feature in detail and take a look at some examples.

Generics
Generics is one of the coolest features of JDK 1.5. By introducing generics, we will have compile-time type safety and possibly fewer ClassCastExceptions during run time. In JDK 1.5, you can declare the type of objects one collection will accept/return. In JDK 1.4, creating a List of employee names requires a collection object like the following statement:
List listOfEmployeeName = new ArrayList();

In JDK 1.5, you would use this statement:
List<String> listOfEmployeeName = new ArrayList<String>();

The cool part is that if you try to insert something that's not a string, you will find out at compile time and then you can fix the problem. Without generics, you discover such a bug when your customer calls and tells you that the program you shipped crashed with a ClassCastException.

The other cool thing is that you don't have to cast when you get an element out of the collection. So instead of this type of statement:
String employeeName = ((String) listOfEmployee.get(i));

It's simply:
String employeeName = listOfEmployee.get(i);

Casting objects without knowing the type of object is not good, and more importantly, it can fail at run time. Suppose the user accidentally passes in a collection that contains string buffers rather than strings. In Listing A, the client is required to pass in a collection of strings that the compiler can't enforce.Listing B shows how the same method looks with generics.

Now it's clear from the method signature that the input collection must contain only strings. If the client tries to pass in a collection of string buffers, the program won't compile. And notice that the method doesn't contain any casts. It's one line shorter and, once you get used to reading generics, it's clearer too.

Enhanced For Loop
Here's the syntax for the For loop in the current version of the JDK:
void printAll(Collection c) {
       for (Iterator i = c.iterator(); i.hasNext(); ) {
               Employee emp = (Employee)i.next();
               System.out.println(emp.getName());
       }
}


Now here's the same method with an enhanced For statement:
void printAll(Collection c) {
       for (Object o : c)
               System.out.println((TimerTask)o).getName());
}


In this For loop, you should read the ":" as "in," so the example reads "for Object o in c". You can see this For loop has more readability.

Autoboxing and unboxing
In Java, we have primitive data types and wrapper classes around these primitive types. Most often programmers need to convert one type to another. Take a look at the code snippet in Listing C.

Notice how messy the inner-loop code that calculates ageAfterTenYear looks. Now take a look at the same program rewritten with autoboxing, as shown in Listing D.

One thing worth noting: Previously, if you unboxed Null, it became zero. In this code, the compiler would automatically convert Integer to int and add 10 to it, then convert that back to Integer.

Typesafe enums
Typesafe enums provide the following features:
  • They provide compile-time type safety.
  • They are objects, so you can put them in collections.
  • They are implemented as a class, so you can add some methods.
  • They provide a proper name space for the enumerated type.
  • Their printed values are informative—if you print an int enum, you just see a number, which may not be that informative.

Example 1:
enum Season { winter, spring, summer, fall }

Example 2:
public enum Coin {
       penny(1), nickel(5), dime(10), quarter(25);

       Coin(int value) { this.value = value; }

       private final int value;

       public int value() { return value; }
}


Static imports
Static imports make code more readable. Currently, you use constants defined in other classes, like this:
import org.yyy.pkg.Increment;

class Employee {
       public Double calculateSalary(Double salary{
              return salary + Increment.INCREMENT * salary;
       }
}


But with static import, we can use those constants without providing the name of the class prior to constant name, like this:
import static org.yyy.pkg.Increment;

class Employee {
       public Double calculateSalary(Double salary{
               return salary + INCREMENT * salary;
       }
}


Note that we are able to call the INCREMENT constant without using the class name Increment.

Metadata
The metadata feature is focused on making a developer's life simpler with the support of tools provided by vendors. Take a look at the code in Listing E.

With metadata support, you can write the code in Listing E like this:
import org.yyy.hr;

public class Employee {
       @Remote public String getName() {
               ...
       }
       @Remote public public String getLocation() {
               ...
       }
}


As you can see, all the boilerplate's code is gone.

The new features and specifications that will be implemented in JDK 1.5 offer the Java programming community many more options for writing robust, scalable code. Serious Java programmers would do well to begin familiarizing themselves with the pending version of the Java programming language.

Useful links
Here are a few useful links for further exploring the specifications of JDK 1.5:

Download a prerelease version of a compiler that understands generics.

The latest draft for generics can be found at the Java Community Process site.

The draft of the Java language proposal is also available from the JCP site.

The JCP also offers the draft for the metadata specification.


 

Editor's Picks