Reasons to Migrate to J2SE 5.0 (Tiger)

   
By John O'Conner, August 16, 2005  
The J2SE 1.4 platform was great, but J2SE 5.0 is even better. Although you may not need to migrate your product to this updated platform, you may want to move anyway. You can find more details about every new enhancement by reading the J2SE 5.0 release notes. Summarizing those notes, here are just a few areas that provide convincing reasons to start your migration now:
 
Language Features
The Java platform now supports some of the most powerful language features that developers have been requesting. You'll find support for all of the following once you migrate to 5.0:
 
Generics
Generics is a powerful new feature that allows you to add compile time type checking to your code. Also, your code will benefit from the cleaner syntax when you use generics instead of all those typecasts. You'll find generics to be particularly useful with the Collections API, but you can use them in other places as well.
 
Suppose you're working with a List of Customer objects, and you want to email an announcement about your latest product. Prior to J2SE 5.0, your code might look like this:
 
    void run() {
        List customerList = getCustomerList();
        sendEmailTo(customerList);
    }
    
    private void sendEmailTo(List list) {
        Iterator i = list.iterator();

        while(i.hasNext()) {
            Customer c = (Customer) i.next();
            sendEmailTo(c);
        }
    }

After adopting version 5.0, you can clean up the typecast when retrieving the next element from the iterator. In this particular example, the change may slightly increase the amount of code you write. However, decreasing the amount of code isn't the only way to improve productivity. The newer syntax using generics will save effort in both development and debugging, especially as the complexity of the application increases.
 
    void run() {
        List<Customer> customerList = getCustomerList();
        sendEmailTo(customerList);
    }
    
    private void sendEmailTo(List<Customer> list) {
        Iterator<Customer> i = list.iterator();

        while(i.hasNext()) {
            Customer c = i.next();
            sendEmailTo(c);
        }
    }

Everyone has a favorite feature that draws them to the latest Java platform. I spoke with Greg Boswell, president of Ilium Technologies, and asked him why he migrated. Without hesitation, he responded that generics were key to his migration. When I asked him why, he said this:
 
"Let's say you have a complicated set of interfaces...they're nested. We have Lists of interfaces and Lists of Lists of interfaces. Documentation is great, but the generics force the issue. Now everyone, including the architect who forgets what he did, is forced to comply with the coding. They are forced to deal with the generics. It prevents the class cast exceptions, but better than that, it cuts down on development time... How long does it take for me to walk through my code to find out [what interfaces are contained in those Lists]? Generics are forced documentation. They force [API] compatibility, cut development and research time, and just make it [programming/development] easier."
Enhanced For-Loop
The for-loop has been enhanced to work with collections of objects more easily. Instead of using iterators to loop through a Collection, you can use the new for-loop to process each object using a less error-prone syntax.
 
Continuing the previous example, you can change the while loop to a more streamlined for-loop:
 
    private void sendEmailTo(List<Customer> list) {
        for(Customer c: list) {
            sendEmailTo(c);
        }
    }

Autoboxing
Some APIs require you to pass objects instead of primitive types like byte, int, or float. Before J2SE 5.0, you had to manually "box" and "unbox" these primitive types when APIs required them to be encapsulated in their Object equivalents. For example, if an API called for an Integer argument, you would have to create the Integer object manually from an int value. In J2SE 5.0, you no longer have to manually package and unpackage (box and unbox) primitive types. The language can do this for you. No big deal? Maybe not, but it sure unclutters your code.
 
Without autoboxing, code that creates a List of integers and then prints the sum might look like this:
 
        // create the list of integers
        List listOfInts = new ArrayList();
        for (int i = 0; i < MAX_INT; ++i) {
            Integer aNumber = new Integer(i);
            listOfInts.add(aNumber);
        }

        // retrieve the list of integers and print the sum
        Iterator iterator = listOfInts.iterator();
        int total = 0;
        while(iterator.hasNext()) {
            Integer aNumber = (Integer)iterator.next();
            total = total + aNumber.intValue();
        }
        Integer theTotal = new Integer(total);
        System.out.printf("Total: %d\n", theTotal);

Using both generics and autoboxing, the code looks cleaner. In this particular case, the same operations require less code. Autoboxing and unboxing are used to automatically create Integers from int values and to create int values from Integers:
 
        // create the list of integers
        List<Integer> listOfInts = new ArrayList<Integer>();
        for (int i = 0; i < MAX_INT; ++i) {
            listOfInts.add(i); // autoboxing here
        }
        
        // retrieve the list of integers and print the sum
        int total = 0;
        for(Integer i: listOfInts) {
            total += i; // unboxing here
        }
        System.out.printf("Total: %d\n", total); //autoboxing here

Enumerations
Prior to J2SE 5.0, savvy engineers used the Typesafe Enum design pattern to produce enumerations. Although useful, the pattern has limitations. The C/C++ crowd has had first-class enumerations for years, and now Java developers have them too. They work in switch statements too!
 
Enumerations are a typesafe way to enforce specific values on variables. For example, imagine that you sell t-shirts in SMALL, MEDIUM, LARGE, and XLARGE sizes. You could create static final int constants for these values:
 
        static final int SMALL = 0;
        static final int MEDIUM = 1;
        static final int LARGE = 2;
        static final int XLARGE = 3;

        int shirtSize = LARGE;

However, your application has no type mechanism to enforce that a size variable should have only these values. In fact, it would be easy for your application to assign an invalid value:
 
        int shirtSize = 47;

While it is possible to enforce a specific range on the int values by creating a method for setting sizes, this isn't the best solution. A better solution is to use enumerations. You can create a Size enumeration, and both compile time and runtime checks will enforce valid value assignments:
 
        public enum Size {
            SMALL,
            MEDIUM,
            LARGE,
            XLARGE
        }

        Size shirtSize = Size.LARGE; //but never 47

In this case, the enumeration enforces valid values into the shirtSize variable.
 
Varargs
The varargs feature provides an alternate syntax for providing a variable number of arguments to a method. Before J2SE 5.0, you had to create an Object array, place your arguments into the array, and pass the array as the method argument. Now you can place the arguments as a sequence of individual arguments in the method call.
 
Consider the following code snippet that formats a user message with variable inputs packaged in an Object array:
 
        Object[] args = new Object[] {new Date(), 5, "Mars"};
        String pattern = "At {0, time, short} on {0, date, short}, we saw {1, number,
                         integer} " + "ships on the planet {2}.";
        String msg = MessageFormat.format(pattern, args);

In the above example, the definition of args is close to its use in the MessageFormat class, so it's not particularly difficult to know what those arguments actually are. However, in a larger example, it might be difficult to trace the declaration and definition of args. In that situation, one might want to be more explicit in the format call. Instead of passing a single Object array as above, one might consider passing a sequence of variable arguments as shown below:
 
        Date time = new Date();
        int count = 5;
        String planet = "Mars";

        String pattern = "At {0, time, short} on {0, date, short}, we saw {1, number,
                         integer} " + "ships on the planet {2}.";
        String msg = MessageFormat.format(pattern, time, count, planet);

This example explicitly shows the variable input arguments being using in the format method.
 
Static Imports
The static import feature allows you to import an entire set of static class members into your code and to refer to those constants or methods by their short, unqualified names. For example, if you use the java.lang.Math class, you can now import Math's static members to refer to them directly. This allows you to use PI instead of Math.PI or tan instead of Math.tan.
 
Before static imports, your code had to include the classname that contained the static fields or methods like this:
 
        double x = Math.tan(45.0);
        double y = Math.pow(3.0, 2.0);

After J2SE 5.0, you can import the entire set of Math static members and use the methods without a qualified class name:
 
        import static java.lang.Math.*;
        ...
        double x = tan(45.0);
        double y = pow(3.0, 2.0);

Static imports should be used sparingly. Although this feature does provide a coding shortcut that can save you time, the J2SE 5.0 language guide describes several good reasons for using this particular feature in moderation.
 
Annotations
Annotations provide runtime-accessible information about your code. Unlike comments or even Javadoc tags, which are not included in compiled code, annotations are compiled into the class file. Applications can access annotation information at runtime, allowing your code to make sophisticated, dynamic decisions about how to use annotated classes, methods, and other members in your programs. You can learn more about annotations in the language guide. Additionally, the article " Using Annotations to add Validity Constraints to JavaBeans Properties" shows how one engineer uses annotations to solve a longstanding problem with validity constraints.
 
Class Libraries
If the new language features don't pull you to J2SE 5.0, the class library enhancements will. Check out some of the new libraries below:
 
Concurrency
The Java platform has always provided basic support for multi-threaded applications. Developers use the java.lang.Thread and its related classes to create, start, and stop threads. However, developers had to create their own frameworks for managing those threads to avoid deadlocks and other synchronization problems. The new java.util.concurrent package in J2SE 5.0 is dedicated to creating and managing concurrent threads. This package provides utilities that will save you time and trouble creating concurrent applications. The article " Concurrent Programming with J2SE 5.0" will help you understand and use this new concurrency package.
 
Scanner
Using System.out.println, you can easily send text output to a shell or console window. However, getting text into a non-GUI application hasn't been as easy...until now. J2SE 5.0 provides a new Scanner class that you can wrap around System.in. The Scanner class uses the regex package to parse text input and to convert that input into primitive types. Of course, it's not limited to scanning System.in, but it is certainly helpful in that area. The following code snippet shows how Scanner can be used to retrieve a string and an integer from the console:
 
        Scanner scan = new Scanner(System.in);

        System.out.print("What is your name? ");
        String name = scan.next();
        
        System.out.print("How old are you? ");
        int age = scan.nextInt();
        
        String msgPattern = "Hi {0}. You are {1} years old.";
        String msg = MessageFormat.format(msgPattern, name, age);
        System.out.println(msg);

Security
Security enhancements now allow applications to use non-blocking SSL/TLS implementations, Kerberos ciphersuites, SASL, and the Time Stamp Protocol. Now you have even more options for creating and delivering secure applications and content. You can begin your research into these enhancements with the language guide " Security Enhancements in the Java 2 Platform Standard Edition 5".
 
Internationalization
The Java platform supports more languages and writing systems than ever before. Unicode 4.0 is fully supported throughout the platform. Many classes, including both Character and String, have new methods to manipulate supplementary characters. Supplementary characters are characters beyond the base 0x0000 through 0xFFFF range and are represented by two char code units. Unicode 4.0 support is particularly important to you if your application must comply with the Chinese government's GB18030 charset initiative.
 
If your application has been localized to any Asian market, it will definitely benefit from the new APIs. The article " Supplementary Characters in the Java Platform" describes how to handle supplementary characters with the new platform libraries.
 
Tool Support
Some engineers may hesitate to migrate their code when a new Java platform becomes available. They fear that their favorite tool may not support the latest language features. However, if you've been waiting to migrate to J2SE 5.0 for this reason, you should definitely reconsider. Most popular tools, integrated developer environments, and editors now provide full, rich support for the J2SE 5.0 platform. My brief look at just a few popular tools found complete J2SE 5.0 language support in all of the following:
 
This list is definitely not complete. If you've been waiting for tool support, you're wait is over. Chances are good that your favorite tool now supports J2SE 5.0 as well.
 
Desktop Enhancements
With all the excitement over language and class library updates, it may be easy to overlook all that's happened on the desktop. The Java platform has significant improvements in several areas. Although I present a few updates here, you can learn about more desktop enhancements by reading Chet Haase's informative blog " Tiger on the Desktop". Here are just a few of the desktop updates you can enjoy after migrating to J2SE 5.0:
 
  • look and feel
  • JTable printing
  • multilingual fonts
Ocean Look and Feel
The default Java look and feel has migrated from the old, rusty Metal theme to a brighter, cooler Ocean them. We think you'll agree that this new style is a welcome enhancement. John Zukowski provides an overview of this theme in " Taming Tiger: Ocean and Synth meet Metal." Here's a snapshot for you to see it for yourself:
 
Taming Tiger: Ocean and Synth meet Metal
Taming Tiger: Ocean and Synth meet Metal
Have Your JTable and Print it Too
Prior to the Tiger release, you had to leave your information rich JTables behind when you left your computer. Sure, you could see it on screen, but printing was practically impossible. Not any more. J2SE 5.0 makes it possible, even easy, to print JTable contents. Check out our tech tip for how to add printing to your JTable.
 
Multilingual Fonts
Displaying multilingual text using logical fonts has always been possible, just not very easy. However, the new text rendering engine makes displaying multilingual text easy. If your system has the physical fonts containing the characters you want to display, the 2D text rendering engine can find and use them regardless of the logical font you've selected. Additionally, if you add fonts to the JRE's /lib/fonts/fallback directory, the runtime environment will find and add them to your logical font definitions. Now, whether your application is hosted in a Japanese locale or U.S. English locale, you can display Korean, Indic, or any other supported writing system as long as you have appropriate fonts installed.
 
Multilingual Fonts
Multilingual Fonts
Quality
If you're still undecided about migrating, consider this: quality was the #1 theme for J2SE 5.0 development. During the development cycle for this product, Sun engineers were constantly reminded about their commitment to stability, robustness, and compatibility.
 
Many of the development processes were changed to enforce this theme. For example, new processes were adopted to manage defect resolution, to monitor new enhancements, and to develop new tests. Not only does this release provide a wide range of new features, but it contains fixes for hundreds of defects. Compatibility with previous versions of the platform is always a priority. JDK 5.0 is upward compatible with JDK 1.4.2. You can find out more in the compatibility release notes for J2SE 5.0.
 
Graham Hamilton makes a good point in his blog about version numbers. Some engineers like to wait for the .1 release of any technology because they think it will be more stable than the .0 release. OK, maybe that's true in general, but if you've been waiting for the .1 release of J2SE 5.0, don't wait any longer. It won't come. The next major release is 6.0, not 5.1. So, you should consider the current update as your anticipated .1 release. It's available now, and there's no need to wait any longer.
 
Get Started Now
Migrating to J2SE 5.0 couldn't be easier. It's an easy decision and an easy process. It's an easy decision because of the new language enhancements, new class libraries, tool support, and quality. Migration has plenty of benefits. It's an easy process because the updated platform is both binary and source compatible with your J2SE 1.4.2 code. You can run old classes under the new JRE, and you can recompile source code with confidence that your application will continue to work. Join the migration. Get started today.
 
Rate and Review
Tell us what you think of the content of this page.
Excellent   Good   Fair   Poor  
Comments:
Your email address (no reply is possible without an address):
Sun Privacy Policy

Note: We are not able to respond to all submitted comments.