Are Static Imports Becoming Increasingly Accepted in Java?
The J2SE 5 Programming Language Guide‘s section on Static Imports is famously quoted (emphasis is part of original): “So when should you use static import? Very sparingly!” The section’s final paragraph describes when static import might be preferable:
So when should you use static import? Very sparingly! Only use it when you’d otherwise be tempted to declare local copies of constants, or to abuse inheritance (the Constant Interface Antipattern). In other words, use it when you require frequent access to static members from one or two classes. If you overuse the static import feature, it can make your program unreadable and unmaintainable, polluting its namespace with all the static members you import. Readers of your code (including you, a few months after you wrote it) will not know which class a static member comes from. Importing all of the static members from a class can be particularly harmful to readability; if you need only one or two members, import them individually. Used appropriately, static import can make your program more readable, by removing the boilerplate of repetition of class names.
Like the word “ain’t,” the educated Java developer masses seem to be almost universally in agreement that the static import should be used sparingly. The reasoning here is obvious. First, the official documentation says so. Second, and far more importantly, there is no question that overuse of static import might actually lead to less readable code even if it’s more concise code. In fact, too much static importing might lead to collisions that will remove the ability to use static imports so much. Despite awareness and acknowledgement of the evils and potential abuses of the static import, its use seems to be growing in the Java community.
When writing simple examples to illustrate points (such as for posts on this blog), I frequently don’t bother using a logging framework and instead resort to simple use of System.out and System.err. I don’t mind making the assumption that any reference to out
in my code refers to the handle to the standard output and that any reference to err
refers to the handle to the standard error. I don’t plan to use out
or err
in any other context, so this brings conciseness to the simple code without loss of readability or adding of ambiguity. It also feels very much like Groovy’s approach (although not quite as concise as that) to writing to standard output. You can find more details on this approach in Java static import: System.out and err, in my post Static Imports and System.out, and in Cay Horstmann‘s post Are you using static import?
Perhaps even more prevalent use of static import in the Java world occurs in the name of unit testing. Several of the most popular Java-oriented unit testing frameworks encourage use of static imports for more fluent test code. JUnit‘s Assert methods, Mockito‘s Mockito methods, and Hamcrest‘s Matchers are some of the most obvious examples of the prevalence of static import usage in the Java unit testing world.
In the post My dislike of Java’s static import, Mark Needham described a situation I think many Java development shops find themselves in when it comes to static imports:
On my last project we ended up saying that import static was allowed in test code because there were relatively few places the static methods could be imported from, but when it came to production code the fully qualified path was required.
Even use of static imports in test code is not without issue or controversy. The StackOverflow thread Finding import static statements for Mockito constructs talks about some frustrations related to the use of static imports. Needham also addressed this issue:
The benefit of this approach is that it makes the code read more fluently but the disadvantage is that you can’t immediately tell where a method lives. I want to be able to tell what is going on in the code from looking at it and anything which prevents this is a hindrance.
So far, I’ve looked at use of Java static imports in association with calls to java.lang.System.out
and in association with unit testing. Both of these cases are not typical production code cases (logging with a logging framework is preferable in production to standard output and unit tests are not production code, though they may be delivered with it).
It is perhaps less obvious which Java frameworks intended for production code encourage use of static imports. One example is lambdaj. The lambdaj features Wiki page starts off by recommending use of static imports: All those features are provided as static methods in the class Lambda, so the best way to use them is just to add the following import:
import static ch.lambdaj.Lambda.*;
in the classes where you want to use it.
The more general use case for Java use of static import is the development of Domain-Specific Languages (DSLs) in Java. In many ways, the use of static imports already discussed in this post for JUnit, Mockito, Hamcrest, and Lambdaj are specific examples of this more general trend toward fluent interfaces and DSLs.
For good reason, I believe that most Java developers are cautious about overuse and abuse of static imports. However, increased use of static imports in appropriate circumstances seems to be the result of playing with these and learning the positives and negatives of them. The rise of the JVM scripting languages and other more concise (less ceremony) languages has also probably affected the general thinking about use of static imports.
The drive for fluent interfaces (positive effect of static imports) must be compared to the maintenance and readability costs associated with use of static imports. In general, just as I think “ain’t” is still generally frowned upon but is perhaps less frowned upon than it used to be, I also think that static imports are still generally discouraged, but that perhaps we as a Java community have started to see situations in which they might be okay or even a positive feature worth their cost. I don’t think anyone thinks it’s a good idea to use them frequently and without regard to the context in which they are being used.
Reference: Are Static Imports Becoming Increasingly Accepted in Java? from our JCG partner Dustin Marx at the Inspired by Actual Events blog.
I haven’t thought about using static imports for the System.out and System.err fields, but I think this is a very good idea!
Also I think statically importing functions from the Math class like sin and cos makes the code much more readable and probably every developer knows where these functions live…