Packages Core Java

Java allows you to group classes in a collection called a package. Packages are convenient for organizing your work and for separating your work from code libraries provided by others.

The standard Java library is distributed over a number of packages, includingjava.lang, java.util,, and so on. The standard Java packages are examples ofhierarchical packages. Just as you have nested subdirectories on your hard disk, youcan organize packages by using levels of nesting. All standard Java packages areinside the java and javax package hierarchies.

The main reason for using packages is to guarantee the uniqueness of class names. Suppose two programmers come up with the bright idea of supplying an Employee class. As long as both of them place their class into different packages, there is no conflict.In fact, to absolutely guarantee a unique package name, Sun recommends thatyou use your company’s Internet domain name (which is known to be unique) writtenin reverse. You then use sub packages for different projects. For example, horstmann.comis a domain that one of the authors registered. Written in reverse order, it turns intothe package com.horstmann. That package can then be further subdivided into sub packagessuch as com .horstmann .corejava.

From the point of view of the compiler, there is absolutely no relationship betweennested packages. For example, the packages java.util and java.util.jar have nothing todo with each other. Each is its own independent collection of classes.

Class Importation

A class can use all classes from its own package and all public classes from other packages.
You can access the public classes in another package in two ways. The first is simply toadd the full package name in front of every class name. For example:

That is obviously tedious. The simpler, and more common, approach is to use the import statement. The point of the import statement is simply to give you a short hand to refer to theclasses in the package. Once you use import, you no longer have to give the classes their full names.

You can import a specific class or the whole package. You place import statements at thetop of your source files (but below any package statements). For example, you can importall classes in the java.util package with the statement

Then you can use

without a package prefix. You can also import a specific class inside a package:

The java.util.* syntax is less tedious. It has no negative effect on code size. However, if you import classes explicitly, the reader of your code knows exactly which classes you use.

TIP: In Eclipse, you can select the menu option Source -> Organize Imports. Package statements such as import java.util.*; are automatically expanded into a list of specific imports such as

This is an extremely convenient feature.
However, note that you can only use the * notation to import a single package. You cannotuse import java.* or import java.*.* to import all packages with the java prefix.

Most of the time, you just import the packages that you need, without worrying toomuch about them. The only time that you need to pay attention to packages is when youhave a name conflict. For example, both the java.util and java.sql packages have a Dateclass. Suppose you write a program that imports both packages.

If you now use the Date class, then you get a compile-time error:

The compiler cannot figure out which Date class you want. You can solve this problem by adding a specific import statement:

What if you really need both Date classes? Then you need to use the full package name with every class name.

Locating classes in packages is an activity of the compiler. The byte codes in class files always use full package names to refer to other classes.

C++ NOTE: C++ programmers usually confuse import with #include. The two have nothing in common. In C++, you must use #include to include the declarations of external features because the C++ compiler does not look inside any files except the one that it is compiling and explicitly included header files. The Java compiler will happily look inside other files provided you tell it where to look.

In Java, you can entirely avoid the import mechanism by explicitly naming all classes, such as java.util.Date. In C++, you cannot avoid the #include directives.

The only benefit of the import statement is convenience. You can refer to a class by a name shorter than the full package name. For example, after an import java.util.* (or import java.util.Date) statement, you can refer to the java.util.Date class simply as Date.

The analogous construction to the package mechanism in C++ is the namespace feature. Think of the package and import statements in Java as the analogs of the namespace and using directives in C++.

Static Imports

Starting with Java SE 5.0, the import statement has been enhanced to permit the importingof static methods and fields, not just classes.

For example, if you add the directive

to the top of your source file, then you can use static methods and fields of the System class without the class name prefix:

You can also import a specific method or field:

In practice, it seems doubtful that many programmers will want to abbreviate System.outor System.exit. The resulting code seems less clear. But there are two practical uses forstatic imports.

  • Mathematical functions: If you use a static import for the Math class, you can usemathematical functions in a more natural way. For example,
sqrt(pow(x, 2) + pow(y, 2))

seems much clearer than

Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2))
  • Cumbersome constants: If you use lots of constants with tedious names, you willwelcome static import. For example,
if (d.get(DAY_OF_WEEK) == MONDAY)

is easier on the eye than

if (d.get(Calendar.DAY_OF_WEEK) == Calendar.MONDAY)

Addition of a Class into a Package

To place classes inside a package, you must put the name of the package at the top ofyour source file, before the code that defines the classes in the package. For example, thefile Employee. java in Listing below starts out like this:

If you don’t put a package statement in the source file, then the classes in that source filebelong to the default package. The default package has no package name. Up to now, allour example classes were located in the default package.

You place source files into a sub directory that matches the full package name. For example,all source files in the package com.horstmann.corejava package should be in a sub directorycom /horstmann /corejava (com horstmann corejava on Windows). The compiler places theclass files into the same directory structure.

The program in Listings below is distributed over two packages: the PackageTest classbelongs to the default package and the Employee class belongs to the com .horstmann .core java package. Therefore, the Employee .java file must be contained in a subdirectory com/horstmann/corejava. In other words, the directory structure is as follows:

(base directory) PackageTest.class com/ horstmann/ corejava/ Employee.class

To compile this program, simply change to the base directory and run the command

The compiler automatically finds the file com /horstmann /corejava /Employee .java and compiles it.

Let’s look at a more realistic example, in which we don’t use the default package buthave classes distributed over several packages (com .horstmann .corejava and com .mycompany).

. (base directory) com/ horstmann/ corejava/ Employee.class mycompany/ PayrollApp.class

In this situation, you still must compile and run classes from the base directory, that is,the directory containing the com directory:

Note again that the compiler operates on files (with file separators and an, whereas the Java interpreter loads a class (with dot separators).

CAUTION: The compiler does not check the directory structure when it compiles source files. For example, suppose you have a source file that starts with the directive

You can compile the file even if it is not contained in a subdirectory com /mycompany. The source file will compile without errors if it doesn’t depend on other packages. However, the resulting program will not run. The virtual machine won’t find the resulting classes when you try to run the program.

Package Scope

You have already encountered the access modifiers public and private. Features tagged aspublic can be used by any class. Private features can be used only by the class thatdefines them. If you don’t specify either public or private, the feature (that is, the class,method, or variable) can be accessed by all methods in the same package. The Employee class was not defined as apublic class. Therefore, only other classes in the same package—the default package inthis case—such as Employee Test can access it. For classes, this is a reasonable default. However,for variables, this default was an unfortunate choice. Variables must explicitly be marked

private or they will default to being package visible. This, of course, breaks encapsulation.The problem is that it is awfully easy to forget to type the private keyword. Here isan example from the Window class in the java.awt package, which is part of the source code supplied with the JDK:

Note that the warning String variable is not private! That means the methods of all classesin the java.awt package can access this variable and set it to whatever they like (such as"Trust me!"). Actually, the only methods that access this variable are in the Window class, soit would have been entirely appropriate to make the variable private. We suspect thatthe programmer typed the code in a hurry and simply forgot the private modifier. (Wewon’t mention the programmer’s name to protect the guilty—you can look into thesource file yourself.)

NOTE: Amazingly enough, this problem has never been fixed, even though we have pointed it out in eight editions of this book—apparently the library implementors don’t read Core Java. Not only that—new fields have been added to the class over time, and about half of them aren’t private either.

Is this really a problem? It depends. By default, packages are not closed entities. That is,anyone can add more classes to a package. Of course, hostile or clueless programmer scan then add code that modifies variables with package visibility. For example, in early versions of the Java programming language, it was an easy matter to smuggle anotherclass into the java.awt package. Simply start out the class with

Then, place the resulting class file inside a sub directory java /awt somewhere on the class path, and you have gained access to the internals of the java.awt package. Through thissubterfuge, it was possible to set the warning string.

Changing the warning string in an applet window

Changing the warning string in an applet window

Starting with version 1.2, the JDK implementors rigged the class loader to explicitly dis allow loading of user -defined classes whose package name starts with "java."! Of course,your own classes won’t benefit from that protection. Instead, you can use another mechanism,package sealing, to address the issue of promiscuous package access. If you seal apackage, no further classes can be added to it.

All rights reserved © 2018 Wisdom IT Services India Pvt. Ltd Protection Status

Core Java Topics