What is a good use case for static import of methods?
This is from Sun's guide when they released the feature (emphasis in original):
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). ... 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.
(https://docs.oracle.com/javase/8/docs/technotes/guides/language/static-import.html)
There are two parts I want to call out specifically:
- Use static imports only when you were tempted to "abuse inheritance". In this case, would you have been tempted to have BusinessObject
extend some.package.DA
? If so, static imports may be a cleaner way of handling this. If you never would have dreamed of extendingsome.package.DA
, then this is probably a poor use of static imports. Don't use it just to save a few characters when typing. - Import individual members. Say
import static some.package.DA.save
instead ofDA.*
. That will make it much easier to find where this imported method is coming from.
Personally, I have used this language feature very rarely, and almost always only with constants or enums, never with methods. The trade-off, for me, is almost never worth it.
Are there any advantages of using static import over import?
The only difference between a normal import
and an import static
is that the latter is for moving static
members of some other class or interface — especially constants — into scope. It's up to you whether you use it; I like it because it keeps the body of the class shorter, but YMMV.
There are no performance benefits or penalties to using them (except possibly when compiling, as if you care about that) as they compile into identical bytecode.
Is import static a good practice?
Depends on the context, not exist an explicit rule to use in all the cases. But the most common use is when you do a test and need to import classes like Assert.* or Mockito.*, in order to no-repeat Assertion.assertEquals a lot of times a good idea is to do something like this:
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertAll;
import static org.junit.jupiter.api.Assertions.assertEquals;
class ErrorsControllerImplTest {
@Test
void should_return_all_the_errors_types() {
ErrorsController controller = new ErrorsControllerImpl();
assertAll(
() -> assertEquals(58, controller.getAllErrors().size()),
() -> assertEquals("BadRequestStatus {code=4000509, message='Site must have a value'}",
controller.getAllErrors().get(0)));
}
}
As another user said, the idea is that the code will be readable and remove duplicates parts.
Should I use static import?
As the docs say, use it sparingly. Look there for the justifications.
When to use static methods
One rule-of-thumb: ask yourself "Does it make sense to call this method, even if no object has been constructed yet?" If so, it should definitely be static.
So in a class Car
you might have a method:
double convertMpgToKpl(double mpg)
...which would be static, because one might want to know what 35mpg converts to, even if nobody has ever built a Car
. But this method (which sets the efficiency of one particular Car
):
void setMileage(double mpg)
...can't be static since it's inconceivable to call the method before any Car
has been constructed.
(By the way, the converse isn't always true: you might sometimes have a method which involves two Car
objects, and still want it to be static. E.g.:
Car theMoreEfficientOf(Car c1, Car c2)
Although this could be converted to a non-static version, some would argue that since there isn't a "privileged" choice of which Car
is more important, you shouldn't force a caller to choose one Car
as the object you'll invoke the method on. This situation accounts for a fairly small fraction of all static methods, though.
Java static imports
The explanation is simple although it doesn't change the fact that the behavior is highly unintuitive:
When resolving the method to be invoked the first thing the compiler does is find the smallest enclosing scope that has a method of the right name. Only then come other things like overload resolution and co in game.
Now what is happening here is that the smallest enclosing scope that contains a toString()
method is class A which inherits it from Object
. Hence we stop there and don't search farther. Sadly next the compiler tries to find the best fit of the methods in the given scope and notices that it can't call any of those and gives an error.
Which means never statically import methods with a name that is identical to a method in Object, because methods that are naturally in scope take precedence over static imports (the JLS describes method shadowing in detail, but for this problem I think it's much simpler to just remember that).
Edit: @alf kindly submitted the right part of the JLS that describes the method invocation for those who want the whole picture. It's rather complex, but then the problem isn't simple either so that's to be expected.
Why are static imports of static methods with same names legal?
The ambiguity of the static imports of methods could be resolved at the point of the method invocation.
For example if you had a static import for two methods that look like this:
void frobnicate(int i);
// and
void frobnicate(boolean b);
Then you could import and use both, because the compiler could tell which one to use, based on the arguments you pass in (frobnicate(1)
calls the first one, frobnicate(true)
calls the second one).
With classes, that's not possible: Foobar a;
alone is not sufficient to tell you which of the two Foobar
classes you want.
Also note that a single static import can import multiple names. According to the relevant section of the JLS (emphasis mine):
A single-static-import declaration imports all accessible static members with a given simple name from a type.
For example if the two frobnicate
methods above where located in the same class, a single static
import could import them both.
Related Topics
Determining If an Object Is of Primitive Type
What Is an Object's Hash Code If Hashcode() Is Not Overridden
How to Convert Currenttimemillis to a Date in Java
Casting Object Array to Integer Array Error
Why Does the Behavior of the Integer Constant Pool Change at 127
Gson Serialize a List of Polymorphic Objects
Does the Jvm Prevent Tail Call Optimizations
How to Retrieve Element Value of Xml Using Java
How to Create an .Exe for a Java Program
Java:If a Extends B and B Extends Object, Is That Multiple Inheritance
Java: Ternary with No Return. (For Method Calling)
How to Execute System Commands (Linux/Bsd) Using Java
How to Bundle a Native Library and a Jni Library Inside a Jar
Convert Float to String and String to Float in Java
What Does the Question Mark in Java Generics' Type Parameter Mean
Which Cipher Suites to Enable for Ssl Socket
Jsp - What Is Wrong with Scriptlets, and What to Use Instead