Tuesday June 20, 2000


Quiz 11


1. What are the five primary components of a class definition?

2. What statement is used to produce output?

3. What package must be imported to use that statement? (Hint: Trick question)

4. What are the two classes that are used to get input from the user?
























Today we will look more closely at the structure of a Java file to gain a better understanding of how Java works.

You have probably noticed that when we open a new file in JBuilder sometimes it places a statement like the following on the first line.

package untitled;
Recall that a package is a collection of related Java classes. For example, the java.io package is a collection of I/O related classes. The syntax of that package name means that there is a directory called java and inside that directory another named io. Inside that directory are class files.

Whenever we use a package statement in our program, Java assumes that we are creating a new package. Every Java program we write that has the statement package untitled; is assumed to be in the untitled package.

There is a rule associated with creating files with package statements. Any program that includes the statement package untitled; must be placed within a directory called untitled. So whatever the name of the package is, it must be the name of the directory where we store the program.

The next statement which is normally included in a Java program is the import statement. We can use as many import statements as we want. The syntax of the import statement is similar to the following.

import a.b.*;
This instructs the compiler to locate a directory called a, and inside that directory locate a directory called b, and then load all of the class files it finds in that directory.

Now a natural question to ask is where will the compiler begin to search. The answer to this question is the CLASSPATH.

In most operating systems, there are certain variables known as environment variables. One of the standard environment variables is called the PATH.

When you ask the operating system to execute a program, for example, javac, the the operating system will search the PATH. The PATH is a list of directories in which executable programs may be found. On Windows systems, the directories in the PATH are usually seperated by semicolons. On UNIX systems, the directories in the PATH are usually seperated by colons. When you make a call to javac, the operating system searches through each directory listed in the PATH until it finds an executable file called javac.exe. If it doesn't find that file in the PATH it reports an error.

The CLASSPATH is similar to the PATH environment variable, however the CLASSPATH lists a set of directories for the compiler to use to search for packages listed in the import statement. The CLASSPATH is also used by the interpreter to locate class files.

For example if try to execute our Java bytecode with the command

java MyClass
, then the interpreter will search through the CLASSPATH looking for the file MyClass.class. If it doesn't find it, it reports an error.

To see how this works, let's look at an example.

When I log into the system, the CLASSPATH is set to the directory /usr/local/java.

Within /usr/local/java I create a directory called demonstration.

Within that directory I write the following Java program in a file called Test.java and compile it.

package demonstration;

public class Test {

   public static int get_number() {
      return(2);
   }

}
Now I go to a different directory on the system and try to use this package. I type the following program in a file called MyTest.java.

import demonstration.*;

public class MyTest {
   
   public static void main(String[] args) {
      int number = Test.get_number();

      System.out.println("The number is " + number);
   }

}
Now I compile it, and there is no error. But now what happens if I try to run the interpreter. It reports that it can't find class MyTest even though it is in the directory I am in. What is the problem? The problem is that the CLASSPATH only contains the directory /usr/local/java. If I copy the file MyTest.class to /usr/local/java, then I can run execute the bytecode.

After the import statment we have the class header. Recall that the structure of a class header is

<access control keyword> class classname <extends A> <implements B,C, etc.>
There are four choices for access control keyword.
  1. public
  2. private
  3. protected
  4. none
These keywords tell the compiler how to treat a method or variable. We will discuss later the implications of each of these keywords. For now we will use the keyword public in most of our programs.

Recall that the extends clause is used to allow us to inherit properties from another class. If we use the header

public class A extends B
, then class A will inherit from class B all of the variables and methods that B allows (through access control keywords).

We are only allowed to extend one class. This is called single inheritance.

When we don't use an extends clause in our class header, we still extend the class Object. Object is at the top of the class hierarchy in Java. We will discuss in more detail later what this means.

Now let us look at the homework problem from yesterday.

Problem

The factorial of a number is a very important concept. The definition of the factorial of n, written n!, is the product of all integers from 1 to itself.

For example, 2! = 2*1, 3! = 3*2*1, 4! = 4*3*2*1, 5! = 5*4*3*2*1, etc.

Develop an algorithm for finding the factorial of a given number and translate that into Java code.
Solution

Notice that the way the definition is set up the most appropriate strucure to use would be repeated execution. In this instance a for loop would be more straightforward to use. Let us look at the algorithm we would use to solve the problem..

The first step is to get the number we wish to find the factorial of.

1. Get n.

Now notice that the factorial is an accumulated product. So it would make sense to set up a variable to hold this product. So let's introduce a variable called factorial. Note that since it will be use to accumulate a product we should initialize it to 1.

2. Introduce an integer called factorial and make its initial value 1.

Now we need a way to determine when we have included enough integers in the product. So let's introduce a variable called counter to determine this. Note that since 1 will not contribute to a product, we can start our counter at 2.

3. Introduce an integer called counter and make its initial value 2.

Now we will continue to increment counter until it is equal to n, and for each value of counter include it in the product.

4. As long as counter is less than or equal to n, include counter in the product and then increment counter by 1.

5. When this loop stops the value of the product, factorial, will be n!. Report n! to the user.

So now we have a plan. Let's implement each step of the plan in Java.

1. Get n.

In this problem, n is necessarily an integer.

InputStreamReader stream = new InputStreamReader(System.in);
BufferedReader keyboard = new BufferedReader(stream);

System.out.println("Please enter n");

int n = new Integer(keyboard.readLine()).intValue();
2. Introduce an integer called factorial and make its initial value 1.

int factorial = 1;
Now for steps 3 and 4 we can easily combine them into a for loop. Recall the structure of a for loop.
for (statement1;condition;statement2) {
   somestatements
}
We normally use statement1 for an initialization and statement2 for an increment. So let's implement steps 3 and 4.

3. Introduce an integer called counter and make its initial value 2.

4. As long as counter is less than or equal to n, include counter in the product and then increment counter by 1.

for (int counter = 2;counter <= n;counter++)
Now in the body of the loop we include counter in the product.

factorial *= counter;
Recall that this is a shortcut for saying factorial = factorial*counter.

Notice here that since I have only one line in the body of the for loop it is not necessary to use braces.

Now we report the value of factorial.

5. When this loop stops the value of the product, factorial, will be n!. Report n! to the user.

System.out.println("The value of " + n + "! is " + factorial);
Now let's put this together in a program.
import java.io.*;

public class Factorial {

   public static void main(String[] args) throws IOException {
      InputStreamReader stream = new InputStreamReader(System.in);
      BufferedReader keyboard = new BufferedReader(stream);

      System.out.println("Please enter n");

      int n = new Integer(keyboard.readLine()).intValue();

      int factorial = 1;

      for (int counter = 2;counter <= n;counter++)
         factorial *= counter;

      System.out.println("The value of " + n + "! is " + factorial);
   }

}
Now let us return to a problem we talked about a couple of weeks ago but didn't look at the solution.

Given a positive number, n, find all of the prime numbers less than or equal to n.

We discussed a method for determining whether or not a given number was prime. However, the way the method was set up would not be appropriate for this problem.

The reason for that is that the code was based on a single number n. We looked at all of the integers between 2 and n-1, and if we found a divisor, then we knew the number was not prime. But this does not lend itself well to this problem.

If we solved the problem the same way, then we would need to rewrite the code for every number between 2 and n-1. This is not very efficient.

The answer to this problem would be to make use of a method somehow.
Homework

Try to come up with a solution to this problem. You may make use of instance methods or class methods. Tomorrow a solution will be posted and we will discuss it.