This question already has answers here:
Java import vs code performance
(5 answers)
Closed 9 years ago.
I have read that unlike C/C++, when we "import" packages they actually don't get added (they get referred instead of getting embedded) to the class file.
What are the performance implications because of this ?
I am curious about overhead (call outs to the referred packages ...etc) that may be incurred because the referred data (from the packages) are not available in the .class itself.
Or the overhead is extremely minimal ?
There are no performance hits. It only affects how the compiler resolves types; there are no impacts on the generated byte code or information available at runtime. It is almost exactly equivalent to using [namespace] in C++ (where packages are like namespaces).
Like C++, you can also fully qualify a type with its package instead of importing it.
C++:
Something::Whatever x = ...;
// or
using namespace Something;
Whatever x = ...;
Java:
com.something.Whatever x = ...;
// or
import com.something.*;
Whatever x = ...;
You can (and should) also import specific type:
C++:
using Something::Whatever;
Java:
import com.something.Whatever;
As with C++, classes in the same package can refer to each other without having to qualify the package name.
Note that, unlike C++ using namespace, import must be at the top of the file. Additionally, package names directly reflect the directory structure of the source relative to the classpath (path separators are replaced with dots); because classes can be dynamically loaded in Java, the package name also specifies where in the file system the class loader looks for the class.
Also, to pick nits, there is no such concept in C.
There is not a performance overhead cost of adding packages. But you should not simply import unnecessary packages in your code. Sometimes there are classes with the same name but in different packages, so you will run into unnecessary problems.
From good coding practice, use only what you need, nothing extra is good. So import classes instead of complete packages.
Almost all the IDEs comes with a feature to organize your imports, so you really don't need to remember the packages and complete path of classes. Simply utilize the IDE features and keep your code clean.
The Java classloader loads a class into memory only when it needs to. It does not load classes into memory after imports, see this answer. There are no "performance downsides" to this... when a class's bytecode needs to be accessed, the address in memory is almost certainly retrieved in constant time.
import does not have any performance overheads. At least the JLS doesn't mention that
An import declaration makes types or members available by their simple
names only within the compilation unit that actually contains the
import declaration
Related
In Java, imports are related to an (outer) class, as every (outer) class is supposed to be coded in a separate file. Thus, one could claim that the import ...; directives before a class definition are associated with the class (somewhat like annotations are).
Now, if one could inherit a parent class' imports, that would greatly reduce the clutter of source files. Why should this not be possible? i.e. why should the Java compiler not consider also the imports of base classes?
Notes:
There's probably more than one answer.
I know this is not much of an issue if you let eclipse organize your imports, no need to mention that. This is about the 'why', not the 'how' (a-la-this).
Firstly, it is important to note that not every class must be coded in a separate file - but rather that every public, top level class must be. And no, imports are not really associated with any class - they are just statements used to include certain external classes / packages within a file so that they can be used. In fact, you never need to actually import anything, you can always use the full name, i.e.:
java.util.List<String> list = new java.util.ArrayList<String>();
Imports are there for convenience (and only for the compiler - they are lost after the class is compiled), to save you from having to write all that out and instead only make you write List<String> list = new ArrayList<String> (after you make the relevant imports from java.util). Consequently, there is no reason why subclasses should 'inherit' imports.
Imports are syntactic sugar, nothing more. You could write any Java program without ever using an import statement if you really wanted to. For example, the following class compiles all by itself:
class Foo {
java.util.List<String> list = new java.util.ArrayList<String>();
}
Additionally, inheriting imports makes it much, much harder to remove an import from a class. For example, if Bar.java inherits from Foo.java, you might not be able to remove an import from Foo without adding it to Bar. Forcing imports to be explicit makes it significantly easier to change a single file without worrying about the effects on other files, which is pretty much a fundamental principle of Java and object-oriented programming generally.
(This last point is related to issues that were a significant factor in the design of Go, which was specifically attempting to avoid the problems with C and C++ in this area.)
Having each file explicitly specify its imports improves readability. Imagine opening a file and not being able to see the dependencies at a glance, because the imports are inherited from another file.
If one writes two public Java classes with the same case-insensitive name in different directories then both classes are not usable at runtime. (I tested this on Windows, Mac and Linux with several versions of the HotSpot JVM. I would not be surprised if there other JVMs where they are usable simultaneously.) For example, if I create a class named a and one named A like so:
// lowercase/src/testcase/a.java
package testcase;
public class a {
public static String myCase() {
return "lower";
}
}
// uppercase/src/testcase/A.java
package testcase;
public class A {
public static String myCase() {
return "upper";
}
}
Three eclipse projects containing the code above are available from my website.
If try I calling myCase on both classes like so:
System.out.println(A.myCase());
System.out.println(a.myCase());
The typechecker succeeds, but when I run the class file generate by the code directly above I get:
Exception in thread "main" java.lang.NoClassDefFoundError: testcase/A (wrong name: testcase/a)
In Java, names are in general case sensitive. Some file systems (e.g. Windows) are case insensitive, so I'm not surprised the above behavior happens, but it seems wrong. Unfortunately the Java specifications are oddly non-commital about which classes are visible. The Java Language Specification (JLS), Java SE 7 Edition (Section 6.6.1, page 166) says:
If a class or interface type is declared public, then it may be accessed by
any code, provided that the compilation unit (ยง7.3) in which it is declared is
observable.
In Section 7.3, the JLS defines observability of a compilation unit in extremely vague terms:
All the compilation units of the predefined package java and its subpackages lang
and io are always observable. For all other packages, the host system determines which compilation units are observable.
The Java Virtual Machine Specification is similarly vague (Section 5.3.1):
The following steps are used to load and thereby create the nonarray class or
interface C denoted by [binary name] N using the bootstrap class loader [...]
Otherwise, the Java virtual machine passes the argument N to an invocation of a
method on the bootstrap class loader to search for a purported representation of C
in a platform-dependent manner.
All of this leads to four questions in descending order of importance:
Are there any guarantees about which classes are loadable by the default class loader(s) in every JVM? In other words, can I implement a valid, but degenerate JVM, that won't load any classes except those in java.lang and java.io?
If there are any guarantees, does the behavior in the example above violate the guarantee (i.e. is the behavior a bug)?
Is there any way to make HotSpot load a and A simultaneously? Would writing a custom class loader work?
Are there any guarantees about which classes are loadable by the bootstrap class loader in every JVM?
The core bits and pieces of the language, plus supporting implementation classes. Not guaranteed to include any class that you write. (The normal JVM loads your classes in a separate classloader from the bootstrap one, and in fact the normal bootstrap loader loads its classes out of a JAR normally, as this makes for more efficient deployment than a big old directory structure full of classes.)
If there are any guarantees, does the behavior in the example above violate the guarantee (i.e. is the behavior a bug)?
Is there any way to make "standard" JVMs load a and A simultaneously? Would writing a custom class loader work?
Java loads classes by mapping the full name of the class into a filename that is then searched for on the classpath. Thus testcase.a goes to testcase/a.class and testcase.A goes to testcase/A.class. Some filesystems mix these things up, and may serve the other up when one is asked for. Others get it right (in particular, the variant of the ZIP format used in JAR files is fully case-sensitive and portable). There is nothing that Java can do about this (though an IDE could handle it for you by keeping the .class files away from the native FS, I don't know if any actually do and the JDK's javac most certainly isn't that smart).
However that's not the only point to note here: class files know internally what class they are talking about. The absence of the expected class from the file just means that the load fails, leading to the NoClassDefFoundError you received. What you got was a problem (a mis-deployment in at least some sense) that was detected and dealt with robustly. Theoretically, you could build a classloader that could handle such things by keeping searching, but why bother? Putting the class files inside a JAR will fix things far more robustly; those are handled correctly.
More generally, if you're running into this problem for real a lot, take to doing production builds on a Unix with a case-sensitive filesystem (a CI system like Jenkins is recommended) and find which developers are naming classes with just case differences and make them stop as it is very confusing!
Donal's fine explanation leaves little to add, but let me briefly muse on this phrase:
... Java classes with the same case-insensitive name ...
Names and Strings in general are never case-insensitive in themselves, it's only there interpretation that can be. And secondly, Java doesn't do such an interpretation.
So, a correct phrasing of what you had in mind would be:
... Java classes whose file representations in a case-insensitive file-system have identical names ...
I tried to add or remove a character from one of the class names and it worked. I feel it's always better to use different class names.
Don't think just about folders.
Use explicit different namespaces ("packages") for your classes, and maybe use folders to match your classes.
When I mention "packages", I don't mean "*.JAR" files, but, just the concept of:
package com.mycompany.mytool;
// "com.mycompany.mytool.MyClass"
public class MyClass
{
// ...
} // class MyClass
When you do not specify a package for your code, the java tools (compiler, I.D.E., whatever), assume to use the same global package for all. And, in case of several similar classes, they have a list of folders, where to look for.
Packages are like "virtual" folders in your code, and apply to all your packages on your classpath, or installation of Java. You can have several classes, with the same I.D., but, if they are in different package, and you specify which package to look for, you won't have any problem.
Just my 2 cents, for your cup of Java coffe
What is effected by redundant java import statements?
Do they effect the compiled runtime (performance/size)?
or just stuff like intellisense?
To ask differently:
how important is it to remove them?
Import statements only affect what happens during compile time.
The compiler takes this code, and creates a .class file that represents your code in an executable format (something in binary).
In the end, the binaries are exactly the same, but the method by which they are made are different.
Let's look at a simple case:
import java.util.*;
vs
import java.util.ArrayList;
import java.util.List;
when used in:
//...
List <String> someList = new ArrayList <String> ();
//...
When the compiler hits the word List, in the first case, it will need to figure out if List exists in that set of classes or not. In the second case, it is already given it explicitly, so its much easier.
In essence, what happens is the compiler must take all the classes existing in the import statements and keep track of their names so that, if you use it, the compiler can then retrieve the appropriate functions that you are calling.
Sometimes, there are classes that have the same name in multiple packages. It is in this case (which Thomas is referring to) that you should not use the * to select all the classes in the directory.
It is best practice to explicitly describe your class usage.
It doesn't impact performance to have excess import statements. It may make the source code longer than it should be but there is no effect on the compiled code. Java itself imports unnecessary class files - see the Java Language Specification section 7.5.5:
Each compilation unit automatically imports all of the public type
names declared in the predefined package java.lang, as if the
declaration:
import java.lang.*;
appeared at the beginning of each
compilation unit, immediately following any package statement.
Section 7.5.2 says that
A type-import-on-demand declaration never causes any other declaration
to be shadowed.
...meaning that wildcard imports won't trump single-entry imports.
As others have pointed out, any decent IDE (NetBeans, Eclipse, etc) will remove unused imports for you.
Like many questions about performance, clarity of the code is usually more important. This should be your first thought, and only in the rare cases where you have a known (measured) performance problem you should consider not writing the simplest and clearest code you can.
Like many performance questions, in this case the simplest, clearest code is also the fastest.
You should maintain your import or have your IDE maintain them, to keep them clear and make you code easier to maintain. The performance issue is very small, even for the compiler or IDE.
The biggest danger is namespace collisions. If two imported libraries both have a List type for example, it may not use the one you think it is.
It is important to remove them because they add bloat to the .java file and because getting rid of them within a given file is fast and cheap, especially if you're using an IDE (CTRL-SHIFT-O, I believe, is the shortcut in Eclipse).
As far as "What do redundant imports do for the machine", well, not much really. The class itself will only be added to the relevant jar file once, and it will only be loaded once per class (please see not vis-a-vis "per class"), so aside from adding some trivial amount of time to compilation, it won't really have any substantial long-term effect on the program itself.
That said, it is cheap and easy to fix the problem: if you aren't using an IDE, then you should have clearly grouped import statements which are in some sane order to begin with (I alphabetize mine, meaning that I'll immediately see two imports of java.util.Map, because they'd be right next to each other!). Your fellow coders will actively complian if you don't fix it, so I suggest that it is in your best interest to do so.
Is it possible that adding more import statements to your java code could slow down the time it takes to load your classes into the JVM?
No, imports are only used in compilation to find class references. Add unused imports and they don't do anything. To put it another way:
import java.util.*;
simply means you can write:
Map map = new HashMap();
instead of:
java.util.Map map = new java.util.HashMap();
That's all it does.
No. Imports are purely a compile time construct ... syntactic sugar.
The imports tell the Java compiler how to map identifiers in the source code to fully qualified class names. But if the source code does not use an imported class, the bytecode file will have no references to it. Hence, a redundant import does not (and cannot) impact on class load times.
Imports can have an effect on compilation time, but not on loading time or running time. Basically, if you import classes that you don't need (typically by using wildcard imports when explicit imports would do), then you can slow the compiler a bit.
However, even that effect is generally trivial unless you are compiling a huge system.
Don't confuse the word "import" with "class loading". The import statement does not cause any code to be loaded into memory. It's just a convenience that allows you to refer to classes using their short name instead of typing the full class name (e.g, "Connection" instead of "java.sql.Connection").
Why does Eclipse take a fine grained approach when importing types? In C# I'm used to things like "using System.Windows.Controls" and being done with it, but Eclipse prefers to import each widget I reference individually (using the Ctrl+Shift+O shortcut). Is there any harm to importing an entire namespace if I know I'll need multiple types in it?
Eclipse has a great setting called the "Organize Imports" in the Window -> Preferences dialog that lets you say when N classes are used from a package, do a wildcard import. I use it at N=2 or 3 usually.
Somebody can read your code without IDE - in this case non-wildcard imports will help him to figure out which classes are used in your code.
The only harm that wildcard package imports can cause is an increased chance of namespace collisions if there are multiple classes of the same name in multiple packages.
Say for example, I want to program to use the ArrayList class of the Java Collections Framework in an AWT application that uses a List GUI component to display information. For the sake of an example, let's suppose we have the following:
// 'ArrayList' from java.util
ArrayList<String> strings = new ArrayList<String>();
// ...
// 'List' from java.awt
List listComponent = new List()
Now, in order to use the above, there would have to be an import for those two classes, minimally:
import java.awt.List;
import java.util.ArrayList;
Now, if we were to use a wildcard in the package import, we'd have the following.
import java.awt.*;
import java.util.*;
However, now we will have a problem!
There is a java.awt.List class and a java.util.List, so referring to the List class would be ambiguous. One would have to refer to the List with a fully-qualified class name if we want to remove the ambiguity:
import java.awt.*;
import java.util.*;
ArrayList<String> strings = new ArrayList<String>();
// ...
// 'List' from java.awt -- need to use a fully-qualified class name.
java.awt.List listComponent = new java.awt.List()
Therefore, there are cases where using a wildcard package import can lead to problems.
The import directive is a compiler directive, it tells the compiler where to look for a class and allows to not have to always use fully qualified class names, e.g. java.util.HashMap. But the import directives themselves do not get put into the compiled bytecode files, the compiler compiles the fully qualified name into the .class file.
When used wiithout a wildcard, the directive explicitly tells the compiler to look for one specific file in the classpath. With a wildcard, the directive tells the compiler to look for the named package and to search in that package for possible matches every time any name needs to be matched. The latter version is probably going to take (a bit) longer for the compiler than the former.
In other words, the import directive cannot affect runtime code execution in any way. However, the import directive does affect compilation time. Additionally, I find that using import with wildcards makes the code less readable.
Actually, the cost of import statements question of the month on javaperformancetuning.com perfectly summarize this in its conclusion:
There is no runtime cost from using an import statement
The compilation process can take a little more time with an import
statement
The compilation process can take even more time with a wildcard import
statement
For improved readability, wildcard import statements are bad practice for
anything but throwaway classes
The compilation overhead of non-wildcard import statements are
minor, but they give readability
benefits so best practice is to use
them
I don't believe that wildcard imports have any sort of performance implications (and if it does, I think it would only happen at compile time). But as this SO post points out, it's possible that you can have class name overlaps if you use them.
I just use Ctrl+Space to force the import when I'm using a class that hasn't been imported yet, and the import happens automatically. Then I hit Ctrl+Shift+O after I refactor a class to remove any imports that are no longer used.
Up until JDK 1.2 this code would compile fine:
import java.awt.*;
import java.util.*;
public class Foo
{
// List is java.awt.List
private List list;
}
in JDK 1.2 java.util.List was added and the code no longer compiled because the compiler did not know which List was wanted (awt or util). You can fix it by adding "import java.awt.List;" at the end of the imports, but the point is you have to do something to fix it.
I personally use the single import instead of the on-demand import for two reasons:
it is clear where each class comes
from
if you have a huge number of imports
the class is probably doing too much
and should be split up. It is a
"code smell".
From a purist point of view, every import creates a dependency and a potential for conflict. Imports are treated as a necessary evil so they are minimized. Importing another package with a * is like writing a blank check. Importing two packages like that is like giving somebody access to moving money between your accounts.
From a practical point of view, this often makes sense because different projects and libraries use surprisingly similar names for differing concepts. Or, imagine you import everything from package A and then everything from package B, and use some class C from package B. If someone later on adds a class with the name C to package A, your code might break!
That being said, I admit I'm lazy. I'll often pre-import everything in the package, and then let Eclipse organize it for me based on what I actually use.
There's no harm in importing all the classes in a package/namespace, but I think it's better to include each individual class. It makes things clearer to developers who come after you exactly where each class comes from.
It's a non-issue if you're using a capable IDE like IntelliJ. I would imagine that Eclipse and NetBeans can manage imports as well. It will add the code for you and collapse them from view so they don't clutter the window. What could be easier?
Doesn't hurt the code. As a general principle, why import something if you are not going to use?
If you write some java code such as
LinkedList<foo> llist = new LinkedList<foo>()
and you haven't imported LinkedList to your project, Eclipse will ask if you want to import it. Since you are only using LinkedList and nothing else, it will only import LinkedList. If you do something else in the same project such as
ArrayList<foo> alist = new ArrayList<foo>()
Then Eclipse will also say you need to import ArrayList, but nothing else. Eclipse only has you import what you need based on any library calls you have made. If you need multiple types or items from the same library, there isn't harm in using a
import java.namespace.*
to go ahead and bring in the other items you need. Eclipse won't care as long as you are importing the packages and libraries that contain the items you are referencing such as Scanners, LinkedLists, etc.
From a readability perspective, it's a different question. If you want people to explicitly know what exactly you are importing, then calling each widget or package might be in order. This can get rather tedious if you are using lots of different functions from the same package in the standard library and can make your file headers quite long hence the .* wildcard. There's no harm in importing via wildcard, it really boils down to your coding standards and how transparent you want your class headers to be.
Importing each class explicitly gives a hard binding between the short name (e.g. Proxy) and the long name (e.g. java.lang.reflect.Proxy), instead of the loose binding saying that there probably is one in java.lang.reflect.*, java.io.* or java.net.* or somewhere else of the wildcard imports you have.
This may be a problem if for some reason another class named Proxy shows up somewhere in java.io.* or java.net.* or your own code, as the compiler then doesn't know which Proxy class you want as it would have if you explicitly imported java.lang.reflect.Proxy.
The above example is not contrieved. The java.net.Proxy class was introduced in Java 5, and would have broken your code if it was written as hinted above. See the official Sun explanation of how to circumvent wildcard problems at http://java.sun.com/j2se/1.5.0/compatibility.html
(The wildcard import is just a convenience mechanism for those not using an IDE to maintain import statements. If you use an IDE then let it help you :)