Java Static Imports

A Look at Static Imports in Java

I was recently working a tutorial when I came across something a bit confusing.  The example code was calling methods that didn’t exist anywhere in the class without any qualifier.  Typically, tutorial code doesn’t show the imports, so I had to go digging around the associated GitHub code base to figure out what was going on.  The code in question was using static import and then calling methods on the statically imported classes as though the existed in the current class.

Static imports aren’t new.  They’ve existed in Java since Java 5 was released in 2004.  They allow a developer to access static methods without qualifying the class they come from.

There are two ways to use static imports: a single static import and an on-demand or en-masse import.

Here’s a quick illustration using a very common example usage: java.lang.Math.

This demonstrates a single static import.  It brings in just the PI constant from java.lang.Math.  In the calculateArea method, PI is referenced as though it had been declared as a static variable in the class.

import static java.lang.Math.PI;

public class IndividualStaticImport {
   public double calculateArea(double radius) {
      return PI * (radius*radius);
   }
}

For the on-demand import, we use the .* to bring in all the members of the java.lang.Math class.  As you can see in the triangle area, we can access both the PI constant and the sin method without qualification.

import static java.lang.Math.*;

public class OnDemandStaticImport {
   public double calculateArea(double radius) {
      return PI * (radius*radius);
   }
 
   public double calculateTriangleArea(double sideA, double sideB, double angle) {
      double angleRadians = angle * PI/180;
      return (sideA*sideB*sin(angleRadians))/2;
   }
}

Prior to Java 5, developers had sometimes been using the Constant Interface Anti-Pattern.  There are even examples in Java Swing which people often point out in discussions about whether or not this is actually a Very Bad Thing to Do.  The Constant Interface Anti-Pattern will have an interface that defines some constants and then any classes that need those constants can just implement the interface and viola!  they have the constants.  The primary argument against this is that it allows implementation details in the public API.

Here’s an example of the Constant Interface Anti-Pattern.  First an interface is defined that creates constants.  Then that interface is implemented by a class doing the calculations.

public interface MathConstants {
   public static final double PI = Math.PI;
   public static final double E = Math.E;
}

public class ConstantInterfaceAntiPatternDemo implements MathConstants {
   public double calculateArea(double radius) {
      return PI * (radius * radius);
   }
}

 

Usage of static imports is controversial.  The Java documentation itself is frequently quoted where it says to use static imports “Very Sparingly.”  The biggest argument for limiting use of static imports is for code readability.  Others will argue that it can improve readability by reducing repetitive qualifiers.  During my research, I encountered a JavaWorld article from 2012 wondering if Static Imports were becoming more accepted.  One of the article’s arguments was that popular testing frameworks encourage the use of static imports.  With the release of Java 8, Mockito made changes to eliminate the need for static imports according to an article from JavaCodeGeeks.  Another point made was that a lot of popular uses, including unit tests, are not used in production code.  A common example given is using a static import of java.lang.System.out for printing lines in example code.  A production system would use a logging framework.  My opinion is that it’s probably not a great idea to get in the habit of doing things that shouldn’t be in production app.  Raise your hand if you’ve accidentally left ridiculous debugging messages in a production app…

After delving into this a bit further, I tend to agree with Java on the use sparingly suggestion.  Developers always have to use their own best judgement on what to make use of when writing an application.  Personally, I am inclined to avoid using it for method members because I think that is particularly confusing.  If I found myself accessing the same constant over and over, I would definitely consider it.  I would also probably add a comment at the first usage, explaining that it’s not qualified because of a static import.  I think this would be especially helpful in tutorial/blog examples where the imports are typically not included.

What do you think about static imports?

References:

Advertisements

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 )

Google photo

You are commenting using your Google 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 )

Connecting to %s