Java in a Nutshell, 5th Edition [Electronic resources] نسخه متنی

اینجــــا یک کتابخانه دیجیتالی است

با بیش از 100000 منبع الکترونیکی رایگان به زبان فارسی ، عربی و انگلیسی

Java in a Nutshell, 5th Edition [Electronic resources] - نسخه متنی

| نمايش فراداده ، افزودن یک نقد و بررسی
افزودن به کتابخانه شخصی
ارسال به دوستان
جستجو در متن کتاب
بیشتر
تنظیمات قلم

فونت

اندازه قلم

+ - پیش فرض

حالت نمایش

روز نیمروز شب
جستجو در لغت نامه
بیشتر
لیست موضوعات
توضیحات
افزودن یادداشت جدید


2.10. Packages and the Java Namespace


A

package
is a
named
collection of classes, interfaces, and other reference types.
Packages serve to group related classes and define a namespace for
the classes they contain.

The core classes of the Java platform are in packages whose names
begin with java. For example, the most fundamental
classes of the language are in the package
java.lang. Various utility classes are in
java.util. Classes for input and output are in
java.io, and classes for networking are in
java.net. Some of these packages contain
subpackages, such as java.lang.reflect and
java.util.regex. Extensions to the
Java platform that have been
standardized by Sun typically have package names that begin with
javax. Some of these extensions, such as
javax.swing and its myriad subpackages, were later
adopted into the core platform itself. Finally, the Java platform
also includes several "endorsed standards,"
which have packages named after the standards body that created them,
such as org.w3c and org.omg.

Every class has both a
simple name, which is the name given to it in its definition, and a
fully qualified name, which includes the name of the package of which
it is a part. The String class, for example, is
part of the java.lang package, so its fully
qualified name is java.lang.String.

This section explains how to place your own classes and interfaces
into a package and how to choose a package name that
won't conflict with anyone else's
package name. Next, it explains how to selectively import type names
into the namespace so that you don't have to type
the package name of every class or interface you use. Finally, the
section explains a feature that is new in Java 5.0: the ability to
import static members of types into the namespace so that you
don't need to prefix these with a package name

or a class name.


2.10.1. Package Declaration



To specify the package a class
is to be part of, you use a package declaration.
The package
keyword,
if it appears, must be the first token of Java code (i.e., the first
thing other than comments and space) in the Java file. The keyword
should be followed by the name of the desired package and a
semicolon. Consider a Java file that begins with this directive:

package com.davidflanagan.examples;

All classes defined by this file are part of the package
com.davidflanagan.examples.

If no package
directive appears in a Java file, all classes defined in that file
are part of an unnamed default package. In this case, the qualified
and unqualified names of a class are the same. The possibility of
naming conflicts means that you should use this default package only
for very simple code or early on in the development process of a
larger project.


2.10.2. Globally Unique Package Names


One of the important functions of packages
is to partition the Java namespace and prevent name collisions
between classes. It is only their package names that keep the
java.util.List and
java.awt.List classes distinct, for example. In
order for this to work, however, package names must themselves be
distinct. As the developer of Java, Sun controls all package names
that begin with java

,
javax, and sun.

For the rest of us, Sun
proposes a package-naming scheme, which, if followed correctly,
guarantees globally unique package names. The scheme is to use your
Internet domain name, with its elements reversed, as the prefix for
all your package names. My web site is at
http://davidflanagan.com, so all my Java
packages begin with com.davidflanagan. It is up to
me to decide how to partition the namespace below
com.davidflanagan, but since I own that domain
name, no other person or organization who is playing by the rules can
define a package with the same name as any of mine.

Note that these package-naming rules apply primarily to API
developers. If other programmers will be using classes that you
develop along with unknown other classes, it is important that your
package name be globally unique. On the other hand, if you are
developing a Java application and will not be releasing any of the
classes for reuse by others, you know the complete set of classes
that your application will be deployed with and do not have to worry
about unforeseen naming conflicts. In this case, you can choose a
package naming scheme for your own convenience rather than for global
uniqueness. One common approach is to use the application name as the
main package name (it may have subpackages beneath it).


2.10.3. Importing Types



When referring to a class or interface
in your Java code, you must, by default, use the
fully qualified name of the type,
including the package name. If you're writing code
to manipulate a file and need to use the File
class of the java.io package, you must type
java.io.File. This rule has three exceptions:

  • Types from the package java.lang are so important
    and so commonly used that they can always be referred to by their
    simple
    names.

  • The code in a type p.T may refer to other types
    defined in the package p by their simple names.

  • Types that have been

    imported into the namespace
    with an import declaration may be referred to by
    their simple names.


The first two exceptions are known as
"automatic imports." The
types from java.lang and the current package are
"imported" into the namespace so
that they can be used without their package name. Typing the package
name of commonly used types that are not in
java.lang or the current package quickly becomes
tedious, and so it is also possible to explicitly import types from
other packages into the namespace. This is done with the
import declaration.

import declarations must appear at the start of a
Java file, immediately after the package
declaration, if there is one, and before any type definitions. You
may use any number of import declarations in a
file. An import declaration applies to all type
definitions in the file (but not to any import
declarations that follow it).

The import declaration has two forms. To import a
single type into the namespace, follow the import
keyword with the name of the type and a semicolon:

import java.io.File;    // Now we can type File instead of java.io.File

This is known as the "single type
import" declaration.

The other form of import is the
"on-demand type import."
In this form, you specify the name of a package followed the
characters .* to
indicate that any type from that package may be used without its
package name. Thus, if you want to use several other classes from the
java.io package in addition to the
File class, you can simply import the entire
package:

import java.io.*;   // Now we can use simple names for all classes in java.io

This on-demand import syntax does not apply to
subpackages. If I import the java.util package, I
must still refer to the
java.util.zip.ZipInputStream class by its fully
qualified name.

Using an on-demand type import declaration is not the same as
explicitly writing out a single type import declaration for every
type in the package. It is more like an explicit single type import
for every type in the package

that you actually
use in your code. This is the reason it's
called "on demand"; types are
imported as you use them.


2.10.3.1 Naming conflicts and shadowing

import

declarations are invaluable to Java
programming. They do expose us to the possibility of
naming
conflicts, however. Consider the packages
java.util and java.awt. Both
contain types named List.
java.util.List is an important and commonly used
interface. The java.awt package contains a number
of important types that are commonly used in client-side
applications, but java.awt.List has been
superseded and is not one of these important types. It is illegal to
import both java.util.List and
java.awt.List in the same Java file. The following
single type import declarations produce a compilation error:

import java.util.List;
import java.awt.List;

Using on-demand type imports for the two
packages is legal:

import java.util.*;  // For collections and other utilities.
import java.awt.*; // For fonts, colors, and graphics.

Difficulty arises, however, if you actually try to use the type
List. This type can be imported
"on demand" from either package,
and any attempt to use List as an unqualified type
name produces a compilation error. The workaround, in this case, is
to explicitly specify the package name you want.

Because java.util.List is much more commonly used
than java.awt.List, it is useful to combine the
two on-demand type import declarations with a single-type import
declaration that serves to disambiguate what we mean when we say
List:

import java.util.*;    // For collections and other utilities.
import java.awt.*; // For fonts, colors, and graphics.
import java.util.List; // To disambiguate from java.awt.List

With these import declarations in place, we can
use List to mean the
java.util.List interface. If we actually need to
use the java.awt.List class, we can still do so as
long as we include its package name. There are no other naming
conflicts between java.util and
java.awt, and their types will be imported
"on demand" when we use them
without a package name.


2.10.4. Importing Static Members





In Java 5.0 and later, you can import
the static members of types as well as types themselves using the
keywords import static. (Static members are
explained in Chapter 3. If you are not already
familiar with them, you may want to come back to this section later.)
Like type import declarations, these static import declarations come
in two forms: single static member import and on-demand static member
import. Suppose, for example, that you are writing a text-based
program that sends a lot of output to System.out.
In this case, you might use this single static member import to save
yourself typing:

import static java.lang.System.out;

With this import in place, you can then use out.print(
)
instead of System.out.print( ). Or
suppose you are writing a program that uses many of the the
trigonometric and other functions of the
Math class. In a program that is clearly
focused on numerical methods like this, having to repeatedly type the
class name "Math" does not add
clarity to your code; it just gets in the way. In this case, an
on-demand static member import may be appropriate:

import static java.lang.Math.*

With this import declaration, you are free to write concise
expressions like sqrt(abs(sin(x))) without having
to prefix the name of each static method with the class name
Math.

Another important use of import static
declarations is to import the names of
constants into your code.
This works particularly well with enumerated types (see Chapter 4). Suppose, for example that you want to use
the values of this enumerated type in code you are writing:

package climate.temperate;
enum Seasons { WINTER, SPRING, SUMMER, AUTUMN };

You could import the type
climate.temperate.Seasons and then prefix the
constants with the type name: Seasons.SPRING. For
more concise code, you could import the enumerated values themselves:

import static climate.temperate.Seasons.*;

Using static member import declarations for constants is generally a
better technique than implementing an interface that defines the
constants.


2.10.4.1 Static member imports and overloaded methods

A
static import declaration
imports a

name , not any one specific member with
that name. Since Java allows method overloading and allows a type to
have fields and methods with the same name, a single static member
import declaration may actually import more than one member. Consider
this code:

import static java.util.Arrays.sort;

This declaration imports the name
"sort" into the namespace, not any
one of the 19 sort( ) methods defined by
java.util.Arrays. If you use the imported name
sort to invoke a method, the compiler will look at
the types of the method arguments to determine which method you mean.

It is even legal to import static methods with the same name from two
or more different types as long as the methods all have different
signatures. Here is one natural example:

import static java.util.Arrays.sort;
import static java.util.Collections.sort;

You might expect that this code would cause a syntax error. In fact,
it does not because the sort( ) methods defined by
the Collections class have different signatures
than all of the sort( ) methods defined by the
Arrays class. When you use the name
"sort" in your code, the compiler
looks at the types of the arguments to determine which of the 21
possible imported methods you mean.


/ 1191