JSR 201 analysis

December 5, 2002 10:14 PM

Well, a few hours after writing about JSR-201, I thought I might expand on what I think about the features being proposed.

Enums

Good. The proposal basically creates a shorthand syntax for the Typesafe Enum pattern in Joshua Bloch's Effective Java, and allows you to use these enums directly inside switch statements.

I had a short discussion about this over the phone with a colleague, who was of the enduring opinion that switch statements are a Code Smell, and their use shouldn't be encouraged. I believe that switch still has its place: the choice between switching on the enumeration, and adding polymorphic behaviour to the enumerated type itself, really depends on proximity, and whether the enumerated type should know about the code being put inside it.

One point. Have the compiler issue a warning if you're doing a switch on an enum, and missed one of the possible enumerations.

Static import

Static import adds a behaviour to the import statement, allowing you to import the static methods and fields of a class. So if you statically import java.lang.Math, then you can call abs() instead of Math.abs(). The main target of this feature seems to be the annoyingly bad habit of some developers to import a pile of constants by implementing the interface that defines them.

This is nice syntactic sugar, but otherwise a pretty minor feature.

Auto-boxing/unboxing

This eliminates some of the difficulties inherent in having a distinction between primitive types and Objects. I ranted about this distinction earlier this year. Just to reiterate, I have no problem with there being such a distinction inside the JVM, I just believe it should never have been visible in the Java language itself. To the programmer, it's so much simpler if everything is an object.

Auto-boxing/unboxing seems to me to be a band-aid solution. The distinction still exists, it's just hidden under a layer of (still programmer-visible) conversion rules. Given that the biggest problems with primitives come from the interaction between “primitives aren't objects” and “Arrays aren't really objects either, sort of”, it will be interesting to see just how effectively this problem is made to go away. Will you finally be able to write a single method that can act on any type of array?

Stick a big “wait and see” on this one.

Enhanced for loop

Once again, this goes back to something I wrote about in Java Peeves. Java really needs a convenient, concise way to do closures (or blocks, for Smalltalkers). All we have now are anonymous inner classes, which are far too verbose for regular use, so closures are only ever used in Java when there is no possible alternative.

Foreach takes probably the most common use of Smalltalk blocks, the internal iterator, and creates a syntactic special-case for them. Once again, it's a band-aid solution. Foreach removes the annoying duplicated syntax for the simplest case, but it does nothing to give programmers the chance to remove duplication on the more complex cases. For example, here's an implementation of map over an array, using the three different syntaxes. Assume we have an array of ints, orig[], and we want to increment each value inside it.

Current Java:

int[] dest = new int[orig.length];
for (int i = 0; i < dest.length; i++) {
    dest[i] = orig[i] + 1;
}

With enhanced for, it's even clumsier:

int[] dest = new int[orig.length];
int count = 0;
for (int i : orig) {
    dest[count] = i;
    count++;
}

With blocks, we could just have an Arrays.map() function:

int[] dest = Arrays.map(orig, { int i : i + 1; });

Of course, the map() function would contain the same code as the first example, but the point would be you'd only ever have to write it once, ever. Blocks are a wonderful way to get rid of all sorts of code duplication that pops up all over the place in Java code.

I think my biggest problem with the enhanced for statement is that it's the one thing in JSR-201 that is a step away from the right thing, because it happens to be the most convenient way to match a piece of C# functionality. Once foreach is implemented, the precedent has been set: whenever the lack of blocks causes us to lag behind C#, don't fix the underlying problem, work around it with a variant on what we have already. That leaves me a little cold.

All in all, I'd love to see three quarters of JSR-201 implemented in Tiger.

Previously: When Reuse isn't.

Next: SOAPy Madness