New features in JDK 5

Here is a summary of the new language features coming this fall in JDK 5, taken mostly from a talk given Wednesday by Joshua Bloch and Neal Gafter at the Denver Java Users Group.

The seven language changes in Java 1.5:
  • Generics
  • For-each loop
  • Autoboxing/unboxing
  • Enums
  • Varargs
  • Static imports
  • Annotations (metadata)
There are additional features and new libraries coming in 1.5 (easier multi-threading, disconnected JDBC rowsets, JMX added to the core language, dynamically generated stubs to eliminate almost all need for RMIC, and more!), but the above are actual syntax changes. Josh said Sun's primary goal of the language changes was to make our lives as programmers easier -- less typing, clearer programs, easier to avoid mistakes.

Here's a summary of the features I'm likely to use right away in everyday programming. You can read more about new features from Josh and Neal's presentation slides. Read on if you want more of the explanation you would have heard had you been able to attend their presentation in Denver.

Generics, autoboxing, for-each

Josh showed a simple program that demonstrates these new features:
import java.util.Map;
import java.util.TreeMap;
public class Frequency {
public static void main(String[] args) {
Map<String, Integer> m = new TreeMap<String, Integer>();
for (String word : args) {
Integer freq = m.get(word);
m.put(word, (freq == null ? 1 : freq + 1));
}
System.out.println(m);
}
}
Running the code would look something like this:
$ java Frequency if it is to be it is up to me
{be=1, if=1, is=2, it=2, me=1, to=2, up=1}
The first odd-looking line,
Map<String, Integer> m = new TreeMap<String, Integer>();
says to create a TreeMap that stores only Integers using only Strings as the map's key. When you create a map by defining the actual types in the declaration, the compiler won't let you use a non-string as the map's key, and won't let you store something that isn't assignable as an Integer to the map's value. The benefit?
  • Compile-time type safety
  • No ugly casts
How's that for making coding easier! Josh Bloch called it "stronger typing with less typing."

Now, take a look at the for loop:
for (String word : args) {
Integer freq = m.get(word);
m.put(word, (freq == null ? 1 : freq + 1));
}
This code demonstrates the new for-each syntax, autoboxing and autounboxing.

The loop reads almost as written: "For each string word in the args array..." The locally scoped variable word will be assigned each element in the args array on each pass through the loop. No need to index the array. The for-each loop syntax works with all the Collections types, too, which Josh dubbed "syntactic polymorphism." No more writing iterators when all you want to do is loop through a collection from beginning to end.

If you need to access the iterator in the loop, you can still write the loop the old way. Like if you want to iterate through the elements in an array list:
for (Iterator i = myList.iterator(); i.hasNext(); ) {
// ...
}
Josh says there was some desire, for clarity, to use a new foreach keyword in the new loop syntax, and to use the word in instead of the colon. But adding keywords would guarantee existing code would break. (For instance, since you can't use a keyword as a variable name, not only would System.in be illegal, but how many in variables are in your code?)

Java 1.5 is completely backwards compatible . Rather than break backwards compatibility, Sun opted to go for the slightly less-readable syntax by using non-keywords like a colon and ellipse (for varargs, below).

Not only is the for-loop syntax new in the above code, look at the lines inside:
Integer freq = m.get(word);
m.put(word, (freq == null ? 1 : freq + 1));
The first line shows the power of generics. Since the Java Collections classes have been "generified" in JDK 1.5, and the code creates the map m by defining the key and value types, there is no need to cast m.get(word) to an Integer before assigning it to the Integer variable.

The second line shows autoboxing/unboxing in action.

Autoboxing is a fancy way of saying, "If you use a primitive type where only the object wrapper type is legal, automatically insert a constructor for the object wrapper type." That is, if you use an int where only an Integer object legal, the compiler will automatically insert new Integer([primitive value]) for you. Autounboxing is the opposite: If you use a primitive object wrapper type, such as Integer, where only the primitive type, like int, is legal, the compiler will automatically insert code to get the object's primitive value.

Note the definition: The compiler does the work. It will actually insert the bytecode into the .class file as if you wrote it. The objects still get created and the methods like Integer.intValue() are still called. The "auto" nature of boxing/unboxing just means you don't have to go through the chore of writing all that "obvious" code.

Speaking of clutter, here is the "old" way writing the above code.
Integer freq = (Integer) m.get(word);
m.put(
word,
freq == null ? new Integer(1) : new Integer(freq.intValue() + 1)
);
Hmm, I bet you're beginning to like this generics and autoboxing stuff.

Varargs

Although I think varargs will make some code clearer and easier, I don't see using them every day like I will the new for-each loop, generics and autoboxing.

Varargs will allow you to declare a method that takes a variable number of arguments. Josh and Neal's varargs example demonstrates a new varargs format method in the java.text.MessageFormat class:
public static String format(String pattern, Object ... arguments) {
// method body not shown
}
The ellipse is actually part of the Java language, not an indication I left some code out. With the above format method, you can now call it with a variable number of arguments, like:
String result = MessageFormat.format(
"At {1,time} on {1,date}, there was {2} on planet " +
"{0,number,integer}.",
7,
new Date(),
"a disturbance in the Force"
);
Java does the work for you of wrapping the arguments into an object array. Less coding for you. Less clutter. And, yes, C programmers rejoice: There is a new System.out.printf in Java 5 that had been missing from Java for nine years because of the inability to pass a variable number of arguments to a method.

As you can expect, the varargs parameter must be the last one in the method's parameter list, since all remaining parameters will get packaged into that varargs parameter in the method call.

Josh's advice: Don't override a varargs method. It could get confusing. Neal called varargs "kind of a dangerous language feature" because of the potential for making code harder to understand.

One nice feature I like in varargs: Instead of passing several arguments to fill out the "Object..." parameter, you can also just pass an object array. So if you already have your method params packed into an array, you can just pass it to the varargs method just as you would to a "simulated" varargs method today.

Other new features

You can read about the other new features, enums, static imports (blechh!) and annotations in Josh and Neal's presentation slides and in this J2SE 1.5 in a Nutshell article from Sun.

The static import feature looks like a way to keep bad programmers from saddling us with bad code by giving them a cleaner option.

On the other hand, I think the metadata/annotations feature will be powerful once XDoclet-like tools are available to process the metatags. For now, though, unless I'm writing a web service using Sun's WSDP, which will be able to understand and use JDK 5 meta tags in an upcoming release, or the upcoming Apache Beehive, which will require annotations, I'll continue to use XDoclet to pre-process my Java code and generate the boilerplate artifacts.

Are you ready to download the JDK 5 beta? The more-stable Beta 2 has been out for a while. Build 60 of the Beta 3 snapshot has been out for two weeks. Neal said the first JDK 5 release candidate should be out shortly.

Java Puzzlers

Josh Bloch and Neal Gafter's presentation on JDK 5 was actually their second presentation of the evening at the Denver Java Users Group.

The duo warmed up the crowd of more than 120 by quizzing us about the "sharp corners" of Java -- the ones that can catch you if you're careless. For this presentation, they billed themselves as Click and Hack, the Typeit Brothers. That's because they parody a slightly more famous duo during their Puzzler talk.

One of their puzzler questions: What does the following program print?
public class LongDivision {
private static final long MILLIS_PER_DAY
= 24 * 60 * 60 * 1000;
private static final long MICROS_PER_DAY
= 24 * 60 * 60 * 1000 * 1000;
public static void main(String[] args) {
System.out.println(MICROS_PER_DAY / MILLIS_PER_DAY);
}
}
I'll give you a hint: the answer is not 1000. To find out what it does print and why, you can download their puzzler presentation from our JUG website.

You can also read their puzzler book when it comes out next year. Josh and Neal are compiling their puzzlers into a book that will show you code that behaves in a way you wouldn't expect, then tell you the "moral" the code teaches us about Java coding. I like their primary moral for coding correctly:
"If you aren't sure what a program does,
it probably doesn't do what you want."
If you'd like to send them a Java puzzler for potential inclusion in their book, email them at "javapuzzlers at gmail.com". They'll give you credit in the book if they use your puzzler.

One thought on “New features in JDK 5

  1. This will pretty much be of limited use until we get a J2EE specification taking this features into account. I suppose Swing apps and selected libraries will take advantage of this, but as far as large applications are concerned, I don’t see an instant adoption of J2SE 5.0

Comments are closed.