Computer Science 212 - Tutorial 2
Text file I/O, arrays, static methods, and JavadocCopyright © 2005 by Dorothy L. Nixon. All rights reserved.
Table of contents
- A simple static method example
- Object references, constructors, and text file input
- Arrays and text file I/O
- Methods as a means of eliminating redundant code
- Selection sort, and more about methods and method calls
- Example using a boolean method
- The Java Library documentation
- Some public constant fields
- Javadoc
Example files (download as ZIP file here)
- ClassifyChar1.java
- ConsoleInput.java
- CountOddFile1.java
- CountOddFile2.java
- ExamScores1A.java
- ExamScores1B.java
- ExamScores2.java
- MathMethodsDemo.java
- MathUtility.java
- SortingDemo.java
- SortingDemoMessages.java
- TestASCII.java
- TextFileInput.java
- TextFileOutput.java
- ValueParametersDemo.java
- ExamScores.txt
- numbers.txt
The example files may be downloaded in a ZIP file here.
Tutorial on text file I/O, arrays, static methods, and Javadoc
- A simple static method example
Let us now consider two examples involving static methods, i.e. methods which do not define behaviors of objects but are just routines.
Look first at MathUtility.java, containing class MathUtility, which does NOT contain a main method and thus is not a program. Rather, it contains two methods that can be used in a program whose main method is in some other file, such as ValueParametersDemo.java. Observe the method call in following statement in ValueParametersDemo.java:
double result = MathUtility.power(enteredBase, enteredExponent);The above statement contains a call to one of the two power methods defined in class MathUtility. Note that a class can contain definitions of more than one method with the same name, provided the parameter types are different. Having more than one method with the same name is known as method overloading. (Some programming languages allow method overloading, while others do not.)
Consider now the the power method with the following heading:
public static double power(float base, int exponent)This method takes two parameters named base and exponent. Parameters are variables which are declared within the parentheses of a method heading and receive their values when then the method is called. When the method begins executing, the parameters are first assigned the values of the arguments in the method call. For example, suppose the power method were called as follows:
System.out.println(power(2, 3));In this case the parameter base would be set equal to 2 and the parameter exponent would be set equal to 3.
Consider now the body of the method. If the exponent is non-negative, the power can be computed via a cumulative product with an initial value of 1, whch is then multiplyed by the base exponent time:
double product = 1; for ( int i = 0; i < exponent; i++ ) product *= base;The variable product is a local variable. A local variable is declared inside the body of a method, in contrast to a parameter, which is declared inside the parentheses of the method heading.
If the exponent is negative, an equivalent power can be computed the same way if we first change the sign of the exponent and take the reciprocal of the base, as follows:
if ( exponent < 0 ) { exponent = 0 - exponent; base = 1 / base; }At the end of the method body is the return statement:
return product;A return statement does two things: (1) It ends execution of the method, and (2) communicates a value back to the part of the program which called the method. The returned value must be of the type specified in the method heading, in this case type double. When the method is called, the method call itself is an expression with a value equal to the returned value. For example, the following method call:
power(2, 3)is an expression whose value is 8.
- Object references, constructors, and text file input
Compile CountOddFile1.java by typing:
javac CountOddFile1.javaand run it as follows:
java CountOddFile1 numbers.txtwhere numbers.txt is a data file containing a column of integers, one number per line.
The program reads numbers from the data file using an object of class TextFileInput, defined in TextFileInput.java.
You'll need to use objects of class TextFileinput in some of your projects. Just make sure that a copy of TextFileInput.java is in the same directory/folder where your program is, and you'll be able to able to use it in your program. (You don't need an import statement.) Note that TextFileInput.java is compiled automatically when you compile CountOddFile1.java, and you don't need an import statement for it, provided that it is in the same directory.
Like class ConsoleInput which we used earlier, class TextFileInput has a readLine method. The readline method of class TextFileInput reads a line from a text file, whereas the readLine method of class ConsoleInput reads a line typed by the user in the console (e.g. the DOS window). Another important difference between the two readLine methods is that the readLine method of class ConsoleInput is a static method, whereas the readLine method of class TextFileInput is an instance method because we will be using an object of class TextFileInput to read the file.
Why do we bother to use an OBJECT of class TextFileInput, rather than just some routines as we did in the case of class ConsoleInput? Because, if a program were to use multiple data files for input, it would then be convenient to use multiple TextFileInput objects, one managing each file.
You are not expected to understand everything in the file TextFileInput.java. For now, simply note that it does NOT contain a main method and thus is not a program. Rather, it is used solely to define objects of class TextFileInput, which can be used in other programs.
Let's now examine how it is used in CountOddFile1.java. First, an object of class TextFileinput is instantiated (created) and assigned to an object reference of type TextFileinput, as follows:
TextFileInput dataFile = new TextFileInput(args[0]);On the right side of the assignment statement we create the TextFileInput object using a special method called a constructor, which has the same name as the class. The new object is then assigned to dataFile, which itself is not an object but an object reference that could be assigned to point to any object of class TextFileInput.
A key difference between Java and C++ is that, in C++, we can create an object by simply declaring it. For example, in C++, declarations like the following are permitted and would both succeed in creating an object if the corresponding constructors TextFileInput() and TextFileInput(String) were both defined:
TextFileInput dataFile; TextFileInput dataFile(args[0]);In Java, on the other hand, you cannot create an object by simply declaring a variable of the class type. In Java, declaring a variable of a class type creates just an object reference without yet making it point to any object. It must then be given an object to point to, e.g. via an assignment statement. Alternatively, an object reference can be assigned the value null (zero), meaning that it is not pointing to any actual object.
In the Tutorial on some Java basics, we saw two types of methods, static methods and instance methods. Constructors are a third type of method. Constructors differ from instance methods in that a constructor is used to create a new object of the constructor's class, whereas an instance method defines a behavior of an already-existing object. In Java, a call to a constructor is always preceded by the keyword new. A class can have multiple constructors with different parameter lists.
Class TextFileInput has just one constructor. It takes an argument of type String, representing the filename of the input text file. In our present example, the filename has been input via a command-line argument.
Once our TextFileInput object has been created, it will then be used to manage input from the text file. We will use it to read text from the file, one line at a time, by calling the TextFileinput object's readLine method:
String line = dataFile.readLine();The first time the readLine method is called, it reads the first line in the file. The second time it is called, it reads the second line, and so on. Each time it reads the next line after the line it read the previous time it was called.
Note that the readLine method of class TextFileInput is an instance method, i.e. it pertains to a specific object of class TextFileInput, whereas the readLine method of class ConsoleInput was a static method, i.e. it did not pertain to an object of class ConsoleInput.
The variable line is an object reference. As we have seen, object reference is a memory location which contains NOT the object itself, but a pointer to the actual object, which resides elsewhere in memory. An object reference can be assigned to contain either (1) a pointer to an actual object, or (2) null (zero), a special value to indicate that it is not currently pointing to any actual object.
The readLine method reads one line from the file, always the next line after what it read the previous time it was called. Each time it reads a line successfully, it returns the line of text as an object of class String. But what happens after the readLine method has read the last line of the file? It then returns the special value null, rather than an actual String object, to indicate that there are no more lines of text to be read.
In CountOddFile1.java, note that the readLine method is called both before the while loop and at the end of the loop body. In either case, it is called just before the condition is tested. The while loop condition tests whether we have reached the end of the file, as follows:
while ( line != null )The condition is false if we have reached the end of the file, true otherwise. Thus the loop reads the file one line at a time until the end of the file is reached.
CountOddFile2.java is another version of the program which does the exact same thing but uses a conditional break statement, thereby eliminating the need for two separate readline statements.
- Arrays and text file I/O
We will now look at three versions of a program which reads numbers from a text file into an array, and then modifies the contents of the array and outputs the modified array contents to another text file.
We will look at a program which reads a text file ExamScores.txt, then computes the maximum score, then curves the grades by moving all the grades up by the same amount such that the person with the highest score gets 100, and then outputs the curved scores to a text file Curve.txt. Below are the three versions:
In all three versions, we use a TextFileInput object to read from an input text file, as we did in the previous example.
We also use an object of class TextFileOutput, defined in TextFileOutput.java, to generate our output text file. Class TextFileOutput has print and println methods which are similar to System.out.print and System.out.println except that they are intended for output to a file rather than to the console.
However, the print and println methods of class TextFileOutput do NOT send text directly to the file. Instead, they send text to a buffer in memory. Our program must then call the flush method to send text from the buffer to the file itself.
Why? So that we can make a program run more efficiently by reducing the number of times it has to access the disk. Because a disk drive has electromechanical moving parts, accessing a disk is a much, much slower operation than accessing memory, which is purely electronic. Therefore, to avoid slowing down the program too much, we want it to access the disk as few times as possible. Thus our program contains only one call to the flush method, near the end of the program, whereas it calls the print and println methods many more times.
As mentioned earlier, our present example also uses an array. In all three versions of our program, the length of the array is set to be equal to MAX_NUMBER_OF_SCORES, where MAX_NUMBER_OF_SCORES was declared earlier as a constant:
final int MAX_NUMBER_OF_SCORES = 40;Note that, in Java, we use the keyword final to declare a constant (whereas in C++ we would use const).
Let's now consider the array itself. In all three versions of our program, the array is declared and instantiated as follows:
int[] scores = new int[MAX_NUMBER_OF_SCORES];An alterntive syntax, which the Java compiler would also accept, is the following:
int scores[] = new int[MAX_NUMBER_OF_SCORES];In Java, arrays are treated as objects, except that they are not defined by classes. As is the case with other objects, an array cannot be created by simply declaring it. In C++ we could do the following, which is NOT allowed in Java:
int scores[MAX_NUMBER_OF_SCORES];In our present Java example, scores is an array reference, not the array itself. The array itself must be instantiated (created) in a separate expression, as we have done on the right-hand side of the assignment statement. It is then assigned to the array reference on the left-hand side of the assignment statement.
In all three versions of the program, we use a while loop to read each line of the file into an element of the array, each time reading the next line of the file into the next element of the array. However, let's not assume that we know in advance exactly how many numbers will be in the file. Our program is written on the assumption that the number of numbers in the file is not greater than MAX_NUMBER_OF_SCORES, but it might be less. Therefore, our array will likely be partially-filled, meaning that only a portion of the array will contain numbers that have been read from the file.
Therefore, the program needs to keep track of exactly how many numbers have actually been read into the array, so that, when the program does things with the array later, it processes only the subarray (portion of the array) containing the numbers that were read and ignores the rest of the array. To that end, in the while loop, our program uses the variable lengthFilled to keep track of how many numbers have been read into the array. Later in the program we have a for loop with the following heading:
for ( int i = 0; i < lengthFilled; i++ )which processes only the filled portion of the array, ignoring the rest of the array.
ExamScores1A.java and ExamScores1B.java differ from each other in that the while loop in ExamScores1B.java uses a break statement and thereby eliminates the need for two separate readLine statements.
ExamScores1A.java and ExamScores1B.java both ignore the question of what happens if the input file contains too many numbers to fit into the array. Try modifying either of these programs so that MAX_NUMBER_OF_SCORES is 4 rather than 40. (Recall that our sample data file ExamScores.txt contains 5 numbers.) Observe that the program crashes, in a rather ugly fashion, with an ArrayIndexOutOfBoundsException.
In ExamScores2.java, the ArrayIndexOutOfBoundsException is prevented using the following compound condition in the while loop which reads lines of the file into the array:
while ( lengthFilled < scores.length && line != null )After the while loop is finished executing, our program then checks to see whether the end of the file has been reached. If not, then there were too many numbers in the file to fit into the array, which means the program will be unable to perform the desired computation involving all the numbers in the file. So, in that case, the program quits with an error message at that point.
Unlike arrays in C++, arrays in Java know their own length. The length of an array can be accessed via an expression of the form arrayReference.length, as was done with scores in the above while loop condition.
In this program, the String object reference line is declared and initialized before the while loop:
String line = in.readLine();thereby necessitating a second readLine statement inside the loop as well, at the end of the loop body, as we did in ExamScores1A.java, rather than using a break statement to enable us to use a loop with just one readLine statement inside the loop at the beginning, as we did in ExamScores1B.java. In ExamScores2.java, the variable line needs to be declared and initialized before the while loop, because the program will be testing the value of line immediately AFTER the while loop:
if ( line != null )If we were to declare or initialize the variable line inside the loop instead of before the loop, then the compiler would complain about our attempt to test its value after the loop. Had we declared the variable inside the loop, the problem would be that the variable's scope is limited to the loop. On the other hand, had we declared it before the loop but then given it its first value inside the loop, then the problem would be that the variable line "might not have been initialized" before the loop is finished executing, because a while loop might not be executed at all if the condition is false the first time it is checked. Recall that the Java compiler is very fussy about ensuring that a local variable has been given a value before the program can attempt to use the variable in any way that assumes it already has a vlaue.
In addition to text file input, all three versions of this program also do text file output. To that end, each program uses an object of class TextFileOutput, defined in TextFileOutput.java. Note that class TextFileOutput is not a program and thus does not contain a main method. Its sole purpose is to define a type of object, which can be used within other Java classes.
An object of class TextFileOutput is instantiated as follows:
TextFileOutput out = new TextFileOutput(outputFileName);Class TextFileOutput has print and println methods similar to System.out.print and System.out.println except that they output to a text file rather than to the console (DOS window). Note that the print and println methods are instance methods of class TextFileOutput.
Actually, the print and println methods of class TextFileOutput do not output directly to the file but, instead, output to a buffer -- an array of characters, stored in memory, which will later be output to the file itself. To move text from the buffer to the file itself, you must then call the flush method, another instance method of class TextFileOutput.
out.flush();Why is output done in two steps (print and/or println, and then flush)? To reduce the number of times that the program actually has to access the disk. Because a disk drive has electromechanical moving parts, accessing a disk is much slower than accessing a buffer in memory, which is purely electronic and can be done at close to the speed of light. Therefore, for maximum efficiency, a program should access the disk as rarely as possible. So, if there are multiple calls to print or println, it is more efficient to do these multiple outputs to a buffer in memory and then, when we are finished outputting to the buffer, send it all at once to the disk via just one call to the flush method.
Whenever you do text file output, always remember to call the flush method after you have finished your entire series of calls to print and println. If you forget to call the flush method, your output file will be blank or at least incomplete.
Finally, when you are finished with either text file input or text file output, it is a good idea to call the close method, which releases the file for use by another TextFileInput or TextFileOutput object later in the program. In this particular example, the calls to the close method are not really needed, because the files are NOT re-used later, but calls to the close are included in our present example programs just for completeness.
- Methods as a means of eliminating redundant code
Look again at the source code of ExamScores2.java and compare it with ExamScores1A.java and ExamScores1B.java. This program prints numbers to a file Curve.txt in two right-justified columns. In ExamScores1A.java and ExamScores1B.java, which both have only a main method, the right-justification is done using two almost-identical pieces of code within a for loop in the main method:
// Print original score in a right-justified column: String scoreText = Integer.toString(scores[i]); for ( int j = scoreText.length(); j < columnWidth; j++ ) out.print(" "); out.print(scoreText);and:
// Print curved score in a right-justified column; String curvedScoreText = Integer.toString(curvedScore); for ( int k = curvedScoreText.length(); k < columnWidth; k++ ) out.print(" "); out.println(curvedScoreText);Both pieces of code insert enough leading spaces in front of the string representation of a number so that the leading spaces plus the characters in the number's own string representation will take up a total of columnWidth character positions.
In ExamScores2.java, we avoid having two separate but almost-indentical pieces of code by consolidating them into one method which does the right-justifying of numbers:
private static String rightJustify(int numberToPrint, int width) { String numberText = Integer.toString(numberToPrint); for ( int i = numberText.length(); i < width; i++ ) numberText = " " + numberText; return numberText; } // method rightJustifyThe rightJustify method is called twice in the main method, in the following loop:
// Print original scores and curved scores // to output text file: for ( int i = 0; i < lengthFilled; i++ ) { // Print original score in a right-justified column: out.print(rightJustify(scores[i], columnWidth)); // Calculate curved score; int curvedScore = scores[i] + curveUp; // Print curved score in a right-justified column; out.println(rightJustify(curvedScore, columnWidth)); } // for iNote the syntax of the method calls:
methodName(arguments)rather than
ClassName.methodName(arguments)If a method is being called within the same class where it is defined, then the class name and dot are not needed.
- Selection sort, and more about methods and method calls
Compile SortingDemo.java and run it using the filename numbers.txt as a command-line argument. The program generates a new text file sorted-numbers.txt containing the same numbers as numbers.txt, but arranged in ascending order. In other words, it sorts the numbers.
SortingDemo.java defines a main method and three other static methods, including selectionSort, which sorts an array of short integers. In Java, values of type short take up 16 bits, whereas values of type int takes up 32 bits.
There are many algorithms for sorting. In this program we use selection sort, which is not very efficient but is easy to understand.
for ( int i = 0; i < length - 1; i++ ) { // Find the lowest-valued element in // the subarray from index i up to // index length - 1 int indexLowest = i; for ( int j = i + 1; j < length; j++ ) if ( array[j] < array[indexLowest] ) indexLowest = j; // Put the lowest-valued element at // index i, swapping if necessary: if ( array[indexLowest] < array[i] ) { short temp = array[indexLowest]; array[indexLowest] = array[i]; array[i] = temp; } } // for iThe basic idea is this:
On the first iteration of the outer loop, we find the smallest number in the array and put it at position 0, swapping it with the number at position 0 if the smallest number wasn't already there. On the next iteration, we find the smallest number in the remaining portion of the array and put it at position 1, swapping if necessary. On the next iteration, we find the smallest number in the remaining portion of the array and put it at position 2. And so on. Each time through the outer loop, the inner loop searches the remainder of the array for the smallest element, which, in the outer loop, is then compared with the element at position i and swapped if necessary.
Our method selectionSort has the following heading:
static boolean selectionSort(short[] array, int length)Note the syntax of the array parameter declaration. The Java compiler would also accept the following C++ derived syntax too:
static boolean selectionSort(short array[], int length)The integer parameter length specifies the length of the filled (meaningfully defined) portion of the array, in case the array is not completely filled.
Becuase the selectionSort method does not return a value, its heading contains the keyword void where it would otherwise indicate the type of the returned value.
This program also contains two other static methods, inputFromFile and outputFromFile.
The inputFromFile method takes two parameters, a filename (of type String) and the array into which numbers from the file will be read. Since the array may be partially filled, the inputFromFile method returns the length of the subarray containing the numbers that have been read.
The outputToFile method takes three parameters, (1) a filename (of type String), (2) the array from which numbers will be outputted to the file, and (3) the length of the subarray containing the numbers that will be outputted. The outputToFile method does not return a value; hence its heading contains the keyword void.
Note that if a method returns a value, the method should usually be called in such a manner that the returned value can be used somehow. For example, consider the following statement in the main method of class SortingDemo:
int subArrayLength = inputFromFile(inputFileName, numbersArray);Here, the call to inputFromFile is on the right-hand side of an assignment statement. The returned value is assigned to the variable subArray, which is then used in the following two subsequent statements:
selectionSort(numbersArray, subArrayLength); outputToFile(outputFileName, numbersArray, subArrayLength);Both of the above statements are calls to void methods. Observe that a call to a void method is a statement unto itself, not an expression that can be part of a larger statement. On the other hand, a call to method which returns a value is itself an expression with a value (namely the value that was returned) and hence can and should be used as part of a larger statement.
- Example using a boolean method
For another example of a program using using static methods, see TestASCII.java. This file is a program containing two methods, the main method and another static method, containsNonAscii.
Compile TestASCII.java and run it. First, run it with any the filename of any ASCII text file as a command-line argument, such as the file TestASCII.java itself:
java TestASCII TestASCII.javaThe program will then print out a message saying that the file is all-ASCII. On the other hand, try running the program with an input file that is NOT an ASCII text file, such as the Jave byte code file TestASCII.class:
java TestASCII TestASCII.classThe program will then print out a message saying that the file is NOT all-ASCII.
Look now at the source code. In TestASCII.java, the main method reads the file one line at a time, testing whether each line contains any non-ASCII characters. If none of the lines contain any non-ASCII characters, then the entire file doesn't contain any non-ASCII characters either. Each line is tested via a call to the containsNonAscii method, which checks whether any of the characters on the line are non-ASCII. Note that the containsNonAscii method returns a value of type boolean, a primitive data type with only two possible values, true and false. (In Java, boolean is a full-fledged data type unto itself. Other primitive data types do not convert automatically to boolean, as they do in C++.)
- The Java Library documentation
We will now look at the library documentation for Java 1.4.2. (To find it on java.sun.com, click on "API specification" in the left hand column, then click on "J2SE 1.4.2" in the middle column.)
You will be viewing a page with frames. In the main frame is a list of all the packages in the Java library, including javax.swing, among many others.
The most important library package of all is java.lang, which contains some of the most commonly-used classes such as String, System, Math, Object, and the wrapper classes for the primitive data types. You haven't seen it mentioned in import statements because java.lang is the only package which is automatically imported into every Java program. (Note: java.lang.reflect is a separate package from java.lang.)
Click on the link java.lang. You will be taken to a list of all the classes, interfaces, Exceptions, and Errors in the java.lang package. Don't worry about the interfaces, Exceptions, and Errors for now. Focus only on the classes, which are listed below the interfaces and above the Exceptions. Note that the classes include (among others) the wrapper clssses for the primitive data types, such as class Integer, Float, Double, and Character. It also includes our old friend class String.
In the list of classes, click on String. You will be taken to a document which, among other things, contains descriptions of all the methods in the String class.
Scroll down in the file. You will encounter, first, a description of class String as a whole. You're not expected to understand the entire description at this point in your studies. Below the description of class String is a "Field Summary." Don't worry about this for now, either.
Below the "Field Summary" is a "Constructor Summary." Note, however, that you don't usually need to use constructors to create String objects. Instead, you have usually created String objects in other ways.
Below the "Constructor Summary" is a "Method Summary," listing all the methods in class String. The methods are listed in alphabetical order, and the first one is charAt. Click on the charAt link. You will be taken to a longer description of the charAt method. You should be able to understand MOST (though not necessarily all) of this description, having read our tutorial material so far. Observe that the detailed description includes the complete heading of the charAt method, as it appears in the source code for class String. Observe that the charAt method takes a parameter of type int and returns a value of type char.
When you are finished reading the description of charAt, click your browser's "Back" button to return to the "Method Summary." Use the method summary to look up descriptions of the following methods: length, the two substring methods, the two startsWith methods, the endsWith method, the two regionMatches methods, and the various indexOf and lastIndexOf methods. (A substring is a String obtained by taking part of another String.) Click on each method's name to look up a more detailed description.
In the descriptions, "this string" refers to the particular String object for which an instance method is being called.Note that there is more than one substring method and more than one startsWith method, where the different methods with a given name have different parameter lists. Having more than one methond with the same name is known as method overloading.
In the assignment, you will be using the version of the compareTo method that takes a String parameter. Make sure you understand what that method does.
Now click your "Back" button to return to the list of classes in the java.lang package.
Then click on class Character, the wrapper class for the primitive data type char. Do not confuse class Character with classes Character.Subset and Character.UnicodeBlock.
Scroll down the page for class Character. The first thing you will encounter is a description of the class. Again, you are not expected to understand the entire description at this point in your studies.
Below the general description is the "Nested Class Summary." A nested class is a class defined inside another class. Do not worry about them for now, except to note that if the Java compiler ever complains to you about a "nested class" or an "inner class" when you hadn't written one, it probably means you have a curly brace problem.
Below the "Inner Class Summary" is the "Field Summary." You will learn about fields later in this course, but do not worry about them for now.
Below the "Field Summary" is the "Constructor Summary." Class Character has only one constructor, which you have already used in a previous assignment.
Below the "Constructor Summary" is the "Method Summary." In the "Method Summary," scroll down to the method isDigit (not to be confused with the method digit). Click on the isDigit link for a detailed description.
The isDigit method determines whether a character is a digit. Note that the isDigit method recognizes not only ASCII digits, but also digits in all of the many languages supported by Unicode. (For a review of what ASCII and Unicode are, see the section More about characters and strings in Java in the Tutorial on some Java basics.)
For an example of how the isDigit method can be used, compile ClassifyChar1.java and run it using a single command-line argument of up to 15 characters including a few digits, a few capital letters, a few lower-case letters, and a few punctuation marks, and observe the displayed classifications of the characters. The program uses three methods of class Character, as follows:
if ( Character.isDigit(x) ) System.out.println("digit"); else if ( Character.isUpperCase(x) ) System.out.println("capital letter"); else if ( Character.isLowerCase(x) ) System.out.println("lower-case letter"); else System.out.println("non-alphanumeric");where x is a variable of type char.
Observe that a call to the isDigit method is being used as the condition of an if clause. Recall that the condition of an if clause must be either true or false. In Java and many other programming languages, true and false are considered to be values of a primitive data type known as type boolean. Expressions of type boolean can have only two possible values, true and false. In Java, a boolean value is stored as a single bit, which can have only two possible states.
In the Java documentation for class Character, the isDigit method has the following heading:
public static boolean isDigit(char ch)Recall that the word to the left of the method's name is the type of the returned value, if the method returns a value. Thus, isDigit returns a value of type boolean.
In your browser, click the "Back" button to return to the "Method Summary." Then click on links to detailed descriptions of the methods isLetter, isLowerCase, and isUpperCase. These methods, too, return values of type boolean. Two of these methods are used in our application ClassifyChar1.java.
Also in the java.lang package, look now at the Math class, which contains lots of static methods implementing various commonly used mathematical functions such as square root (sqrt) and trigonometric functions. For an example of the use of some Math methods, see MathMethodsDemo.java.
- Some public constant fields
In addition to using some static methods of the Math class, MathMethodsDemo.java also uses the public static constant Math.PI, listed in the Java library documentation under the "Fields" of the Math class. Later in the course you'll be taught more about fields, including both static variables (Java's nearest equivalent of global variables in C++) and instance variables (which store an object's data).
Also in the java.lang package, look now at the Java library documentation for the System class. It has the following public static constants, listed as fields: err, in, and out. Note that a field can be of any kind of data type: primitive, array, or object. System.err, System.in, and System.out are all object references. System.out is a reference to an object of class PrintStream.
Is System.out.println a static method or an instance method? You might at first have guessed that it is a static method, because System is the name of a class, not an object reference. However, as we have seen, System.out is an object reference. So, the println method is called using the syntax:
objectReference.methodName(arguments)System.out.println is an instance method of class PrintStream.
System.out is known as the standard output stream. There can also be a separate output stream just for error messages, if the programmer so chooses. System.err is the standard error stream. By default, System.err sends its output to the same console as System.out, though they can be reset to send their output to different places. (You will not be taught how to do this in this course.)
For an example of the use of System.err, see SortingDemoMessages.java. (This program will be discussed in more detail in Tutorial 3.)
We've seen some examples of public static constants. What about instance constants? For an example of a public instance constant, recall that the length of an array is obtained via an expresson of the form:
arrayName.lengthIn Java, arrays are treated as a kind of object, although they are not defined by classes. The length of an array is an instance constant.
Similar to the notation for instance methods vs. static methods, non-private instance variables (including instance constants) can be accessed via the notation:
objectReference.fieldNamewhereas non-private static variables (including static constants) can be accessed via the notation:
ClassName.fieldName
- Javadoc
In your DOS window, in the directory containing your example files, type:
javadoc *.javaA bunch of HTML files will be generated, creating documentation for whatever Java files happen to be in that directory, similar to the documentation you saw on the Sun website. Click on the file index.html. In the left frame will be a listing of all the classes defined by the source code files. Click on the links for the following classes:
- ConsoleInput
- ExamScores2
- MathUtility
- SortingDemo
- SortingDemoMessages
- TestASCII
- TextFileInput
- TextFileOutput
Observe how the HTML pages for classes ConsoleInput, MathUtility, TextFileInput and TextFIleOutput document how one can use those classes and their methods in a larger program.
On each of the HTML pages for a given class, at the top is a general description of the class. Below that is a method summary. Then, below the method summary, taking up most of the page, is a detailed description of each method. Observe the nicely formatted descriptions of (1) a function's parameters, if it takes any parameters, and (2) a function's return value, if it has a return value.
Look now at the comments in the following source code files:
- ConsoleInput.java
- ExamScores2.java
- MathUtility.java
- SortingDemo.java
- SortingDemoMessages.java
- TestASCII.java
- TextFileInput.java
- TextFileOutput.java
Above each class heading and method heading is a special comment which:
- begins with /**
- ends with */
- begins each line with *
- is positioned directly above a class heading or method heading, with no blank line - or anything else - separating the comment from the heading.
Such comments are called Javadoc comments. Like all comments in Java, they are ignored by the compiler. But they are recognized and used by Javadoc, the Java documentation generator.
In all your projects starting with Project 2, you will be required to use Javadoc comments. Look carefully at our examples to see how Javadoc comments are used.
In the Javadoc comments above some of the methods, observe the @param tag at the beginning of each description of a parameter. If a function takes more than one parameter, the Javadoc comment contains more than one @param tag, one for each parameter.
Also in the Javadoc comments above some of the methods, observe the @return tag for those methods that return a value.
Ignore the @throw tags for now. You'll learn about those later.
Above each method, the comment begins with a general description of the function. The tags are all placed after the general description.
Above the class heading there is a general description of the class followed by an @author tag. On your projects, next to the @author tag, you should put your name, last 4 digits of ID, and section number. (This information should also be included in a separate normal C++ comment at the very top of the first page.)
To see what the @author tag does, type in your DOS window:
javadoc -author *.javaNote that Javadoc comments are aimed at the USER of the file, not at the programmer who may need to modify the file later. Javadoc comments should tell you exactly what a class or method does for you, but not how it does it. If your program also needs to contain comments of interest only to the programmer, these should not be Javadoc comments, but instead should be normal C++ comments, usually inside a method.
Look now at the source code SortingDemo.java and SortingDemoMessages.java. These programs each have some private methods, whereas the Javadoc HTML files contain descriptions of only the public methods, not the private methods. To generate Javadoc HTML documents which describe the private methods as well as the public methods, type:
javadoc -private *.javaHowever, because Javadoc comments are aimed primarily at the user rather than the programmer, it is most common to generate Javadoc HTML files which omit the private methods.