Programming with Objects: A Comparative Presentation of Object Oriented Programming with C++ and Java

3.9 PACKAGES IN JAVA

The Java platform consists of packages of related classes and interfaces. For example, all the classes that deal with I/O are in the Java.io package; the utility classes are all grouped in the java.util package; and so on. If you become involved in a large software development project in Java, you'd want to organize your own classes into packages.

In this section, we will first show how a package supplied with the Java platform is used in your own program. Then we will discuss how you can create your own packages.

The following program is a simple demonstration of how a package that comes with the Java platform can be used in your own program. The program first declares and initializes an array of integers in lines (B) and (C). Subsequently, in line (E), this array is sorted by invoking the highly efficient sort method defined for the class Arrays in the java.util package. Finally, the program reports back the time taken for sorting in line (G).


//SortTiming.java import java.util.*; //(A) public class Test { public static void main( String [] args ) { int[] arr = new int[1000000]; //(B) for ( int i=0; i<1000000; i++ ) arr[i] = (int) ( 1000000 * Math.random() ); //(C) long startTime = System.currentTimeMillis(); //(D) Arrays.sort( arr ); //(E) long diffTime = System.currentTimeMillis() - startTime; //(F) System.out.println("Sort time in millisecs: " + diffTime);//(G) } }

For line (E) to make any sense to the compiler, the program starts in line (A) with the statement

import java.util.*;

for importing the java.util package that contains the class Arrays. With the import statement as shown in line (A), our program will be able to refer to any class in the java.util package by its name directly. Without the import statement, we would need to replace the statement in line (E) by

java.util.Arrays.sort( arr );

Therefore, when your program includes an import statement for a certain package, you just make it easier to refer to the classes in that package. If for some reason you decide to use a class without importing the package containing the class, then you have no choice but to use what's known as the package qualified name for that class, as, for example, by java.util.Arrays for the Arrays class in the java.util package.

The program also uses a couple of other classes, Math and System. Both these classes are in the java.lang package which gets automatically imported into every Java program. The class Math is needed in line (C) for the invocation of random() to fill up a million-element array with random numbers.[9] And the class System makes available the method currentTimeMillis(), used in lines (D) and (F), which returns the current time in milliseconds from midnight January 1, 1970. A particular run of the program on a 4-processor UltraSparc produced the following output:

Sort time in millisecs: 1378

The rest of this section is devoted to how you can create and use your own packages. To illustrate the various issues related to package creation and usage, let's say that we want to create the following three packages with classes therein as shown:

packageX: contains classes TestOne and TestTwo packageY: contains class TestOne testDirectory: contains class TestFinal

In order to create a name conflict, we have intentionally named one of the classes in packageX the same as the sole class in packageY. The TestOne class in packageX is meant to be different from the TestOne class in packageY.

We will now provide simple definitions for the four classes listed above. As could be the case during code development, for testing purposes you would want to compile and execute the classes in the directories in which they exist. With respect to class definition, compilation, and execution, the reader should note the following:

We now ask the reader to carry out the following steps:

  1. In any directory in which you like to do Java programming, create the following three subdirectories:

    packageX packageY testDirectory

  2. In the directory packageX, create the class TestOne in a file named TestOne.java:


    //TestOne.java package packageX; //(A) public class TestOne { public void print() { System.out.println( "print of packageX.TestOne invoked" ); } public static void main( String[] args ) { TestOne testone = new TestOne(); testone.print(); } }

    Note the statement in line (A) at the top of the class file

    package packageX;

    that tells the Java platform that this class will reside in a package named packageX. This class can be compiled by

    javac TestOne.Java

    If you wanted to execute this class while you are in the directory packageX, you'll have to invoke the Java Virtual Machine with the -classpath option, as for example in

    java -classpath .:/chap3/packageStudy.d packageX.TestOne

    which is based on the assumption that the three package directories you created are in the directory packageStudy.d.

  3. Create in the same directory, packageX, the following class in a file named TestTwo.Java:

    //TestTwo. java package packageX; //(B) import packageX.*; //(C) public class TestTwo { TestOne testone = new TestOne(); //(D) public void print() { System.out.println ( "print of packageX. TestTwo invoked" ); } public static void main( String[] args ) { TestTwo testtwo = new TestTwo(); testtwo.print(); testtwo.testone.print(); } }

    Note that this class contains both a package statement, in line (B), that says that the class resides in package packageX and an import statement in line (C). The import statement is needed because the class has a data member of type TestOne in line (D) which is defined in the package packageX. To compile this class, you'd now need to use the -classpath option, as for example in

    javac -classpath .:/chap3/packageStudy.d TestTwo.java

    The classpath tells the compiler how to go about locating packageX needed by the import statement of the class. Executing the class with the java command will also need the -classpath option, as for example in

    java -classpath .:/chap3/packageStudy.d packageX.TestTwo

  4. Now switch over to the directory packageY and, in order to create a name conflict with packageX, install in this directory a class named TestOne in a file named TestOne.Java:


    //TestOne.java package packageY; //(E) public class TestOne { public void print() { System.out.println( "print of packageY.TestOne invoked" ); } public static void main( String[] args ) { TestOne testone = new TestOne(); testone.print(); } }

    Note the declaration of packageY in line (E) at the top of the class file. As long as you are in the packageY directory, you can compile this class by

    javac TestOne.java

    And you can execute the class by something like this

    java -classpath .:/chap3/packageStudy.d packageY.TestOne

  5. Now switch over to the directory testDirectory and create in it a class named TestFinal in a file called TestFinal.java:

//TestFinal.java import packageX.*; //(F) public class TestFinal { packageX.TestOne testone_X = new packageX.TestOne(); //(G) packageY.TestOne testone_Y = new packageY.TestOne(); //(H) TestTwo testtwo = new TestTwo(); //(I) void print() { System.out.println( "print of TestFinal invoked" ); } public static void main( String[] args ) { TestFinal tf = new TestFinal(); tf.print(); tf.testone_X.print(); tf.testone_Y.print(); tf.testtwo.print(); } }

Note how the package qualified names are used in lines (G) and (H) to tell the compiler which TestOne class is used where. Also note that the import statement in line (F) is needed for the unqualified class name in line (I). To compile the file TestFinal.java, you'd need to use the -classpath option to help the compiler locate the packages packageX and packageY:

javac -classpath .:/chap3/packageStudy.d TestFinal.java

To execute TestFinal, you'd again need to use the -classpath option, as in

java -classpath .:/chap3/packageStudy.d TestFinal

Executing this class produces the expected output:

print of TestFinal invoked print of packageX.TestOne invoked print of packageY.TestOne invoked print of packageX.TestTwo invoked

[9]Math.random() returns a double that is greater than or equal to 0.0 and less than 1.0. The statistical distribution of these pseudorandomly generated numbers is uniform over this range.

Категории