Why Is Using a Wild Card With a Java Import Statement Bad

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

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.

Performance difference between a wild card import and the required class import

At runtime 0.

Both generate the same byte code

Is it better to import specific packages or a whole tree with wildcards in java?

Also, you can't include a whole tree. You can cut down your import list to

import java.util.Calendar;
import java.util.logging.*;

but

import java.util.*;

does not import anything in the java.util.logging package. For the Java compiler, there are no subpackages. Also not for the VM (apart from some classloaders which use the package structure as a file directory structure).


Also, it seems you are mixing the concepts package and class/interface (or type). java.util and java.util.logging are packages, while java.util.Calendar, java.util.logging.Level etc. are classes.

A type (class/interface) is something you can use in your programm, while a package is mainly only a name space in which to put classes and interfaces. (Additionally, it has some consequences on visibility.)

You can import either single types (by specifying their name) or all types directly in a package (by specifying the package and .*). (You can also import all nested types in a type by using a wildcard, or import all static methods/fields of a class with import static <class>.*, just for completeness).

Importing is never recursive, wildcard importing is only for one level. (And you also can't use import java.util.*.* to import the logging classes.)

Implications importing java packages with wildcard

Absolutely no effect on run time.

Wildcard imports are probably marginally slower at compile-time, but I wouldn't think you'd need to care.

Is it a bad practice to import all the sub classes of a class at a time?

To be specific, what exactly is the difference between import java.applet.*; & import java.*;

The first import makes all types (classes, interfaces, enums) from the java.applet package visible to the compiler, while the second makes all types from the java package visible.

Note that there is no "subclass" relationship between packages - packages make up a package hierarchy, but not a class hierarchy. With a wildcard import (import package.*), all types from one single package are imported, not from a whole package hierarchy. In particular, import java.* does not import java.applet or any other package below java in addition.

In practice, by the way, you should avoid wildcard imports at all as they pollute your name space and might cause naming conflicts when identical type names exist in different packages. Most IDEs today organize the imports (semi-)automatically, so there is no need to use the wildcard import.

IntelliJ: Never use wildcard imports

It's obvious why you'd want to disable this: To force IntelliJ to include each and every import individually. It makes it easier for people to figure out exactly where classes you're using come from.

Click on the Settings "wrench" icon on the toolbar, open "Imports" under "Code Style", and check the "Use single class import" selection. You can also completely remove entries under "Packages to use import with *", or specify a threshold value that only uses the "*" when the individual classes from a package exceeds that threshold.

Update: in IDEA 13 "Use single class import" does not prevent wildcard imports. The solution is to go to Preferences ( + , on macOS / Ctrl + Alt + S on Windows and Linux) > Editor > Code Style > Java > Imports tab set Class count to use import with '*' and Names count to use static import with '*' to a higher value. Any value over 99 seems to work fine.

Does an import wildcard import everything all the time?

Be clear about what import is doing. It does NOT mean loading .class files and byte code.

All import does is allow you to save typing by using short class names.

So if you use java.sql.PreparedStatement in your code, you get to use PreparedStatement when you import java.sql.PreparedStatement. You can write Java code forever without using a single import statement. You'll just have to spell out all the fully-resolved class names.

And the class loader will still bring in byte code from .class files on first use at runtime.

It saves you keystrokes. That's all.

It has nothing to do with class loading.

Personally, I prefer to avoid the * notation. I spell each and every import out. I think it documents my intent better. My IDE is IntelliJ, so I ask it to insert imports on the fly.

Laziness is usually a virtue for developers, but not in this case. Spell them out and have your IDE insert them for you individually.

if you type

import java.util.*;

you'll get to refer to Scanner and List by their short names.

But if you want to do the same for FutureTask and LinkedBlockingQueue you'll have to have this:

import java.util.concurrent.*;

Java import wildcard not importing everything inside package

Here is the definition of type-import-on-demand in the Java Language Specification:

A type-import-on-demand declaration allows all accessible types of a
named package or type to be imported as needed.

TypeImportOnDemandDeclaration: import PackageOrTypeName . * ;

It is important to understand the terminology: "all accessible types of a named package" means all the types whose package declaration is specifically the one before the .*.

So, if a class's package is defined like:

package my.pkg.name;

Then it will be available to import my.pkg.name.*, but if a class is defined like:

package my.pkg.name.subname;

Then it will not be available to import my.pkg.name.*, because it does not belong to that package. It specifically belongs to my.pkg.name.subname which is - as far as Java is concerned - a different package.

It is true that Java implementations normally expect the packages to be ordered in a directory hierarchy, so the directory for my.pkg.name.subname is going to be under the directory of my.pkg.name. If you think of it, supposed you wrote

ls my/pkg/name/*

In that directory. It behaves very much the same: it would give you only the files under this directory directly, not the directories further under it. The semantics of type-import-on-demand is pretty much the same (excluding the subname "directory" itself, because it is not a type).



Related Topics



Leave a reply



Submit