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

18

595

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?

Sherri answered 29/9, 2008 at 3:55 Comment(0)
R
724

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 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.

Roxie answered 29/9, 2008 at 3:58 Comment(6)
It is the first scenario that will happen. The compiler notices that there are two Event classes and gives an error.Daria
Make sure to check my comment below -- there's a bigger issue with types being added to third-party libs over time. You can have compiling code that stops compiling after someone adds a type to a jar you depend upon.Foveola
regarding issue 1: technically, you can compile, but you'll have to use the fully qualified class name each time.Exculpate
You can resolve these kind of conflicts without listing every class explicitly, which causes problems of its own.Abomb
I am suprised that this answer was accepted and has 500+ votes. Literally when compilers find things for you, it is a good thing, not a bad thing. I have still not seen one argument about asterisk imports which meets daily developer ground truth needs, and is not a matter of Checkstyle authoritarianism.Ladykiller
To all those saying a class added in the future, may break.. - please start writing test cases for your code. I vote for more than 2 => wildcard for developer sanity!Taluk
C
257

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;
Crippen answered 29/9, 2008 at 15:45 Comment(17)
I agree. Although I would not be opposed to use explicit imports, I still prefer to use star imports. They emphasize that the "unit of reuse" is the whole package, not its individual types. The reasons others listed against star imports are weak, and in my experience using star imports has never caused any actual difficulties.Sacrosanct
See javadude.com/articles/importondemandisevil.html for details why it's evil. Basic idea: it can cause code to stop compiling when classes are added to packages that you import (like when List was added to java.util...)Foveola
Solid configuration management and continuous integration can solve this problem trivially, and you don't have explicit classnames littering your code. I agree it's poor language design, but it's dead simple to work aroundCrippen
All the problems you mention can be solved by modern IDEs (hiding imports, refactoring class name, etc...).N
I shouldn't have to use an IDE to read or write source code - code should be readable on its own without special tools unless the language is incredibly braindead. IN this case, Java works great - just use star imports. There's no reason not to.Crippen
There is a productivity gain for static star imports. It is convenient to just type 'assertTrue' etc. My IDE is configured with checkstyle rules for my job which bans them. Adding a static import then requires conversion of an existing import (manual or via shortcut). At that point I can either manually change the import to a star (must change back later) or repeat the above process for all other methods / constants / enums I'm using. This is a minor but real disruption. List was unfortunate; I have never run into this or a similar issue. Thanks for the heads up.Submergible
@Crippen You don't have to use an IDE to read or write source code. All decent text editors also support folding.Gardner
Even Uncle Bob recommends doing package imports in his Clean Code book. It's a good enough reason for me to use them.Biodynamics
@Crippen If your code contains 10+ wildcard imports, and you use class Foo, and if I read your code without using an IDE (since your argument is that I shouldn't have to use one), how will I know which package Foo came from? Sure, using an IDE, the IDE will tell me, but your entire argument is that I should be able to read the code without one. Doing explicit imports help document the code (great reason to avoid wildcards), and it's a lot more likely that I'll be reading the code without using an IDE, than that I'll be writing the code without using an IDE.Gyrfalcon
Answer: "An import statement is intended to import a package, not a class." My IDE: [Java] Only a type can be imported. org.springframework.stereotype resolves to a packageMallette
If you've got a hundred imports, chances are your class is way too big and probably responsible for way more than one thing. The problem here wouldn't be the imports, but wrotten code. You should dispose of wrotten stuff instead of making in pretty by shaping it like a flower. ;)Hathaway
@Crippen You've invalidated your own argument. To make the code "readable on its own without special tools" you must have fully qualified imports. Using wildcard imports you have no idea where a class is coming from without searching through packages or using the IDEs hover help.Thuggee
Sometime back I was a maintenance programmer. I often had read the code on Github or vi. The problem with start imports is, it's very difficult to find where that certain class is coming from. The worst way was to search entire repository or do grep, both seem overkill. I wished people didn't use * imports. And now I don't irrespective whether it says so in "Clean Code".Mathieu
@GaneshSatpute So you just proved that you shouldn't use GitHub or vi for browsing repositories. I think the rule that 'you shouldn't use special tools to read code' is not good. We are professionals, we should use optimal (if not the best) tools possible, not the other way.Palisade
@Palisade I surely didn't prove anything. I still use vi, Github as well as modern IDEs. I try to be open-minded, I won't consider somebody "non-professional" because he uses vi or Github to show somebody a code, or quickly look at the implementation rather than cloning repository and setting up locally.Mathieu
Personally, I use star imports cos I find it cleaner. Practically, I experienced no major problems.Dexamyl
If you remove or rename a class, you're going to have to modify the file that imports and uses that class regardless of whether you need to update the import itself, anyway. I don't really see how the wildcard import fixes this. If you import something but aren't using it, you shouldn't leave the import statement either way.Gervase
F
234

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.

Foveola answered 29/9, 2008 at 19:42 Comment(23)
This is not a valid excuse. If you're changing java version you somehow expect some things to fail, same thing if you change the version of a binary your code uses. In these cases the code would throw a compile error and it's trivial to fix (see the previous answer: https://mcmap.net/q/64291/-why-is-using-a-wild-card-with-a-java-import-statement-bad)Conchaconchie
@PabloFernandez - Nope - If I check out code that's been in a repository for a year, it should still compile. Import-on-demand can easily fail when new classes are added to existing packages that I've imported. It's not just a problem when upgrading Java versions. Also - if an API is designed well, it should never break existing code on upgrade. The only time I needed to change code when upgrading java versions was because of import-on-demand and when Sun pulled the XML APIs into the java runtime.Foveola
I'm making a big deal of a language feature that causes once-compiling code to stop compiling when you add something to the class path. Very big problem, especially when a maintainer picks up code that they didn't write - how do they know the intent without studying the code for a while - code that used to compile and work perfectly... Why should they have to change it just because a new jar was added to the compilation path or the JDK is upgraded?Foveola
The classpath is a fundamental component of the compilation process. If you think that changing the classpath arbitrarily will have no effect on your once-compiling-code then you're being naive to say the least.Conchaconchie
ADDING a class (with a unique, fully-qualified name!) to the classpath shouldn't affect anything. The point here is that if you do_not use import-on-demand syntax, it won't. So don't use the bad syntax that the language unfortunately allows and this is one less very real problem you can get hit with.Foveola
The point of my answer is that it's an unnecessary language feature that causes problems. Many IDEs/editors automatically handle import expansion. Use fully-qualified imports and there's no chance of this particular error happening. I've been hit by this one when under pressure to fix a bug in existing code, and you really don't need something like this as a distraction from the real task at hand. java.util.List vs java.awt.List isn't too bad to figure out, but try it when the class name is Configuration and multiple dependency libraries have added it in their latest maven repo version.Foveola
In Scott's article, he asserts that had Sun created java.util.collections.List instead of java.util.List there would have not been a conflict with java.awt.List. Why is that?Tobacco
@SheldonR., because if they had invented a new package (java.util.collections) for List there would have been no risk for legacy code to import it by mistake.Verisimilitude
@Verisimilitude Wouldn't java.util.collections be picked up by java.util.*?Tobacco
@Verisimilitude Packages in Java are just unique names. They may look like nested names due to common prefixes, but they never have any relation to other packages. (Note that they happen to share common parent directory structures, but that's just an environment convenience and not anything to do with the language definition...)Foveola
Note that specific imports take precedence over wildcard imports. import java.awt.*; import java.util.*; import java.util.List; suffices to disambiguate the unqualified List. This is much cleaner than naming every class.Compassion
@Compassion Having any wildcard imports put you at risk of code not compiling when you add a new third-party dependency or upgrade to a later Java version. With the IDEs available, you can always fold the import list to to not look at itFoveola
@ScottStanchfield Upgrading will often cause minor headaches, but the chance of an upgrade causing a previously unambiguous name to become ambiguous is pretty rare, to the point of not being worth worrying about.Compassion
And, in my opinion, "readable in an IDE" isn't good enough. Code should be easily readable in any plain-text editor, even those that don't perform folding of imports or code.Compassion
@Compassion - The issue is between readability in editors that don't support folding (I'd posit not the majority of those used) and a huge potential for compiler errors being introduced by library changes. I've seen this potential realized many times (the earliest and most heinous being List in java.util.* and java.awt.*) because developers use import-on-demand, and it most often impacts the person maintaining the code a year or more later, which burdens them at the cost of your weak editor's readability. Don't burden your maintainers. And get a better editor.Foveola
"There is NO reason that code should stop compiling just because a type is added to a package" - this can also be a problem, when an enum was extended with a new type.Bendite
In any case, the compiled application will continue to work under newer editions of Java regardless of how you imported. It's the build process that breaks, but not the application. When upgrading to a new version of the Java SDK, your build tools will let you know you have a problem. There are many reasons a SDK upgrade can go wrong, and this is just one of them. Ultimately, using explicit imports can save you time, but using wildcards is not inherently evil if you are aware of this.Cypher
Also reaching back to Java 1.1 -> Java 1.2 as an example is not valid. That was a MAJOR paradigm change and a ton of existing Java code broke during that transition.Cypher
@PaulCunningham It's the classic example (and perfectly valid) of this problem than can happen at any version of the Java language. The problem has only gotten worse over time with the availability of more and more third-party libraries, all of which may add new classes that may have the same name as a class in another library.Foveola
The ones saying it's not valid have never had to merge two code bases with similar-sounding domain names and a bunch of wildcards included. The conflicts were nightmares.Simony
@Simony Excellent point, especially if devs on either separate codebase are no longer around.Foveola
@ScottStanchfield It's interesting what do you think about openjdk.org/jeps/476... This JEP has the same problem, doesn't it? P.S. Actually, I 100% agree with you that * imports are evil.Retroversion
@RuslanStelmachenko - ooof! That's horrible.Foveola
B
89

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.

Barbule answered 2/1, 2010 at 20:17 Comment(5)
I'd suggest to Robert C. Martin to use better patterns to create more concise packages and classes of his own that don't require 80 lines of imports. That many classes needed for import inside a single class is just begging 'Entropy, Entropy, break me please...' and points the reason to avoid import *'s outlined in Scott Stanchfields anwersMelinite
As much as I generally love what Uncle Bob has to say, in this case I also have to disagree with him.Circum
Long lists of imports are daunting to the reader. -- This assertion has an invalid presumption. Programmers are not required to read source code from top to bottom. We may not read import lists at all. When we do, we might read only one of the imports, for clarification. At other times, the imports may be collapsed entirely, if we're working in an IDE. Regardless of the source, today this is now bad advice.Exarch
Just to provide some counterweight when in comes to citing authorities on this issue: The Google Java Style Guide as well as Twitter's Java Style Guide (which is largely based on the Google one, to be fair) specifically forbid wildcard imports. But they don't provide any rationale for this decision.Sprout
Probably the only point I didn't agree in Clean Code. It's having to scroll through few lines of import statements or struggling to find where the class is coming from. I prefer to be easily identifying where a certain class is coming from.Mathieu
A
36

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.

Artiodactyl answered 6/5, 2014 at 18:21 Comment(4)
import java.* imports nothing. Why would it make a difference?Liver
It makes a difference because it gets searched during compilation.Chump
I feel like this comparison isn't congruent with the question because it compares nothing with a wildcard import. I'd be curious what the compilation time difference is when importing a class via wildcard vs. specifically. And since the compiler "searches" the package for a wildcard, I'm guessing that the time difference varies based on the package size and how many classes from that same package are imported.Pentylenetetrazol
If the imported module is large or contains many symbols, this can increase the memory footprint of program because it loads and stores all the imported symbols, even if it is not used, which can lead to unnecessary memory consumption.Collar
I
28

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.

Incinerator answered 29/9, 2008 at 4:5 Comment(0)
M
27
  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.

Marylouisemaryly answered 29/9, 2008 at 4:42 Comment(2)
I like most of your points, but it was #4 specifically that got me to upvote your answer. Modern IDEs remove most arguments against using explicit imports...Tobacco
Maybe part of the problem here is the way the standard java libraries are laid out with many classes within the same package. As opposed to applying more of a 'single responibility principle' to a package.Chump
O
12

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.)

Obbligato answered 29/9, 2008 at 3:59 Comment(0)
J
11

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.

Jovita answered 17/6, 2016 at 8:54 Comment(0)
M
10

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.

Mince answered 10/10, 2008 at 15:57 Comment(1)
Must have been a lot of import lines or a really pathetic development system for this to be true. I use import-* an I can compile my entire codebase of 2107 classes in under 2 minutes.Mali
A
5

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;
      }
    
Aloes answered 11/10, 2020 at 9:55 Comment(0)
E
3

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

Exudate answered 20/9, 2016 at 17:27 Comment(1)
tip: you could've used Stream as an example of a new class added in Java in java.util in Java 8...Fluoridate
H
2

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.

Hybridize answered 21/12, 2017 at 0:25 Comment(4)
If you take that to its full logical conclusion then your style should be to not use imports at all and instead of "new LinkedList" always use "new java.util.LinkedList" and do this consistently everywhere.Longmire
Oh, come one. Who looks at the import for that information?!Protostele
@Protostele I think this used to be more important before IDEs supported direct navigation to types, for example.Aryl
I think it has been at least 2 decades that we have direct navigation from IDE'sProtostele
D
2

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).

Decani answered 7/2, 2019 at 11:44 Comment(1)
Agree. The motivator isn't so much performance or compilation, but human readability of your code. Just imagine you're reading code without an IDE - on GitHub, for example. Suddenly looking up every reference not defined in the file you're reading becomes mind-numbingly tedious.Androw
C
1
  • 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.

Candidacandidacy answered 18/3, 2018 at 5:29 Comment(2)
In IntelliJ, it is not a mandatory feature and it can be turned off.Oleo
Java had wildcard imports since JDK 1.0.2, it did not introduce the feature after C#. It was C# that copied much of Java. How is Java "tricky" anyway?Callen
A
1

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.

Androw answered 3/10, 2020 at 18:20 Comment(0)
C
0

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

If you're using an IDE (which you should be doing), and there are more code owners than just you, using wildcard imports is bad because it:

  • conceals information from the rest of the team
  • provides only false benefits (things which are better-solved using IDE functionality than with wildcard imports) to you as an individual

Most of the "use wildcards" proponents have a focus on the individual: I don't want to maintain the list, I don't want see the clutter, etc. Here are several of the common examples:

  • maintenance is harder – when you want to introduce a new class into your source code, you have to manually add the import statement
  • refactoring is more difficult – if code is moved around, then import statements have to be updated
  • reduce clutter, tidy up file contents – goal here is something along the lines of "removing distractions"

These arguments were more convincing before IDEs did all of that automatically. If you're using a plain text editor instead of an IDE, then these arguments have some merit. But if you're using a plain text editor, you are already subjecting yourself to a number of other much more significant inefficiencies, and managing import statements is just one among many things that you should stop doing by hand. IDEs offer automatic management of imports, powerful refactoring tools, and folding (hiding) of any parts of the code you don't want to see.

For the "avoid wildcards" proponents, there are many examples, but I'll point out only one:

  • clarity – specifically, when someone new enters the codebase. They will arrive with questions, and continue to discover new questions as they explore the code. For this new code contributor, wildcard import statements do not answer any questions, and at worst can produce confusion, misunderstanding, new questions. In contrast, with explicit imports (and using an IDE) the worst case is neutral: no new info provided; at best, it not only reduces ambiguity but it can also provide answers.

At the end of the day, it helps the entire team to reduce (albeit in a small way) code complexity, to reduce confusion, to add clarity.

Cosmorama answered 18/6, 2022 at 18:25 Comment(0)
O
-1

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.

Ombre answered 26/7, 2020 at 1:27 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.