A programmer's tale

Friday, August 11, 2006

Why static import in introduced in Java 1.5

First of all, what is static import?
Java 1.5 introduced brand new language features. Static import is one of them by which you can import statically the attributes or methods of a particular class such as:


import static com.roy.java.NumberConstants.*;


public class StaticImporter {

public static void main(String[] args) {
System.out.println(54321 * TENTH);
System.out.println(1000 * HUNDREDTH);
System.out.println(multiplyByTen(999));
}
}

TENTH, HUNDREDTH and multiplyByTen are all members of NumberConstants:

public final class NumberConstants {

public static final double TENTH = 0.1;
public static final double HUNDREDTH = 0.01;

public static long multiplyByTen(int n) {
return 10 * n;
}
}



Now why this feature is needed in new java release?
It can be revealed by just a bit of careful observation that the writing of the code is less with static import. Without static import you have to write the fully qualified name of attributes or methods to use such as:

public class Bits {

/**
* @param args
*/
public static void main(String[] args) {
int i = 105;
int j = 254;
int r = i & (i - 1);
System.out.println(Integer.toBinaryString(i));
System.out.println(Integer.toBinaryString(i-1));
System.out.println(Integer.toBinaryString(r));
}

}


But the is a subtle cause from the object oriented point of view behind this. We'll see that. To use constant attributes one old technique is "constant interface". Constant interface is an interface that only contains constant attributes in it, like:

public interface NumberConstants {

static final double TENTH = 0.1;
static final double HUNDREDTH = 0.01;
}


Now to use the constant attributes one just implements the above "constant interface":

public class Multiplyer implements NumberConstants {

public static int multiply(int number, int anotherNumber) {
return number * anotherNumber;
}

public static double divideByTen(double number) {
return number * TENTH;
}

}

This technique basically violates some object oriented paradigms. Suppose we only need the constant fields in a particular class. Now we implements the "constant interface" interface to use it and use these in this class. Further we extend our present class to write another class, but the inherited class no longer need the constants in it but we have these attributes as some extra unnecessary "garbage". If we have to do some calculation in our inherited class, then we are now prone to make mistake by incorporating the constant attributes in our class at hand. Let us see this:

public class TenMultiplyer extends Multiplyer {

private static final int TEN = 10;


public static double multiplyByTen(int number) {
return number * TENTH; // sholud be TEN
}
}


More over we are not actually implementing anything by implementing "constant interfaces", here the intention of an interface is violated. In "Effective Java Programming Guide" item 17, Joshua Bloch says that:

When a class implements an interface, the interface serves as a type that can be used to refer
to instances of the class. That a class implements an interface should therefore say something
about what a client can do with instances of the class. It is inappropriate to define an interface
for any other purpose.

So "constant interface" is a major violation of Object Oriented design. In early days it was not understood or realized fully, for this reason you can still see this pattern in Java SDK code, obviously it is legacy and for backward computability. If you don’t trust me then better to ask SUN. ;)
One other problem is that say, in future realize the implementation of the class do not need the constants any further, but to retain the binary compatibility you must have to implement the "constant interface".
Moreover if you are a good API designer and your export your API that involves the implementation of "constant interface" then your API user may confuse with these unwanted constant are it is also error-prone for the same reason said earlier.

The better way to represent the constants is to represent is as enum type, obviously if it is suited for it otherwise these can be declared and defined in a separate class more preferably in a final class.

If you put the constants in a separate class the you have to write more to use them in another class as mentioned earlier.

For all these reasons Java language designer introduced static import in java 5. You can easily see that the best use of it is for utility classes.