Why is using a wild card with a Java import statement bad?

JavaImportWildcard

Java Problem Overview


It is much more convenient and cleaner to use a single statement like

import java.awt.*;

than to import a bunch of individual classes

import java.awt.Panel;
import java.awt.Graphics;
import java.awt.Canvas;
...

What is wrong with using a wildcard in the import statement?

Java Solutions


Solution 1 - Java

The only problem with it is that it clutters your local namespace. For example, let's say that you're writing a Swing app, and so need java.awt.Event, and are also interfacing with the company's calendaring system, which has com.mycompany.calendar.Event. If you import both using the wildcard method, one of these three things happens:

  1. You have an outright naming conflict between java.awt.Event and com.mycompany.calendar.Event, and so you can't even compile.
  2. You actually manage only to import one (only one of your two imports does .*), but it's the wrong one, and you struggle to figure out why your code is claiming the type is wrong.
  3. When you compile your code there is no com.mycompany.calendar.Event, but when they later add one your previously valid code suddenly stops compiling.

The advantage of explicitly listing all imports is that I can tell at a glance which class you meant to use, which simply makes reading the code that much easier. If you're just doing a quick one-off thing, there's nothing explicitly wrong, but future maintainers will thank you for your clarity otherwise.

Solution 2 - Java

Here's a vote for star imports. An import statement is intended to import a package, not a class. It is much cleaner to import entire packages; the issues identified here (e.g. java.sql.Date vs java.util.Date) are easily remedied by other means, not really addressed by specific imports and certainly do not justify insanely pedantic imports on all classes. There is nothing more disconcerting than opening a source file and having to page through 100 import statements.

Doing specific imports makes refactoring more difficult; if you remove/rename a class, you need to remove all of its specific imports. If you switch an implementation to a different class in the same package, you have to go fix the imports. While these extra steps can be automated, they are really productivity hits for no real gain.

If Eclipse didn't do specific class imports by default, everyone would still be doing star imports. I'm sorry, but there's really no rational justification for doing specific imports.

Here's how to deal with class conflicts:

import java.sql.*;
import java.util.*;
import java.sql.Date;

Solution 3 - Java

Please see my article Import on Demand is Evil

In short, the biggest problem is that your code can break when a class is added to a package you import. For example:

import java.awt.*;
import java.util.*;

// ...

List list;

In Java 1.1, this was fine; List was found in java.awt and there was no conflict.

Now suppose you check in your perfectly working code, and a year later someone else brings it out to edit it, and is using Java 1.2.

Java 1.2 added an interface named List to java.util. BOOM! Conflict. The perfectly working code no longer works.

This is an EVIL language feature. There is NO reason that code should stop compiling just because a type is added to a package...

In addition, it makes it difficult for a reader to determine which "Foo" you're using.

Solution 4 - Java

It's not bad to use a wild card with a Java import statement.

In Clean Code, Robert C. Martin actually recommends using them to avoid long import lists.

Here is the recommendation:

> J1: Avoid Long Import Lists by Using > Wildcards > > If you use two or more classes from a > package, then import the whole package > with > > import package.*; > > > Long lists of imports are daunting to > the reader. We don’t want to clutter > up the tops of our modules with 80 > lines of imports. Rather we want the > imports to be a concise statement > about which packages we collaborate > with. > > Specific imports are hard > dependencies, whereas wildcard imports > are not. If you specifically import a > class, then that class must exist. But > if you import a package with a > wildcard, no particular classes need > to exist. The import statement simply > adds the package to the search path > when hunting for names. So no true > dependency is created by such imports, > and they therefore serve to keep our > modules less coupled. > > There are times when the long list of > specific imports can be useful. For > example, if you are dealing with > legacy code and you want to find out > what classes you need to build mocks > and stubs for, you can walk down the > list of specific imports to find out > the true qualified names of all those > classes and then put the appropriate > stubs in place. However, this use for > specific imports is very rare. > Furthermore, most modern IDEs will > allow you to convert the wildcarded > imports to a list of specific imports > with a single command. So even in the > legacy case it’s better to import > wildcards. > > Wildcard imports can sometimes cause > name conflicts and ambiguities. Two > classes with the same name, but in > different packages, will need to be > specifically imported, or at least > specifically qualified when used. This > can be a nuisance but is rare enough > that using wildcard imports is still > generally better than specific > imports.

Solution 5 - Java

Performance: No impact on performance as byte code is same. though it will lead to some compile overheads.

Compilation: on my personal machine, Compiling a blank class without importing anything takes 100 ms but same class when import java.* takes 170 ms.

Solution 6 - Java

It clutters your namespace, requiring you to fully specify any classnames that are ambiguous. The most common occurence of this is with:

import java.util.*;
import java.awt.*;

...
List blah; // Ambiguous, needs to be qualified.

It also helps make your dependencies concrete, as all of your dependencies are listed at the top of the file.

Solution 7 - Java

  1. It helps to identify classname conflicts: two classes in different packages that have the same name. This can be masked with the * import.
  2. It makes dependencies explicit, so that anyone who has to read your code later knows what you meant to import and what you didn't mean to import.
  3. It can make some compilation faster because the compiler doesn't have to search the whole package to identify depdencies, though this is usually not a huge deal with modern compilers.
  4. The inconvenient aspects of explicit imports are minimized with modern IDEs. Most IDEs allow you to collapse the import section so it's not in the way, automatically populate imports when needed, and automatically identify unused imports to help clean them up.

Most places I've worked that use any significant amount of Java make explicit imports part of the coding standard. I sometimes still use * for quick prototyping and then expand the import lists (some IDEs will do this for you as well) when productizing the code.

Solution 8 - Java

I prefer specific imports, because it allows me to see all the external references used in the file without looking at the whole file. (Yes, I know it won't necessarily show fully qualified references. But I avoid them whenever possible.)

Solution 9 - Java

In a previous project I found that changing from *-imports to specific imports reduced compilation time by half (from about 10 minutes to about 5 minutes). The *-import makes the compiler search each of the packages listed for a class matching the one you used. While this time can be small, it adds up for large projects.

A side affect of the *-import was that developers would copy and paste common import lines rather than think about what they needed.

Solution 10 - Java

In DDD book

> In whatever development technology the implementation will be based on, look for ways of minimizing the work of refactoring MODULES . In Java, there is no escape from importing into individual classes, but you can at least import entire packages at a time, reflecting the intention that packages are highly cohesive units while simultaneously reducing the effort of changing package names.

And if it clutters local namespace its not your fault - blame the size of the package.

Solution 11 - Java

  • There is no runtime impact, as compiler automatically replaces the * with concrete class names. If you decompile the .class file, you would never see import ...*.

  • C# always uses * (implicitly) as you can only using package name. You can never specify the class name at all. Java introduces the feature after c#. (Java is so tricky in many aspects but it's beyond this topic).

  • In Intellij Idea when you do "organize imports", it automatically replaces multiple imports of the same package with *. This is a mandantory feature as you can not turn it off (though you can increase the threshold).

  • The case listed by the accepted reply is not valid. Without * you still got the same issue. You need specify the pakcage name in your code no matter you use * or not.

Solution 12 - Java

Here are the few things that I found regarding this topic.

  • During compilation, the compiler tries to find classes that are used in the code from the .* import and the corresponding byte code will be generated by selecting the used classes from .* import. So the byte code of using .* import or .class names import will be same and the runtime performance will also be the same because of the same byte code.

  • In each compilation, the compiler has to scan all the classes of .* package to match the classes that are actually used in the code. So, code with .* import takes more time during the compilation process as compared to using .class name imports.

  • Using .* import helps to make code more cleaner

  • Using .* import can create ambiguity when we use two classes of the same name from two different packages. Eg, Date is available in both packages.

      import java.util.*;
      import java.sql.*;
      
      public class DateDemo {
          private Date utilDate;
          private Date sqlDate;
      }
    

Solution 13 - Java

The most important one is that importing java.awt.* can make your program incompatible with a future Java version:

Suppose that you have a class named "ABC", you're using JDK 8 and you import java.util.*. Now, suppose that Java 9 comes out, and it has a new class in package java.util that by coincidence also happens to be called "ABC". Your program now will not compile on Java 9, because the compiler doesn't know if with the name "ABC" you mean your own class or the new class in java.awt.

You won't have that problem when you import only those classes explicitly from java.awt that you actually use.

Resources:

Java Imports

Solution 14 - Java

Among all the valid points made on both sides I haven't found my main reason to avoid the wildcard: I like to be able to read the code and know directly what every class is, or if it's definition isn't in the language or the file, where to find it. If more than one package is imported with * I have to go search every one of them to find a class I don't recognize. Readability is supreme, and I agree code should not require an IDE for reading it.

Solution 15 - Java

For the record: When you add an import, you are also indicating your dependencies.

You could see quickly what are the dependencies of files (excluding classes of the same namespace).

Solution 16 - Java

Forget about cluttered namespaces... And consider the poor soul who has to read and understand your code on GitHub, in vi, Notepad++, or some other non-IDE text editor.

That person has to painstakingly look up every token that comes from one of the wildcards against all the classes and references in each wildcarded scope... just to figure out what in the heck is going on.

If you're writing code for the compiler only - and you know what you're doing - I'm sure there's no problem with wildcards.

But if other people - including future you - want to quickly make sense of a particular code file on one reading, then explicit references help a lot.

Solution 17 - Java

Importing all the classes in a package is considered a blind approach. A major reason for this is that it clutters the class namespace and could lead to conflicts between classes in different packages with the same name.

Specifically populating the necessary classes avoids that problem and clearly shows which versions were wanted. This is good for code maintainability.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionjnanchetaView Question on Stackoverflow
Solution 1 - JavaBenjamin PollackView Answer on Stackoverflow
Solution 2 - Javadavetron5000View Answer on Stackoverflow
Solution 3 - JavaScott StanchfieldView Answer on Stackoverflow
Solution 4 - JavahwiechersView Answer on Stackoverflow
Solution 5 - JavaVinish NainView Answer on Stackoverflow
Solution 6 - JavahazzenView Answer on Stackoverflow
Solution 7 - JavaJosh SegallView Answer on Stackoverflow
Solution 8 - JavaJeff CView Answer on Stackoverflow
Solution 9 - JavaMichael HallView Answer on Stackoverflow
Solution 10 - JavaIvanView Answer on Stackoverflow
Solution 11 - JavaLeonView Answer on Stackoverflow
Solution 12 - JavaMilan PaudyalView Answer on Stackoverflow
Solution 13 - JavaAfeeView Answer on Stackoverflow
Solution 14 - Javauser109439View Answer on Stackoverflow
Solution 15 - JavamagallanesView Answer on Stackoverflow
Solution 16 - JavaLeo OrientisView Answer on Stackoverflow
Solution 17 - JavaTestillaView Answer on Stackoverflow