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.
Related
I was reading about predefined methods and was learning about import statements. I have seen and often times used these to use certain predefined methods, but I've always seen them placed at the very beginning of a program. My question is, can these be placed inside a certain block of code so that it is only seen in that block? I'm not sure that there would ever actually be a reason for this, mostly just curious.
java files contains three parts:
package definition
imports definitions (optional)
the class (or interface/enum) definition.
and it also has to be in this order, you'll get compilation error if it's not in this order
No, you need to define it before of the class/interface, after the package statement.
So an import is always visible to the entire .class-file.
import lets you use members of other packages than your local package, without specifying the full name of a class (e.g. either you need to import java.util.List, or you need to use it's full name everywhere).
There is a tutorial on using package members by Oracle.
The order in a .class-file is defined as:
package specification (optional)
import statements
class / interface / enum definition
My guess is that will give you a compiler error. BUT you can effectively acheive the same thing if you specify the full package name of a class when you instantiate it.
E.g:
public String getString() {
return new com.package.some.Class("hello world").toString();
}
In this case you don't need to have an 'import' directive at the top of the class because you are telling the compiler inside the method that the class you want is located in the com.package.some package and the class is called Class.
This actually happens in the wild when for example you have to classes in different packages that have the same name. You can only import one of them, the other one you will have to inline the package definition inside the code.
import com.package.some.Class;
public class Yolo {
private Class classA;
private com.package.other.Class classB;
public Yolo(Class classA, com.package.other.Class classB) {
this.classA = classA;
this.classB = classB;
}
}
you can't just import both 'Class' objects and refer to them as Class because the compiler won't know which one. So, this is a valid situation where you will see this kind of thing happen for real.
From Oracle Docs :
Importing a Package Member
To import a specific member into the current file, put an import
statement at the beginning of the file before any type definitions but
after the package statement, if there is one. Here's how you would
import the Rectangle class from the graphics package created in the
previous section.
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 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.
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.
Ok really stupid question, but I have some methods defined in a file called x.java, which is in the default folder, and in the same folder, I have a file called z.java. I want to use the functions defined in x in z. When I try, it tells me the function is undefined. I tried to put import x.java; but it says x.java cannot be resolved. What am I missing here?
Based on your description, I'd bet there's a good chance both of your source files defined classes in the default package (i.e., you don't explicitly define a package for them).
You can't import a class that's in the default package.
Recommend you put your class x in a named package (e.g., foo.bar.x), then you can import it:
import foo.bar.x;
if you have a file called x.java which compiles to x.class, you don't import by doing:
import x.java;
but you do
import x;
I think, if the two classes are in same package then there is no need to import the class as that class can be used without any import and without any error.