| Home > Core Java FAQ
> Classes, Interfaces, & Packages FAQ |
| Classes,
Interfaces & Packages |
| Objects,
Classes, and Methods(19) * Sub
Class, Overload, and Overriding(11) * Interfaces
and Abstract Classes (11) * Packages
and Access Modifiers (09) |
| |
|
Q . What are packages, and what are they used for?
|
Ans :
A package
is a collection of classes and interfaces that provides a
high-level layer of access protection and name space management.
Although
the class is arguably the central unit of design in Java programs,
Java language packages provide a vital additional level
of support for program modularity. A package groups together a set
of classes and interfaces that needs to work as a coherent
whole. The java.io package, for instance, contains
classes and interfaces for managing various kinds of input and
output.
Packages define boundary lines to
govern how classes and interfaces may interact with one another.
Access control modifiers use package boundaries to:
- facilitate a
high degree of interaction and interdependency within a
package
- reduce access
and interaction across package boundaries
For instance, the
default access to methods and variables, if you don't specify an
access modifier, is that a method or variable defined in one class
cannot be used by classes belonging to a different package.
Packages also reduce the potential
for name clashes, because class names and interface names are
ultimately reckoned relative to the package to which they belong.
Thus, you could define your own Button class,
distinct from the Button class in the java.awt
package, provided that you place it in a package other than java.awt.
In general, you should not deliberately reuse well-known class
names like this; the name space protection provided by packages is
more of a safety measure against accidental clashes.
Every class and interface belongs to
some package. For each compilation unit (typically a source file),
you can declare what package its classes and interfaces belong to
with a package declaration at the beginning. For example:
package myPackage; // if present, must come first in the file
public interface Xyz { /* ... */ }
class Uvw { /* ... */ }
Any number of
source files (compilation units) can be declared to belong to the
same package. If you omit the package declaration, the classes and
interfaces in that file will be assigned to a system-provided
unnamed package. Although the package is nameless, the same rules
for package-internal versus package-external access privileges
still apply.
|
|
Q . I've seen both java.applet.Applet and Applet used to refer to the Applet class-what's the difference?
|
Ans
:
The shorter
name is definitely easier to use, but it requires that you provide
an import declaration to specify which package the class belongs
to.
The
name java.applet.Applet is the fully qualified
name of the Applet class in the java.applet
package. Fully qualified class or interface names come in the
form:
packageName.simpleClassName
packageName.simpleInterfaceName
The package name
itself can be a compound name with its own internal periods, such
as java.applet and java.awt.image.
You can always refer to a class or
interface by its fully qualified name, but it is more common and
more convenient to use just the simple name of the class or
interface. To let the compiler know which package a simple name
belongs to, you provide an import declaration at the head of your
source file (or, strictly speaking, after the package declaration,
if there is one). For example:
import java.applet.Applet;
After this, the
compiler will know to treat each occurrence of the simple name Applet
the same as if it were the fully qualified name java.applet.Applet.
Import declarations let the compiler do the extra name work for
you. Using an import declaration for a class (or interface) is
often called importing the class (or interface).
An alternate form of import
declaration lets you import as many classes as needed from a
package. A type import on demand uses an asterisk (*) in place of
a specific class or interface name. For example:
import java.awt.*;
This form of import
declaration makes all the classes and interfaces in the specified
package available as simple names.
Although package names are
hierarchical, import declarations are not. In the example above,
the import declaration imports only classes and interfaces from
the java.awt package. It does not import from
subpackages in java.awt—you must include separate
import declarations for each subpackage you want to import; for
example:
import java.awt.*; // the main AWT package
import java.awt.image.*; // the image subpackage
import java.awt.event.*; // the event subpackage; in JDK 1.1
Remember:
Importing classes and interfaces affects only the names by which
your code refers to classes. It does not send additional code to
the compiler, like C's include, or perform other
behind-the-scenes manipulations.
|
|
Q .
Why can I get some simple class names "for free," without using an import declaration?
|
Ans
:
Java
language programs automatically imports all classes in the java.lang
package.
The
java.lang package contains classes and interfaces
that provide crucial support to the Java language and Virtual
Machine, including Class, Exception, Object,
Runnable, String, System,
and Thread. To ensure that these classes and
interfaces are always easily available, and to prevent programs
from inadvertently calling on nonstandard versions, the java.lang
package is always automatically imported. The compiler treats each
source file as if its first import statement were
import java.lang.*; // implicit in every Java source file
The
automatic importing of java.lang class and interface
names is one of three sources of simple class names in a source
file:
- automatic
importing from java.lang package
- explicit import
declarations
- classes and
interfaces in unnamed package
|
|
Q .
Is there a default access modifier for classes and
interfaces? For class members (methods, constructors, and fields)?
|
Ans
:
There is no
default access modifier; the absence of a modifier, though,
signals package-level access, which is access only from classes in
the same package.
You
can assign two different levels of access to classes and
interfaces: public and package (also called package private).
Public access is marked with the public keyword, and package
access has no keyword, as shown in Table 1.6:
Table
1.6: Access Levels for Classes and Interfaces
public
keyword |
accessible
to all classes |
| no keyword |
accessible
only to classes in same package |
(The Java language
has a package keyword, but it is used in a different
context, for package declarations;) Table
1.7 lists the four possible levels of access for class and
interface members (methods, constructors, and fields); again,
package access has no keyword.
Table
1.7: Access Levels for Class and Interface Members
public
keyword |
accessible
to all classes |
| no keyword |
accessible
only to classes in same package |
protected
keyword |
accessible
to classes in same package and in limited circumstances
to subclasses in other packages. |
| private
keyword |
not
accessible to any other classes |
Good
program design seeks to isolate parts of a program from
unnecessary, unintended, or otherwise unwanted outside influences.
Access modifiers provide an explicit and checkable means for the
language to control such contact.
|
|
Q . What does protected access mean?
|
Ans
:
A method,
constructor, or field with protected
access is accessible to all classes in the same package, and to
subclasses in other packages provided that the class granting the
access is the same as or a subclass of the class making the
access.
The
protected level of access augments the default
package-level access with limited access for subclasses outside
the package of the class defining the protected
element (call these package-external subclasses). The basic idea
is that access from a subclass outside the protected
element's package is reckoned relative to the object or class
through which the access is occurring—access is allowed only if
the target class is the same as or a subclass of the
package-external class attempting the access.
For example, consider the access
facts for the following scenario:
package
P |
contains
class X and class SubX (a
subclass of X) |
class X
defines protected method M |
package Q |
contains
class Y (a subclass of X) and
class SubY (a subclass of Y) |
First, code in
class X or SubX can always invoke M:
| Method
invocation |
Access
allowed? |
code in
class X or SubX invokes M
on instance of class X or SubX |
Yes;
access is from inside the protected
element's package |
code in
class X or SubX invokes M
on instance of class Y or SubY |
Yes;
access is from inside the protected
element's package |
In contrast, when
code in class Y or SubY attempts to invoke M,
whether or not access is allowed depends crucially on the target
instance:
| Method
invocation |
Access
allowed? |
code in
class Y invokes M on instance
of class X or SubX |
No;
package-external access allowed from class Y
only if target instance belongs to class Y
or a subclass of Y. |
code in
class Y invokes M on instance
of class Y or SubY |
Yes;
package-external access allowed from class Y
because target instance belongs to class Y
or a subclass of Y. |
code in
class SubY invokes M on
instance of class Y |
No;
package-external access allowed from class SubY
only if target instance belongs to class SubY
or a subclass of SubY. |
Admittedly, the
details of protected access are tricky—for a full
specification and further examples, see The Java Language
Specification (p. 100).
|
|
Q . What is the accessibility of a public method or field inside a nonpublic class or interface?
|
Ans :
A public
method or field inside a nonpublic class is accessible only inside
its package, unless some other public access point—a public
interface or public superclass—can be used.
The
accessibility of members (methods and fields) within a class or
interface is limited by the class or interface through which they
are accessed. A nonpublic class receives the default package
access so that even public methods or fields inside that class are
generally not visible outside the class's package.
In two circumstances, though, a
public class member can have full public access even though the
class that defines it has only package access. First, a public
interface can expose methods from a package-private class that
implements the interface. When an instance of the class is
accessed through the interface (that is, through a reference of
the interface type), the methods implementing the interface are
visible outside their package.
A public superclass with public
methods can also expose methods from a package-private subclass.
When an instance of the subclass is accessed through a reference
of the superclass type, any public method of the superclass is
accessible to all classes. By dynamic binding, however, the actual
method body invoked will be the one belonging to the
package-private subclass.
|
|
Q .
Should I prefer importing {package}.{class} over {package}.*?
|
Ans
:
Does it make a difference to the class file in any way, if I import a
package versus use the full name, i.e.
import java.rmi.server.*;
...
RemoteObject ro;
versus:
java.rmi.server.RemoteObject ro;
No, it makes no
difference to the class files or runtime speed. Import is just a
shorthand for quoting the full name package and class name (as in
the examples in the question). Importing a class does not cause
the class to be loaded at run time. There is no runtime penalty
for using the * form of import. The class file will contain the
name of the packages it uses, and the loader will look for those
classes as needed at runtime.
At compile time,
the different forms of import may or may not make a difference to
compile time. Such a difference is likely to be negligible, and
should not be a factor in which form of import you use.
However, there are
style advantages. Some say that stating which classes you are
importing can help program readability. In a program with many *
import statements, it may take a programmer time to find
which package an
obscure class is imported from. If you explicitly list each class
you import at the top of the program, you document which package
each class you use comes from. These people suggest that you
use
import java.rmi.server.RemoteObject;
in preference to:
import java.rmi.server.*;
Other people say
that it is clearer still to use the full package and class name,
at the point where you use classes in other packages.
These people
suggest that you use:
java.rmi.server.RemoteObject ro;
But that gets a
little lengthy when you instantiate:
java.rmi.server.RemoteObject ro
= new java.rmi.server.RemoteObject();
You always have the
option of stating the full package and class name, whether you use
import or not.
Another good reason
not to use the * form is when you are importing two packages that
have classes of the same name and you want to use only one of
those classes. E.g.
import com.sun.*;
import com.ms.*;
where there is a
class called Modem in both those packages. If you use the * form
of import, you import both of the Modem classes and then must
fully qualify the class each time you use it, to say which of the
two you mean. In
Java 1.2, the class java.util.List was introduced. That had the
same unqualified name as java.awt.List. If your code had
"import java.awt.*; import java.util.*;" it would no
longer compile.
You'd get a message
about ambiguous classname. If you import all of a package
indiscriminately you might get bitten when the package API
changes.
In Java 1.0, if you
import a class that has the same name as a class defined in that
source file, you will get an error that the class names clash. In
Java 1.1, the local class will be used when the package name
is not given; to
use the imported class, you have to use the full package name.
The best advice is
to write the program so that it is as readable as possible. Where
you have a group of well-known classes, as in java.awt, there is
no reason not to use "import java.awt.*;"
|
|
Q . How can I use Math.cos() etc. without the prefix "Math."?
|
Ans
:
Is there some declaration that I can use to make
"acos", "cos", "sin", etc. (from java.lang.Math) recognizable in my own class, so I don't
have to prefix "Math." to them?
No. There is no good alternative. There are several bad
alternatives:
1. Using "import" doesn't work.
The import stament only imports packages, subpackages, and classes, not class members. This doesn't work:
import java.lang.Math.*;
2. Minimizing class name usage is unclear and bad style.
- You could wrap the functions in your own class.
double sin(double x) {
return Math.sin(x);
} // etc. for each function
But you'd have to use your class name everywhere but inside your class, so it doesn't help.
- You can make a null reference to the Math class and use it to refer to the static methods. Declare
java.lang.Math M = null;
angle = M.cos(i);
Besides not being clear, this invites abuse and errors.
- You could inherit the names
If java.lang.Math were not final and your class did not extend another class, you could have your class extend Math, to bring the
namespace in. However, it is poor OOP style to use inheritance to obtain a name abbreviation rather than to express a type
hierarchy.
|
|
Q .
An anonymous class can't seem to access a private outer method. Why is that?
|
Ans
:
It's a known bug in the JDK
1.1.4. The code is:
public
class MyDialog {
void Setup() {
addWindowListener( new WindowAdapter() {
public void windowClosing(WindowEvent e) {
myCloseWindow(); }
}
); // anon inner class
}
private void myCloseWindow() { // private outer method
dispose();
}
}
This
code sends javac into an infinite loop. The workaround is to make
the private method non-private, or to make the inner class a named
class. Sun put a workaround in the compiler to silently set the
field to package access.
|
|
|
|