Java’s new static imports

It seems that Kris has been lured toward the sirens that are the proposed JDK 1.5 static imports. I am convinced that static imports will reduce code clarity and therefore increase the bug rate. I offer a contrived example to demonstrate my position:

I am working on a class that staticly imports java.lang.Math to use sin() as well as a number of others functions. Due to the large overhead associated with sin() and the fact that my domain consists of only integral angles, I want to add my own sin() method to the class and switch to a pre-computed look up table of values.

According to the updated JLS:

A static-import-on-demand declaration never causes any other declaration to be shadowed.

That’s fine but it does create confusion on the order of that that would be caused by operator overloading (which is not in Java due in part to “added complexity” associated with it).

For the sake of this example, let’s say that java.lang.Math contains the following signatures:

public static float sin(float angle);
public static float sin(double angle);

(again, this is contrived to prove a point) and the signature that I added to my class is:

float sin(float angle);

The call to sin() resembles:

...
float angle;
...
rotated = PI * sin(angle);
...

In this exmaple, it may be easy to determine which sin() is being called, but in reality it is not. Somewhere along the way, I find a library that contains the signature of:

public static float sin(int angle);

that I want to staticly import. I can’t do it according to the JLS:

If two single-static-import declarations in the same compilation unit attempt to import members with the same simple name, then a compile-time error occurs, unless the two members are the same member of the same type, in which case the duplicate declaration is ignored.

So you hopefully see the mess that I’m in. I’ll attempt to illustrate to drive the point home.

import static java.lang.Math.*;
import com.someco.MathFunctions; // can't be static
private float sin(final float angle) { ... }
public class ContrivedExample {
...
float angle;
...
rotated = PI * sin(angle); // from local sin()
...
other = sin(angle / 1.5); // from java.lang.Math (1.5 is double)
...
uugh = MathFunctions.sin((int)(angle / 65535)); // from MathFunctions
...
}

That is a debuggers worst nightmare.

Of course placing strict coding constraints on how, when, where, and under what conditions static imports are used will help alleviate these problems but given a large set of imports, it might be easier said than done.

David Flanagan has also touched on some other issues — specifically, how one can import a method with the same name but different signatures.

Static imports “solves” something that was never a problem to begin with (i.e. explicit names are a good thing). A more suituable solution to this “problem” would be in-line (or horizontal) code folding; just as some IDE’s provide the ability to vertically fold various scopes, horizontal folding would fold the qualifier of the name.

Updated April 23 at 11:45AM

Advertisements

2 comments

  1. Horizontal code folding is a nifty idea, although it doesn’t help those of us who still use plain old text editors like in the good old days…But for an IDE to be able to this kind of code folding, it would have to have the equivalent of import static. So why not let the compiler play, too?
    There appears to be an error in your contrived example. You’ve declared the Math.sin() method to take and return a float, but I think you’re trying to distinguish it from your local sin() method by its argument type. I think you meant double there, which is the argument it actually takes.
    More to the point, though, this example is contrived. We could create contrived examples to demonstrate why ordinary type imports are also confusing and should not be used. I just don’t think this argument holds much weight. In the case shown here, the obvious fix is to explicitly qualify calls to Math.sin() with the “Math.” part even though the import static allows you to omit it. Another solution would be to omit the import static. And perhpas the best would be to avoid creating local methods whose name conflicst with an imported method. Your local sin() method should have a different name!
    Another problem that static imports are intended to solve is the practice of declaring shared constants in an interface and then implementing the interface just to get the constants. It is safer to declare the constants as static class memebers, and then use import static to import them into your namespace.
    Finally, I think you’ve cited my blog entry a little out of context. My main point was that you *can* import two static members of the same name from two separate classes, as long as they have different signatures. For example you can import the sort() methods from java.util.Collections and java.util.Arrays.
    And even when two classes have a static member with the same name and signature, you can still use import static to import the other members. You just have to type the explicit class name to disambiguate the ambiguous case.

  2. Thanks for the comment and pointing out the error(s). I have made an update to the original post to elimiate further confusion. You’re also right about mis representing your blog entry — I realized it after the fact but unfortunately didn’t have time (until now) to update it.
    I don’t wish to get into the constant interfaces argument (available from http://www.javaworld.com/weblogs/java101/archives/000156.html) other than to state my position: I’m against them for the same reasons as the static imports. Clarity = fewer bugs (less time to debug, etc). If I have to type out a type qualifier each time to enhance clarity (and therefore reduce the possibility of bugs) then that is what I will do as my job is to produce software with as few bugs as possible. Thankfully I have tools to facilitate me (e.g. IDE’s) in this endeavor.
    I will wrap up by stating that my position on starndard imports is parallel to that of the static imports: they DO create confusion and should be used only with a strict corresponding coding convention / style. How I have longed for the ability to “walk back down the package hierarchy” or have horizontal code folding when specifying fully qualified types to improve clarity and reduce the possibility of confusion.


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s