Lab 5: Packages and Archives Lab 5: Packages and Archives Despite the title (and the image above), this lab manual is not part of the postal service training. In this course when we talk about packages we do not meant boxes wrapped in duct tape that contain grandma�s cookies and other goodies from mom and dad. What we mean is a collection of classes that we can include in our program and use in our code. We include packages (or parts of packages) in our code using the import statement. In the previous lab we learned how to search through the Java API documentation and find classes and methods we can use in our code. In this lab we will see how to use them as packages, or parts of packages, and how to create new packages for our code. We will conclude with a short discussion about archiving. Take a look at the following program, which uses two packages - the java.util and the javax.swing packages: /** This class guesses your age. @author Professor Charles Xavier @version 1.0 */
import java.util.Random;
import javax.swing.JOptionPane;
public class GuessYourAge
{
public static void main(String[] args) {
Random rand = new Random();
boolean found = false;
int guess = 0;
String reply;
int steps = 0;
while (!found) {
guess = rand.nextInt(100);
reply = JOptionPane.showInputDialog(
"Are you " + guess + " years old (y/n)?");
if (reply != null) {
steps++;
// in case answer is "Y" or "N"
reply = reply.toLowerCase();
if (reply.equals("y"))
found = true;
else System.out.println("Missed on guess #"
+ steps);
} }
// printing results
System.out.println("It only took me " + steps +
" steps to guess that you are " + guess +
" years old.");
System.exit(0);
} }
Problem 1: (1 point) The GuessYourAge class uses one class from each of the two packages. What are the names of these two classes? Write your answer to a file called classes.txt and save it. In order to use these two classes we had to import them by specifying the package names they belong to. This informs the compiler where to find the actual code for these classes. Often we will need to use several classes from the same package (as with Java applets). In such a case we could use the wildcard character �*� at the end of the import statement like so: import java.io.*; However, it is recommended (and your instructor may even demand) that you import each class you are using separately. This may add a few lines to your program, but a quick glance at the import statements at the top of the class would provide you with a list of the exact classes you are using in your code. There are many packages available in the Java language, each of which contains classes that deal with a specific field. For example, the java.lang package contains the Math, Integer, Double and String classes, among others. The Math class contains only static methods for mathematical computations while Integer, Double and String contain methods that manipulate objects of the respective types as well as a few static methods. By the way, since the java.lang package is used so often it is automatically imported to any program. The java.io package includes classes and methods that handle input and output, etc. If you go to the Java API documentation page at
http://java.sun.com/j2se/1.4.1/docs/api/index.html you will find a list of all the available java packages. Go ahead, take a look and browse through the various packages. Note that the naming convention used in Java is to begin package names with a lower case letter. Two different classes with the same name? When you hear your friend say �I had coffee with the President yesterday,� how can you tell whom your friend had coffee with? You know it was a president of something, but who was it? Was it the President of the United States? The President of the University? Perhaps the President of a foreign country? The truth is that with such a statement you can only know which president it is according to the context of the conversation. Similarly, we may have two or more classes that have the exact same name but describe totally different objects. Consider the following two classes: /** This class describes the fruit apple. */
public class Apple
{
public Apple() {
System.out.println("Picking an apple from the tree.");
}
public String toString() {
return "I am a tasty red apple. No worms here.";
} }
/** This class describes the company Apple. */
public class Apple
{
public Apple() {
System.out.println("Welcome to Apple.");
}
public String toString() {
return "Apple\n" + "1 Infinite Loop\n"
+ "Cupertino, CA 95014";
} }
Both these classes have the exact same name. Since we were also trying to keep these classes short and simple, they even contain very similar code. But the fact of the matter is that these two classes describe totally different objects. In addition, when your professor asks you to write a program that finds the sum of 20 numbers and you choose to call the class Sum, what will happen if several other students will give their class the same name? Though a short homework assignment does not pose a problem, what if you were writing a program for commercial purposes and it had the same name as an already existing class written by someone else? This is where packages come in handy. In our example we can create two different packages - fruit and companies, and make sure that each package contains the corresponding Apple class. This way we can refer to the Apple class we want to use by stating fruit.Apple or companies.Apple. Here�s a picture of our two packages: Note that both packages have a class called Apple but by looking at the package we know exactly which Apple class we are using. This is similar to our friend saying �Yesterday, while I was visiting the White House, I had coffee with the President� verses �Yesterday, while I was visiting San Jose State, I had coffee with the President.� Context makes life a bit simpler. It is important to note that if we import both Apple classes by stating at the top of our program import fruit.Apple;
import companies.Apple;
then the statement Apple myApple = new Apple();
Will cause an error, since the compiler will not know which Apple class we are referring to. Usually it is better to avoid such situations of having two classes with the same name in our program. But if we cannot escape it, we need to refer to each class using the package name - fruit.Apple or companies.Apple. My own package In order to build a package for your own code you have to do 3 things. Let�s assume that we are building a package called bands and in it we will put 3 classes - U2, REM and EddieFromOhio. Here is what we need to do: Create a sub-directory called bands. At the top of each of the three classes, U2, REM and EddieFromOhio, place the statement: package bands;
Place the three files, U2.java, REM.java and EddieFromOhio.java, inside the bands directory. Now all you have to do is to add the proper import statement at the top of any class in which you want to use any of the three classes - U2, REM and EddieFromOhio. Problem 2: (1.5 points) Let�s assume that you write a class called OutOfTime and you want to use objects of type REM. What is the proper import statement you need? Write your answer to a file called REM.txt and save it. Problem 3: (1.5 points) Suppose your classmate, Frodo, created the U2, REM and GratefulDead classes in a package called coolGroups, which is located inside a directory called rockNRoll. What is the complete path where these three classes are located, assuming that the rockNRoll directory is located in the root directory? Save your answer in a file called grateful.txt. The default package So far when writing our classes in the lab or as part of our homework, we never associated them with a package. In such cases the class is automatically associated with the default package. In the next lab we will use an Integrated Development Environment called Eclipse, where the default package will return. By the way, we could have inner packages. For example, let�s go back to the Apple class example. Inside the companies package we could have a package called hiTech and a package called groceries. Now the Apple class will be inside the hiTech sub-package while the class Safeway would be part of the groceries sub-package. Thus, we will import these two classes as follows: import companies.groceries.Safeway;
import companies.hiTech.Apple;
Also, the Safeway class will start with the statement package groceries;
Can you write the equivalent statement for the top of the Apple class? Problem 4: (3 points) Create a package called guitars. The guitars package has two sub-packages - electric and bass. The electric sub-package has two classes - Fender and Gibson. The bass sub-package has two classes as well - Warwick and MusicMan. Each of these classes should contain a constructor that prints a message, and a toString method (similar to the Apple classes above). Make sure to include all the proper code you need in order to create the packages. Submit a folder called guitars that will contain all the proper folders and classes for the guitars package. Do not submit any .class files. Archives Sometimes we create packages from multiple classes and the result a pretty big program. What happens if you want to e-mail that program to someone else but it is too big? What if you're just storing that program on your hard drive as back-up? In both cases, life would be much simpler if we had a way to reduce the program's size without changing the program itself. This is where archives come in. A file compression program can reduce the size of a file. For example, a compression program might replace the text: "it's a big big big big big big world" with the text: "it's a big^6 world" A decompression program performs the reverse substitution, thus restoring the file to its original form. An archive is a single file that contains several compressed files appended together. Programs like zip and tar can be used to create archives and to extract and decompress the files in an archive. The Java SDK comes with an archive creating/extracting tool called jar. The Java on-line tutorial has a chapter on using the jar tool located at: http://java.sun.com/docs/books/tutorial/jar/basics/index.html As an example, a directory called jlab\jartest contains .java and .class files for modeling banking transactions: Directory of D:\jlab\JarTest
10/08/03 01:28p . 10/08/03 01:28p .. 10/08/03 01:06p 578 Account.class 10/08/03 01:05p 308 Account.java 10/08/03 01:08p 364 Address.class 10/08/03 01:07p 95 Address.java 10/08/03 01:08p 436 ATM.class 10/08/03 01:04p 329 ATM.java 10/08/03 01:06p 507 Customer.class 10/08/03 01:06p 593 Customer.java 10/08/03 01:08p 511 Person.class 10/08/03 01:07p 205 Person.java 10/08/03 01:08p 358 Phone.class 10/08/03 01:07p 87 Phone.java 10/08/03 01:06p 698 Transaction.class 10/08/03 01:04p 370 Transaction.java Creating The cvf option of the jar tool is used to verbosely create an archive file: D:\jlab\JarTest>jar cvf bank.jar *
added manifest
adding: Account.class (in=578) (out=399) (deflated 30%)
adding: Account.java (in=308) (out=190) (deflated 38%)
adding: Address.class (in=364) (out=265) (deflated 27%)
adding: Address.java (in=95) (out=80) (deflated 15%)
adding: ATM.class (in=436) (out=319) (deflated 26%)
adding: ATM.java (in=329) (out=185) (deflated 43%)
adding: Customer.class (in=507) (out=349) (deflated 31%)
adding: Customer.java (in=593) (out=229) (deflated 61%)
adding: Person.class (in=511) (out=339) (deflated 33%)
adding: Person.java (in=205) (out=142) (deflated 30%)
adding: Phone.class (in=358) (out=260) (deflated 27%)
adding: Phone.java (in=87) (out=78) (deflated 10%)
adding: Transaction.class (in=698) (out=438) (deflated 37%)
adding: Transaction.java (in=370) (out=202) (deflated 45%)
Viewing The tf option is used to display the contents of an archive:
D:\jlab\JarTest>jar tf bank.jar
META-INF/
META-INF/MANIFEST.MF
Account.class
Account.java
Address.class
Address.java
ATM.class
ATM.java
Customer.class
Customer.java
Person.class
Person.java
Phone.class
Phone.java
Transaction.class
Transaction.java
Extracting The xf option is used to extract and decompress an archive: jar xf bank.jar Problem 5: (3 points) Create an archive called guitars.jar containing all of the files in the guitars package. Compare the size of the archive with the total sizes of all of the decompressed files it contains. What is the difference between them? Save your answers in a file called size.txt. Running The java virtual machine can execute an archive if the archives manifest (i.e. table of contents) contains a line specifying which class in the archive is the main class. In our banking example ATM is the main class. What we need to do is create a file called mainclass.txt containing the single line: Main-Class: ATM We must make sure this line is terminated by a newline character (i.e., a carriage return). We then create a new jar file with the contents of mainclass.txt added to the manifest: jar cmf mainclass.txt bank.jar *.java *.class
In JDK 1.2 and later, the java command can accept a jar file as input:
D:\jlab\JarTest>java -jar bank.jar
creating a new transaction.
creating a new person.
creating a new account.
creating a new customer.
creating a new address.
creating a new phone.
Lab submissions: Submit the following files to the instructor. (Follow your instructor's guidelines to submit the files.) classes.txt REM.txt grateful.txt A folder called guitars that will contain all the proper folder and classes for the guitars package. guitars.jar size.txt Do not submit any .class files.