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.
- public
- private
- protected
- 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.