I am a newbie to Java development. I have a quick question regarding recursive imports in Java.
Lets assume Package "pkg" contains the following
class A,
package B (This in turn contains B1 class)
package C (This in turn contains C1 class)
If I use import pkg.* why am I not allowed to import classes from packages "B" and "C" ?.
I would like to understand the rationale behind in Java's not allowing me to do recursive imports.
Your question is poorly phrased, because if you import pkg.*, you certainly are allowed to then import classes from packages pkg.B and pkg.C. That is, it is perfectly fine to do this:
import pkg.*;
import pkg.B.*;
import pkg.C.*;
But I assume that what you really are asking is why, if you import pkg.* it does not automatically import the types declared in the subpackages of pkg. To answer that, it's best to turn to the Java Language Specification:
The hierarchical naming structure for packages is intended to be convenient for organizing related packages in a conventional manner, but has no significance in itself other than the prohibition against a package having a subpackage with the same simple name as a top level type (§7.6) declared in that package.
For example, there is no special access relationship between a package named oliver and another package named oliver.twist, or between packages named evelyn.wood and evelyn.waugh. That is, the code in a package named oliver.twist has no better access to the types declared within package oliver than code in any other package.
In other words, when you import pkg.*, you are importing all the top-level types defined by the compilation units contained in the package named pkg, but you are not importing any of the sub-packages of pkg (such as pkg.B or pkg.C).
It sounds like you're asking why import java.awt.* doesn't also import java.awt.color.* and so on.
This is best explained by this tutorial where it says
At first, packages appear to be hierarchical, but they are not. For
example, the Java API includes a java.awt package, a java.awt.color
package, a java.awt.font package, and many others that begin with
java.awt. However, the java.awt.color package, the java.awt.font
package, and other java.awt.xxxx packages are not included in the
java.awt package. The prefix java.awt (the Java Abstract Window
Toolkit) is used for a number of related packages to make the
relationship evident, but not to show inclusion.
More importantly,
Importing java.awt.* imports all of the types in the java.awt package,
but it does not import java.awt.color, java.awt.font, or any other
java.awt.xxxx packages. If you plan to use the classes and other types
in java.awt.color as well as those in java.awt, you must import both
packages with all their files:
import java.awt.*;
import java.awt.color.*;
The convention in Java is to import only the classes you required. Most IDEs will automatically organise them for you. Importing classes in bulk is not common like in other languages.
There is no restriction on imports as you described in your original question (prior to the edit).
Let's assume you have the following Hierarchy:
pkg1
A.java
pkg1.pkg2
B.java
pkg1.pkg3
C.java
D.java
You are permitted to import any of the A.java, B.java, C.java, D.java, or combinations therein.
import pkg1.A;
import pkg1.pkg2.B;
import pkg1.pkg3.C;
import pkg1.pkg3.D;
The only caveat is that within class C, you can use class D without importing D explicitly because they share the same package.
However, a blanket statement like import pkg1.* will not pull in the classes located further down the package hierarchy; you'd need to import each sub-package as well: import pkg1.pkg2.*, etc. This is simply how the language is designed.
Related
I'm writing a Java program that has a button with an action listener:
JButton button = new JButton("Change");
button.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
label.setText(textField.getText());
}
});
At the top of the file, I have these two import statements:
import java.awt.*;
import javax.swing.*;
I know this is terrible practice, I am revising for an exam and it's way easier and quicker to just write that at the top of the page.
I get an error, however, telling me to import java.awt.event.ActionListener
If the event package is inside java.awt and I used the wildcard * to import everything, then why is it not being imported??
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).
java.awt.* doesn't include java.awt.event.ActionListener. java.awt.event is not a sub package of java.awt. import java.awt.event.* would include java.awt.event.ActionListener.
I'm talking about the stuff we import.
Suppose, there is something like:
import java.util.Scanner;
util is the package and Scanner is the class, right?
Can this be always generalised and be said that in the import statement, the first one would be java/javax (is there any other?), the second one package, the third class and the fourth, if any, will always be a method belonging to the class?
Are there any exceptions, if so please name them.
Can this be always generalised and be said that in the import statement, the first one would be java/javax (is there any other?), the second one package, the third class and the fourth, if any will always be a method belonging to the class?
Not really, no.
The package is java.util, and you'll definitely see other packages, including the ones you write.
Within a normal import statement, there'll be a package, then either a specific class name or a * (to import all the classes in a package). But the class name could be a nested class name, so you could have:
import foo.bar.Outer.Nested;
where foo.bar is the package name, and Outer.Nested is the class name.
Then there are static imports, where you import members of classes, e.g.
import static java.lang.Math.sqrt;
See the Java tutorial on imports for more details.
No, it does not need to start with java, you can use anything as package name. Usually package names have a pattern like: com.someone.project.any.package.Class where com.someone represents the domain, project the project name and any.package your package hierarchy inside the project. This is just a convention but I would recommend you to use it.
Also take a look at: https://docs.oracle.com/javase/tutorial/java/package/namingpkgs.html
simple example from andEngine library:
org.andengine.entity.modifier.FadeOutModifier;
as you can see it has four nods. Last one is a class, extending modifier class, extending entity class, in package org.andengine... Also it does not start with java.
Hope it explains a bit
In your example
import java.util.Scanner;
java.util is the package, Scanner is the class you're importing from that package to be visible to the compiler.
See, for example, these lines from a the imports section of a pretty normal java file:
import java.util.Map;
import com.google.common.collect.ImmutableMap;
import org.apache.commons.lang.StringUtils;
These are all valid imports, which import the Map interface from java.util package, the ImmutableMap class from com.google.common.collect package, etc.
I have a logical question: Why i cannot import all packages from all packages in java?
For example i can import all classes from java.awt:
import java.awt.*;
But the following isnt possible:
import java.awt.*.*;
My aim would be to import all stuff from awt.image and awt.event and so on.
Is there another way to do this?
Thank you!
There is no way to achieve an import a.package.*.*; in Java. The JLS, Section 7.5 specifies the only 4 types of imports that are legal:
A single-type-import declaration (§7.5.1) imports a single named type,
by mentioning its canonical name (§6.7).
e.g. import java.util.List;
A type-import-on-demand declaration (§7.5.2) imports all the
accessible types (§6.6) of a named type or named package as needed, by
mentioning the canonical name of a type or package.
e.g. import java.awt.*;
A single-static-import declaration (§7.5.3) imports all accessible
static members with a given name from a type, by giving its canonical
name.
e.g. import static org.junit.Assert.assertEquals;
A static-import-on-demand declaration (§7.5.4) imports all accessible
static members of a named type as needed, by mentioning the canonical
name of a type.
e.g. import static org.junit.Assert.*;
Packages allow classes of the same name to be referenced individually. E.g. there is java.awt.List and java.util.List. What would stop someone from importing everything with java.*.*;. How would List be resolved then? There would be too much ambiguity.
No, and using wildcard imports is bad style in general as it makes your code harder to read.
Some disadvantages of using wildcards imports:
Results in including classes that you might not use at all. Not clear picture of what you are working with.
More broader scope which is considered bad programming practice.
Most important can result in namespace clash. If you are blatantly importing everything from two packages it may result in clash between two classes with same name from different packages.
Edit: Seems like importing more classes than required doesn't result in any bulky code, but I would still prefer to import the classes explicitly to have a clear idea about what I am working with.
I'm reading every tutorial I can find as well as a book, still trivial concetps leave me asking questions:
CLASSPATH is a variable registered with the JVM that tells java the root directory in which to start looking for classes/jars/etc?
import is similar to include (C/C++) but provides a namespace via package? I just read how without using import you have to explicitly state the package/namespace for every class (using the FQCN) such as java.util.String (possibly invalid excuse) where as using import java.util would allow me everywhere else in the code to simply refer to class as String.
What confuses me about import is some examples use import like:
import java.util.*; // import all public classes from java.util package
import java.util.Hashtable; // import only Hashtable class (not all classes in java.util package)
Yes the article also follows up:
Note that we can call public classes stored in the package level we do the import only. We can't use any classes that belong to the subpackage of the package we import. For example, if we import package world, we can use only the HelloWorld class, but not the HelloMoon class.
So which is it, when I use the * in an import is that not recursively importing all sub-packages?
7.5.2. Type-Import-on-Demand Declarations
import java.util.*;
causes the simple names of all public types declared in the package java.util to be available within the class and interface declarations of the compilation unit. Thus, the simple name Vector refers to the type Vector in the package java.util in all places in the compilation unit where that type declaration is not shadowed (§6.4.1) or obscured (§6.4.2).
The declaration might be shadowed by a single-type-import declaration of a type whose simple name is Vector; by a type named Vector and declared in the package to which the compilation unit belongs; or any nested classes or interfaces.
The declaration might be obscured by a declaration of a field, parameter, or local variable named Vector.
(It would be unusual for any of these conditions to occur.)
You are correct.
Unlike C/C++ include, Java's import is optional, as Java loads all classes it finds in CLASSPATH regardless.
Java's import statements allows you to alias commonly used classes so you don't have to fully qualify them each time.
Let's say you have the following class defined:
package com.foo.bar;
public class Bazz {
public static final int ONE = 1;
public static final int TWO = 2;
public static final int THREE = 3;
... some methods ...
}
There are several ways of using import:
import com.foo.bar.*; // import all classes belonging to package com.foo.bar, and com.foo.bar only.
import com.foo.bar.Bazz; // import class com.foo.bar.Bazz only
import static com.foo.bar.Bazz.*; // import all static constants in class com.foo.bar.Bazz
import static com.foo.bar.Bazz.ONE; // import static constant com.foo.bar.Bazz.ONE only
As you state, there is no way of recursively importing packages.
As an aside, most IDEs will auto-import the classes for you. For example, Eclipse does this when you press CTRL+SHIFT+O.
As in the example you provided in the question, when you specify
import java.util.*;
You import all of the public classes in the java.util package. You do not import any public classes that reside outside the java.util package.
Integrated development environments (IDE) like Eclipse will create individual class imports for you. There's not much reason to code a global import (with an asterisk) any more.
Yes. That's what it does.
But it is best practice to provide absolute path in the import statement.
I use a mass import class group as below:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.util.*;
import java.io.*;
import java.text.*;
import java.util.regex.*;
This way I don't have to worry about leaving any classes out.
Then when I used List I got this error:
reference to List is ambiguous, both class java.util.List in java.util
and class java.awt.List in java.awt match
How do I fix this? Is there a way to deport one of the classes? Which one is better?
You will need to refer to these types with their fully qualified names, java.util.List and java.awt.List, throughout this class file.
This will disambiguate the two Lists so that it won't strictly be necessary to "deport" anything (your import statements can stay the same). However I do agree with the other answer's recommendations that you tidy up your imports.
If one of the Lists was "deported" then that would let you refer to the other List by its short name.
Firstly, you shouldn't import whole packages like that. You should include only what is required. IDEs do have options where they will include for you whatever is required. At least Eclipse does that. For reading its disadvantages in detail you can go through the following link:
Any difference between class imports and package imports in Java?
However, if it is absolutely necessary then ambiguity can be avoided by referring to these ambiguous classes with their fully qualified names e.g., in your case
java.util.List AND/OR java.awt.List
The fix is to not import everything like that. Use an IDE like Eclipse to manage your imports for you.
always and always import only the classes that you use in your particular program. For classes with the same name but different package like the List class that you are using, can be specified with their fully qualified names rather than the import statement