Java: The "I" of the Tiger

Java
Typography
  • Smaller Small Medium Big Bigger
  • Default Helvetica Segoe Georgia Times

The Rocky movies have been on TV lately. That series generated some great songs. The Rocky theme is one of the all-time great movie themes, but who can forget "The Eye of the Tiger"? And it seems particularly appropriate right now as Java, the one-time indomitable force of the industry, has taken a few blows in recent years, especially from the Number One Contender (Mr. G?).

The whole .NET paradigm is about ease of use and programmer productivity, and that's the constant mantra from the Java detractors: Java is just too hard to use (sounds like the anti-WebSphere crowd, doesn't it?). You can point to all of those beautiful visual programming tools, and until recently the only response from the Java camp was that programming is hard and that dragging and dropping isn't really programming anyway. And even if you agree with that sentiment, it's still not much of a rebuttal. But with this release, Java comes out hitting hard and targeting the correct audience: the professional programmer. This isn't about quickly throwing together a Web page for a storefront; this is about real, serious changes to the language to allow programmers to do more work better.

Welcome to Tiger!

The latest release of Java is known as Tiger. It's interesting to review the history of Java releases. Java 1.0 was all but useless, as one might expect, and designated primarily for browsers. Java 1.1 was the first release that could build respectable applications, and it went through many evolutions, all the way up to Version 1.1.8. Then came Java 1.2, which was the first release to provide the Enterprise Edition, with all of the powerful Web application server capabilities.

It's interesting to then see the following releases. Java 1.3 was primarily a performance release, with the highlight being the Java HotSpot Client Machine. While there were a number of additions to the language, much of the work was done under the covers in the Java Virtual Machine (JVM). Then came Version 1.4, which was the features release, adding tons of new classes ranging from security to logging to assertions to collections. Here, the bulk of the additions came from new code added to the core libraries. Now comes Version 1.5, which is adding features by fundamentally changing the syntax of the language. Each major release has had a different focus area, and together they have radically transformed the language from its early days as a Web browser add-on.

Version 1.5, or Is It 5.0?

One of the more bizarre issues of the release is that Sun has decided to re-invent its numbering scheme. This actually started back in Version 1.2, which Sun started calling Java 2. Many of us thought this might mean that Java 1.2 was being renumbered to Java 2.0, but we were wrong. Sun immediately confused the issue, calling the next release Java 2 Version 1.3 and following it with Java 2 Version 1.4. So the platform is Java 2 (as in J2SE and J2EE), but the version is still 1.x, as in 1.3 and 1.4. Confused? We were.

Well, they've decided to at least end that particular naming convention, for better or for worse. This latest release, which would have been Version 1.5 of Java 2, is now Version 5.0 of Java 2. My guess is that the J2SE and J2EE monikers are so embedded in the lexicon that we'll never see them disappear. But the idea of the software being only on Version 1.x just didn't sit well with the powers that be at Sun, so Java made a grand leap from 1.4 to 5.0, all in one release.

What's New?

There are numerous new things in this release, many of which are changes to the syntax of the language itself. Other changes are simply responding to the inevitable movement of other parts of the industry.

Ease-of-Use Changes

These are some of the most fundamental changes, as they affect the actual syntax you use to write your code. These changes help programmers in two ways: They make it easier to code things, and they help remove common errors. The biggest example is the enhanced for loop code, which not only makes programming loops far easier, but also removes one of the great problems of nested loops. Here's Sun's own example (where suits, ranks, and sortedDeck are objects of type List):

// BROKEN - throws NoSuchElementException!
for (Iterator i = suits.iterator(); i.hasNext(); )
    for (Iterator j = ranks.iterator(); j.hasNext(); )
        sortedDeck.add(new Card(i.next(), j.next()));

This has a nasty bug: The i.next() method, which selects the next suit, is called too many times. It is being called for every card instead of once for each complete set of ranks, and that will cause an exception. The fix is below:

// Fixed, though a bit ugly
for (Iterator i = suits.iterator(); i.hasNext(); ) {
    Suit suit = (Suit) i.next();
    for (Iterator j = ranks.iterator(); j.hasNext(); )
        sortedDeck.add(new Card(suit, j.next()));
}

Note the use of a temporary Suit variable to hold the value. That's because the for loop isn't really good about holding the temporary contents of the loop. The new for construct is much better:

for (Suit suit : suits)
    for (Rank rank : ranks)
        sortedDeck.add(new Card(suit, rank));

Another change is something called "auto-boxing." When I teach Java classes, one of the hardest things to explain is the difference between primitive types (int, float, long, and so on) and objects. One fundamental difference is that primitive types cannot be added to things like Lists, because Lists only support objects. So instead, a set of reference classes (one for each primitive) can be used to wrap a primitive in an object. Whenever you need to treat a primitive as an object, you can "wrap" in it the associated reference type. For example, assume todayTemp is a primitive int and dailyTemps is a List. Currently, you would have to explicitly wrap and unwrap the primitives in the code below:

dailyTemps.add(new Integer(todayTemp));
int firstTemp = ((Integer) dailyTemps.get(0)).intValue();

With Tiger, a programmer can code this:

dailyTemps.add(todayTemp);
int firstTemp = dailyTemps.get(0);

In the first line, the variable todayTemp is automatically cast into its corresponding reference type, while in the second line the Integer object received from the get method is "unwrapped" into the primitive firstTemp. The Java folks call this "auto-boxing," and it greatly simplifies the cross-use of primitives and objects.

The biggest change, though, is the support for Generics. The Java Collection Framework, which consists of a wide variety of powerful classes for ordering, sorting, and selecting data, was only able to work by passing everything as a generic object. And while this allowed very powerful and flexible programming, it also required a lot of casting, especially downcasting, which is a traditional source for runtime errors. Runtime errors are easily 10 times more expensive to find and fix than compile time errors, so this compromise between flexibility and safety has been a problem from the inception of the Collection classes.

Finally, with the advent of Generics, you can specify a type at the time of defining a Collection class, which will force the Collection to become type-safe. In its simplest form, a type-safe Collection might be a List of Strings. The compiler will allow only objects of type String to be added to the List, and because of this, the compiler also knows that any objects coming out of the List are Strings. This allows the programmer to write things more easily. For example, note that the cast is required on the third line, even though we know that we added an object of type String:

ArrayList words = new ArrayList();
words.add(new String("hello"));
String firstWord = (String) words.get(0);

That's because the compiler can't be sure that only Strings were added. We could have instead done something like this:

ArrayList words = new ArrayList();
words.add(new Integer(0));

If the compiler assumed that everything was a String and didn't require the cast, we'd end up with a pretty ugly error at runtime. However, the new Generics syntax allows us to get around all that:

ArrayList words = new ArrayList();
words.add(new String("hello"));
String firstWord = words.get(0);

It doesn't seem like much, but not having to cast things when getting them out of Collections can save a ton of code that really clutters the program. And what about the problem of accidentally adding an Integer object? Well, the compiler simply doesn't allow it, so Generics help you avoid your own programming mistakes as well.

There are other changes, but these are the really big ease-of-use changes that were made with just a simple syntax change. One other that deserves mention is the variable arguments syntax change: Using an ellipsis (...) allows you to specify an indeterminate number of parameters of a given type. The caller specifies as many as needed, separated by commas. The compiler "boxes" them into an array and sends the array to the method. It's just a shorthand for creating the arrays in the calling method yourself, but it's really quite powerful. And this enhancement in combination with auto-boxing of primitives allowed the Java folks to add the long-missed "printf" formatting capabilities of other C-related languages.

Other Changes

The numerous other changes don't rank quite as high on the visibility scale. The concept of an enum has made it into the language, which is a great way to help make code easy to read. Metadata has been added as well, with a carefully thought-out infrastructure. Metadata consists of classes that can be attached to components of other Java code (methods, types, packages, and so on). These classes can then be used for all manner of preprocessing, from generating code as in a traditional preprocessor, to creating additional files such as BeanInfo classes.

The area of security has also seen huge enhancements. These include non-blocking implementations of the Secure Sockets Layer (SSL) and Transport Layer Security (TLS) protocols, enhanced Kerberos support (including triple DES encryption), and support for Simple Authentication and Security Layer (SASL) implementations. All of these will better allow Java-based applications to play in the evolving world of security, especially with Kerberos and single sign-on.

XML support has been enhanced with the addition of DOM level 3, SAX 2.0.2, and XSLT 1.0 APIs. This is just one of the business-related functions the Tiger release adds. Another often-overlooked class is the BigDecimal class, the fixed-precision decimal data class that roughly translates to our packed or zoned decimal fields in RPG. Better support for formatting and parsing these values has been added, making it much easier to write business arithmetic in Java (one of my personal negative points about the language).

This is only a scratch on the surface of the Tiger release. Major enhancements have been added to the VM to support debugging and monitoring, deployment has been improved, three entire packages have been added to support concurrency and multi-threading, and the list goes on. Feel free to check out the J2SE 5.0 New Features page or the J2SE 5.0 in a Nutshell page to get started.

The Process Is Working

What I find refreshing is that it's pretty clear that the Java Community Process (JCP) is indeed working. Windows is fast becoming a closed, proprietary system even as Microsoft advocates argue vehemently against that statement. However, Microsoft's only real rebuttal these days is that C# and CLI have been submitted to a standards body (even this is something of a misnomer, as the 300 classes submitted to the ECMA standards committee comprise only about 10% of the classes that ship with the Microsoft developer tools), while Java is still under Sun's purview through the JCP. Well, this latest release shows me that the JCP is working just fine. The things that have changed in Version 5.0 are clearly direct responses to the issues Java programmers have been dealing with.

Generics, enums, variable argument lists, C-style formatting--all of these are additions that really add no "value" to the language but instead make it easier for programmers to do their job. And that, I think, is a very interesting observation. Whereas Microsoft seems to be moving toward dumbing down the software development process into a drag-and-drop assembly of mediocre quality, the Java team seems to be trying to enable programmers and allow them to develop better code. This may just be my own wishful thinking, but it seems to me that at least some members of the Java community still believe that programming is a hard job done by talented individuals, whereas at Microsoft the idea seems to be that anybody can create programs if given enough toys.

The problem with assembling software, however, is that somebody has to design and create the little pieces that the common person assembles. But once everyone becomes an assembler and nobody is designing anymore, then the software pool becomes stagnant. The trick is not to turn software development into mass production of prefabricated solutions; instead, the trick is to develop tools that empower the best minds to create architectures we've never dreamed of. That's why I like RPG over code generators: RPG lets me do things my way, while code generators have already decided my way for me.

On the Ropes or Just Rope-a-Dope?

Speaking of "boxing," in 1974 Muhammad Ali fought George Foreman in a classic confrontation touted as "The Rumble in the Jungle." Yes, that George Foreman--in the '70s, he was a force of nature every bit as powerful in the ring as he is today on infomercials selling cookware. Foreman had beaten Joe Frazier, who earlier had beaten Ali. Foreman, in his prime at 25 years old, was perhaps one of the hardest punching heavyweights ever to step in the ring, while Ali had had his jaw broken just a year earlier. Everyone except Howard Cosell thought Ali, then 32 and "past his prime," would be little more than a punching bag for young George.

And they were right. For seven rounds, Ali just lay against the ropes, covering his face, letting Foreman pound away at him. And after seven rounds of non-stop battering, George simply punched himself out. At that point Ali, bruised but not broken, calmly proceeded to tear Foreman apart.

This strategy became known as the Rope-a-Dope, and it's valid in every conflict today, including business. If you think you can withstand your opponent's worst barrage, let them throw everything they have at you. Then, when they're tired and dismayed that you haven't dropped, they'll make a mistake and you can walk in and crush them.

While I have no way of knowing what goes on in Sun's boardrooms or in Bill's mind, I do know that there is a certain obvious parallel with history here. Sun knew it needed to do some serious work to the language, and it also knew that nothing Microsoft could do during this period could knock Sun out of the market. So Sun basically covered up and began work on major enhancements to the language, enhancements that allowed Sun to catch up in areas like security, as well as enhancements that put the company ahead of the game, like Generics and metadata. (Author's Note: Microsoft aficionados, especially C# advocates, may argue that the .NET implementation of these features is better than that of Java; you can find interesting comparisons on the Web. But you'll need to compare the features yourself and weigh them along with all the external factors to make your own decision.)

At the same time, Sun allowed Microsoft to effectively punch itself out. While it didn't take any great predictive skills to guess that Microsoft would have some issues with its next version of Windows, the ongoing problems, delays, and feature omissions in this new release have made Sun look like the Amazing Karnak. In fact, with the explosive growth of the Eclipse IDE as a viable alternative to Visual Studio and the focus of Java as a programmer's language rather than a coder's tool, the folks at Sun (and IBM) are beginning to look downright prescient.

Joe Pluta is the founder and chief architect of Pluta Brothers Design, Inc. He has been working in the field since the late 1970s and has made a career of extending the IBM midrange, starting back in the days of the IBM System/3. Joe has used WebSphere extensively, especially as the base for PSC/400, the only product that can move your legacy systems to the Web using simple green-screen commands. Joe is also the author of E-Deployment: The Fastest Path to the Web, Eclipse: Step by Step, and WDSC: Step by Step. You can reach him at This email address is being protected from spambots. You need JavaScript enabled to view it..

BLOG COMMENTS POWERED BY DISQUS