Escolar Documentos
Profissional Documentos
Cultura Documentos
1
Compiler is software that converts a source code into the machine readable and executable code.
2
The distinction between a computer and appliance is simple. The computers have operating system
appliances do not.
3
There was an Oak tree in front of the building in which the programming team at Sun worked.
Penultimate name of Java came from that Oak tree.
4
Functions in Java are called methods.
5
These are the components of a Software Engineering design.
}
}
gives us the signatures or header of the main method for class NoCode. Every
stand-alone Java program6 – for it to do anything useful must have at least one
static method, which must be named main. The word public, once again is the access
specifier for the main method, and its return type is void, which means that method
returns nothing. The word static simply means that one can execute a static member
method of a class with out creating an instance of that class. The main method in
Java class has an argument list
6
Java applets do not need a main method. They work on a different mechanism.
FIG. 2.2A Class DoNothing will compile, but will not run as an
executable program as it is missing the main method
The class DoNothing has a minimal heading required by Java using the word class
and class Name (DoNothing). The body of the class is contained inside a pair of
facing curly braces. Notice that unlike C struct and C++ class, Java class definition
does not have a semi-colon after the right brace. This is because in Java a class is a
block and not a statement7. The class DoNothing will compile, but there is no main
method in it, therefore the JVM will give an error message, if one tries to interpret
the compiled byte-code DoNothing.class. Figure 2.2B gives the details of a static
void main method, which has same signatures in any including Java class.
7
In C++ the class definition is a statement of User-defined data type. Therefore the end of class
definition in C++ needs a semi-colon.
FIG. 2.3
System.out.print, the word System is a Java class, which is defined in the package
java.lang, which is automatically included (Figure 2.3). The word “out” represents a
publicly accessible, static final8 object of type class PrintStream. Notice that since
the field “out” is a public data member, it can simply be accessed using the dot
operator. The word print represents an overloaded method in class PrintStream,
8
The word final before a Java identifier means that the identifier will represent a constant entity. It
is analogous to const in C++.
Now what is the proof that package java.lang, which contains System, and other
utility classes actually got included automatically in our program in Listing 2.2?
Well first proof is in the output. Why would there be an output if our code somehow
did not include an output facility. The second proof lays in fact that in Listing 2.2, if
we replace the line
our output remains unchanged. The fully qualified name gives the full path to locate
a class, field (data) or a member method. We will discuss qualified and unqualified
names in more details later.
FIG. 2.4
There are three types of words as one would see in Java programs.
• Java reserved words,
• Name of the main method and its argument data type (String),
• Programmer created names for data objects, methods, etc.
Reserved words serve an important purpose in the programming languages. They
help the compiler do the conversion from source code to the machine language.
Since reserved words have special meaning in the language, they cannot be used for
any purpose, other than the purpose required by the language. When we accept the
program data from the user or we would process the program data and need to
store it internally; for both we needed to name locations in the memory to store all
these data. Since reserved words have special purpose in the language, they cannot
be used to name the memory elements to store program data. Therefore it becomes
important to know as to what are the Java reserved words. These are given below in
Table 2.1.
The keyword assert is available only in JDK 1.4. The keywords goto, and const are
not used. They are kept only to give meaningful compile error messages in case C++
programmer use them mistakenly. So far you have learned to use only few of the
Java reserved words. It would take you years of professional Java programming to
learn and use all of the Java reserved words. In the meantime the Appendix 2.1
gives detailed definitions of most of the Java reserved words. You may not be able to
understand the definition of all the reserved words at this time.
Not so in Java, which needs a specific data type assigned to the variable name. The
corresponding statements in Java will be;
int My_Integer = 10;
float My_Decimal = 10.0006;
Leaving out data type in Java for a local or class variable name, in which data will
be stored will cause a compile error. We do a survey of Java primitive data types in
the Figure 2.5 below:
FIG. 2.5
Java has the following primitive data types:
1. Integral (byte, char, short, int, and long).
2. boolean, which can only have values true and false.
3. Floating point (float and double).
Unlike C++, Java actually has a boolean data type, whose values are simply true and
false. Table 2.3 shows the possible values and size in bytes for various java
primitives on a Windows 9x system.
Type Size Minimum Value Maximum Value
(bytes)
char 2 Uses Unicode characters. Language dependent.
byte 1 -128 127
short 2 -32768 32767
int 4 -2147483648 2147483647
long 8 -9223372036854775808 9223372036854775807
float 4 +/- 1.4E-45 +/- 3.4028235E+38
double 8 +/- 4.9E-324 +/- 1.7976931348623157E+308
Figure 2.6 below shows the samples of some of Java primitive data types.
FIG. 2.6
Memory
Contents = ? ? ?
named
num1 and
of type
Size = 2 bytes short
FIG. 2.7
FIG. 2.8
Memory
Contents = 1000
named
num1 and
of type
Size = 2 bytes short
2. Two Line Method: The first statement declares the variable and the second
assigns data to it. For example consider the program statements below:
Multiple Declarations
Java allows one to use the comma operator and declare multiple variables of same
data type on one line. For example the following declarations are legal.
int val1,val2,val3;
int val4=22, val5=-10, val6;
However, understand that compile error will result if any attempt is made to use
val1, val2, val3, and val6 prior to their initialization.
Outputting a character
literal
Outputting a
string literal.
FIG. 2.9
The output of the above program will show that all constants are outputted literally.
That is why they are called literals or literal constants.
2. Named Constants – Some time a constant may be used in a program many times.
In that case using the key word final before we declare the data type, constant name,
and its value identifies its constant nature. Figure 2.10 below shows the examples of
declarations of named constants in Java.
Therefore it is easy to remember the simple rule: All local variables and
constants in Java must be initialized before they are used!
The above code snippet will print the following on the DOS console:
John H. Smith is 20 years old and has a gpa = 3.9 and he does well in
true/false type examinations.
Notice that using the property of overloaded operator plus (+) for String class, Java
is able to concatenate characters (such as space, alphabets, and punctuation marks),
integers (20 in above case), floating-point numbers (3.9), and boolean literals (true
and false) all into one string. It is however, required that on right hand side of
String concatenation expression, at least one of the data must be of String type. For
example expression given below is not a valid String concatenation expression and
will cause compile error!
Compile error. None of
String Not_A_String = ‘H’ + 25 + ‘L’; the expressions to be
concatenated are String
type!
Therefore one must remember the following String concatenation rule: At least
one of the expressions to be concatenated must be of String type! More
examples of String concatenation are shown in Figure 2.11 below.
FIG. 2.11
9
All wrapper classes need not have same type of parsing methods.
Invoking Name of
JVM class file to
be Argument list passed to the program.
executed! Argument0 is stored in array element
args[0] and so on.
The word java on comamnd line invokes the JVM to execute the main
method in class CommandLineArgs. All space separated entries after the class name
are considered command line arguments. Figure 2.12 shows as to how the command
line arguments are stored in the String array called args.
Listing 2.3 shows a toy example of parsing integer, and floating point command line
arguments into their numerical form. Let us assume that command line received the
following list of arguments:
John got 90 points with A grade and got gpa = 3.9 // Expression 1
The expression1 passed as command line argument has 11 strings in it. Therefore it
will occupy array indices from zero to 10 in the String array called args. The
mapping of command line of expression1 with the args array shown in Figure 2.12 is
as follows:
Argument0 = “John” stored in args[0];
Argument1 = “got” stored in args[1];
Argument2 = “90” stored in args[2];
………………………………………
……………………………………….
Argument10 = “3.9” stored in args[10];
Notice that in above list, the score 90 read from command line is first stored as a
String and not as an int! It holds true for 3.9 as well. It is stored as a String. Now, if
we just needed to only print values “90” and “3.9”, then we may not need to parse
them into their corresponding numerical values as strings can be printed by the
print or println methods of PrintStream class directly (remember that out in
System.out is an object of type PrintStream). However, we cannot do any
meaningful arithmetic on a string. For example one may need to do some arithmetic
on the score received by John or on his gpa. That is when parsing is required.
FIG. 2.14
User enters a value of –5.4 and either presses the enter key or clicks OK. The DOS
console output shows the value entered by the user and its square. Let us review the
Listing 2.4 line by line. The line:
String Input = JOptionPane.showInputDialog(null, "Please enter the "
+" non-zero coefficient of X square in the quadratic equation" +
" Then either press the enter key or click on OK!");
displays the input dialog box in Figure 2.4. The line
assumes that user inputted a double data types in the dialog box of Figure 2.14 and
parses it into a double data type stored in memory val_A. Since val_A is a double
type value, the mathematical operations can be done on it. The line
Calls the pow static method of class Math and returns its square, which is printed
by the println method of PrintStream class. Some time to release the memory
occupied by graphical components such as a dialog box shown in Figure 2.14, an
explicit call to static method exit of System class is needed. This is accomplished by
the program line:
System.exit (0);
abstract
The abstract keyword can be used in the declaration of classes and methods. Use of
the keyword in a class declaration typically means that one or more of the methods
within the class body are declared as abstract. If the keyword is left off the class
declaration, and a method within the body of the class is declared using the abstract
keyword, then the class is implicitly defined to be abstract. In other words, the
keyword abstract need not be provided as part of the class declaration in this
circumstance, and the code will compile successfully. (For readability it is
recommended that abstract class declarations include the keyword to make the class
intention clear.)
.
.
.
}
The derived class (BananaClass) may be instantiated, and any non-abstract methods
of the abstract class (FruitClass) will be inherited unless they are overridden.
The abstract keyword can also be used to define methods. As already shown above,
a class containing abstract methods is then also (either implicitly or explicitly)
Note that a method declared with the keyword abstract cannot be declared with the
keywords static, private, or final.
boolean
The boolean keyword is used to declare a primitive Java data type containing a
truth value. The two possible values of a boolean variable are true and false. Note
that true and false are defined as keywords in the Java language, but they are
actually literal values. Hence, the keywords true and false can be used as return
values, in conditional tests, and in assignments and comparisons to other boolean
variables.
The contents of boolean variables cannot be cast to or from other types; the current
value of a boolean variable can be converted to a string however.
The following code demonstrates declaration and assignment for a boolean variable:
isRunning = true;
break
The break keyword is used to define a break statement which, without a label,
transfers control out of the innermost enclosing while, do, for, or switch statement.
If the break statement includes a label and the statement is executed, control will be
transferred out of the enclosing statement to the line immediately following the label
declaration. (In this case, the break target need not be a while, do, for or switch
statement.)
The break statement also transfers control outside of try/catch blocks. Note that if
the break statement with a label is executed within a try or catch block, and an
associated finally block is defined for the try/catch block, then the contents of the
finally block will first be executed. After the entire finally block has executed,
control will once again transfer to the first statement immediately following the
label declaration.
recordsRemain = getUpdateStatus( );
while (recordsRemain)
{
if (isRunning)
System.out.println("Update another record");
else
break block1;
}
}
byte
The byte keyword is used to declare a primitive Java data type containing an integer
value in the range of negative 128 to positive 127. A byte is defined as 8 bits in
length, regardless of the platform the Java bytecode executes on.
Note that byte variables can be cast to and from other numeric types.
stripThis = 64;
case
The case keyword can only be used within a switch statement block. It is used
repeatedly to provide any number of unique constants (or numeric labels) for
comparison within a switch statement block. If the case constant equals the value of
the expression at the top of the switch statement, then control is passed to the
statement immediately following the case statement. If, on the other hand, the
expression at the top of the switch statement block and the case label do not match,
control is passed to the next case for comparison.
In the event that no case constants match the value of the expression given at the top
of the switch statement, often a default case is provided.
catch
char
The char keyword is used to declare a primitive Java data type containing a single
16-bit Unicode character in the range \u0000 to \uffff. Unicode characters are used
to represent a majority of known written languages throughout the world. (ASCII
characters make up a very small part of the Unicode character set.)
Note that values stored by char may be cast to and from other numeric types.
However, because character data is implicitly unsigned, casts of char to byte or
short can result in a negative number.
hitChar = 'a';
class
The class keyword is used in the declaration of a new class. A class declaration
defines a new reference type (or object) and describes its implementation through
the use of constructors, methods, and fields. These implementation details can be
inherited from superclasses, or uniquely defined as part of the class declaration.
continue
The continue keyword is used in nested loops to define a continue statement, which,
without a label, transfers control to the end of the innermost enclosing while, do, or
for loop. Once control is passed, the current loop iteration ends and a new one
begins. If the continue statement includes a label and is executed, control is
transferred to the last statement of the outer loop. In this case, the continue target
label must point to a while, do, or for loop. (Contrast this with the labeled break
statement, where the target need not be a loop, or iteration, statement.)
Note that if the continue statement with a label is executed within a try or catch
block, and an associated finally block is defined for the try/catch block, then the
contents of the finally block will be executed first. After the entire finally block has
executed, control will once again transfer to the last statement of the loop
immediately following the label declaration.
block1:
for ( int i = 0; i < 10; i++ )
{
while ( statusOkay )
{
if ( someNum < 0 )
{
someNum++;
System.out.println("Do it again");
continue;
}
if (string1[i] == null)
{
System.out.println("null string here");
continue block1;
}
else
{
string2[i] = string1[i];
}
// continue statement without label points here
}
// continue statement with label points here
}
default
The default keyword can only be used within a switch statement block. It can be
used only once, and is typically located at the end of the switch statement block. The
default keyword is used to label statements that are to be executed by default. That
is, the default statement block is only executed when the result value of the switch
expression does not match any of the case labels within a switch statement block.
do
The do keyword is used as part of a do/while loop. Unlike the other, more commonly
used loop constructs, a do/while loop expression is evaluated only after the block of
code within its body has been executed. Thus, you are ensured that the code within
the loop body is executed at least once, even if the expression tested causes the loop
to end.
Note Don't forget that a semicolon is required after the condition in a do/while
loop.
do
{
System.out.println("Printing at least once");
.
.
.
} while ( i <= 10 );
double
The double keyword is used to declare a primitive Java data type containing a 64-
bit floating-point number in IEEE 754 format. Variables of type double store values
in the range negative 1.7E308 to positive 1.7E308 within approximately 14
significant digits of accuracy. When you want a floating-point literal value to be
treated as a double, append the letters 'd' or 'D' to the end of the value.
Note that double variables may be cast to and from other numeric types. However,
doubles cannot be cast to or from values of type boolean.
dCalcSet = 1.23d;
dCalcSet = 3e2;
dCalcSet = .25;
else
Note that if/else conditional testing is a frequent source of program bugs. Consider
the following example of a poorly formatted if/else condition:
extends
The extends keyword is used in a class declaration to specify the direct superclass of
the class being declared. The superclass can be thought of as the class from whose
implementation the implementation of the current class is derived. The class being
declared is said to be the direct subclass of the class it extends. If no class is explicitly
defined as the superclass with the extends keyword, then that class has the class
java.lang.Object as its implicitly declared superclass.
When a class is extended, the class being declared has access to all the public and
protected variables and methods of it's superclass. Note that classes declared with
the keyword final cannot be subclassed.
false
The false keyword can be used as one of the two possible boolean values. Strictly
speaking, false is not a keyword of the Java language; rather, it is a literal value to
be assigned to a variable of type boolean.
final
The final keyword is used as a modifier for classes, methods, and variables.
When the final keyword appears in a class declaration, it means that the class may
never be subclassed or overridden. This prevents over-specialization of a particular
class. In some sense, the person who created the class considered any further
changes to be tangential to its primary purpose.
When the final keyword appears in a method declaration, it means that the method
may never be overridden. (Note that methods declared with the keywords static or
private are implicitly final.)
When the final keyword appears in a variable declaration, it means that the variable
has an assigned value that can never be changed.
The finally keyword is used to define a block of code following a try/catch exception
block. The finally block is optional, and appears after the try block and after any
catch blocks. The code in a finally block is always executed once, regardless of how
the code in a try block executes. In normal execution, control reaches the end of the
try block and then proceeds to the finally block, which typically performs any
necessary cleanup.
Note that if control leaves the try block because of a return, continue, or break
statement, the contents of the finally block are still executed before control transfers
out of the try block.
If an exception occurs in the try block, and there is an associated catch block to
handle the exception within the method, control transfers first to the catch block,
and then to the finally block. If there is not a local catch block to handle the
exception, control transfers first to the finally block, and then moves up the series of
prior method calls until the exception can be handled.
float
The float keyword is used to declare a primitive Java data type containing a 32-bit
floating-point number represented in IEEE 754 format. Variables of type double
store values in the range positive 3.40282347E+38 to negative 1.40239846E-45.
When you want a floating-point literal value to be treated as a float, append the
letters 'f' or 'F' to the end of the value.
float fCalcSet;
fCalcSet = 1.23f;
fCalcSet = 3e2f;
fCalcSet = .25f;
for
The initialization section allows the programmer to declare one or more local loop
variables. Once the loop ends, these variables are no longer valid.
The update section allows the programmer to increment loop counters or perform
other updates. Typically, the update section is used to increment or decrement
whatever loop counters the programmer defines.
if
implements
The implements keyword is used in a class declaration to indicate that the class
provides an implementation for one or more interfaces. If more than one interface is
implemented within the class, the interface names must be separated by commas in
the declaration. The implements keyword must also follow the extends clause in the
class declaration.
}
import
The import keyword is used by Java to make classes available to the current file
using an abbreviated name. Any number of import statements may appear in a Java
program, but they must appear after the optional package statement at the top of
the file, and before the first class or interface definition in the file.
instanceof
The instanceof keyword is used as an operator that returns true if an object on its
left side is an instance of the class specified on its right side. The instanceof operator
will also return true when comparison is done with an object implementing an
interface. The instanceof operator returns false if the object is not an instance of the
specified class or does not implement the specified interface. It also returns false if
the specified object is null.
int
The int keyword is used to declare a primitive Java data type that contains an
integer value in the range of negative 2147483648 to positive 2147483647. An int is
defined as 32 bits in length, regardless of what platform the Java bytecode executes
on.
The contents of int variables can be cast to or from other numeric types.
The following example demonstrates declaration and assignment for an int variable:
iValueK = 1024;
interface
• Interfaces cannot implement other interfaces. (They may extend other interfaces.)
• All methods declared within an interface are implicitly declared to be public and
abstract. Methods within an interface cannot be declared as final, native, static, or
synchronized.
long
The long keyword is used to declare a primitive Java data type containing a value in
the range negative 9223372036854775808 to positive 9223372036854775807. A long
is defined as 64 bits in length, regardless of what platform the Java bytecode
executes on.
The contents of long variables can be cast to or from other numeric types.
iLedgerBalance = 1234567890;
native
Note that native methods cannot be declared with the keyword abstract.
new
The new keyword is used as an operator for creating a new object or array.
When new is used to create an object, it first creates an instance of the specified
class, then initializes all of the instance variables to their default values, and last
invokes the appropriate constructor for the class, depending on the arguments
provided in the argument list.
Using the new keyword to create a class object typically looks like this:
The new operator can also be used to allocate dimensional arrays for any numeric
or object type. Once an array has adequate space allocated, all the elements of the
Using the new keyword to create an array typically looks like this:
null
The null keyword represents a special value that indicates a variable does not refer
to any object. The value null may be assigned to any class or interface variable to
aid garbage collection. (Assigning the value null to any of the items above indicates
to the garbage collection system that the object or variable is no longer in use.) It
cannot be cast to any other type, and should not be considered to have a known
numeric value.
package
The package keyword is used by Java to specify which package the code in the file is
located in. Java code that is part of a particular package has access to all classes in
the package, and all non-private methods and variables in those classes.
The package statement must come before anything else (except comments and
conditional compilation directives) in a Java file. If the package statement is omitted
from a Java file, the code in that file becomes part of an unnamed default package.
private
The private keyword is a modifier that can be used in the declaration of methods or
variables. (Note that the private keyword cannot be used in the declaration of local
variables.) Using the private modifier in the declaration for either of these types
hides the methods and variables so they cannot be directly referenced outside of the
class they're declared in. One exception to this rule is that private methods or
variables declared within a class can also be used by inner classes.
protected
The protected keyword is a modifier that can be used in the declaration of methods
or variables. (Note that the protected keyword cannot be used in the declaration of
local variables.) A protected variable or method is only visible within its class,
within its subclasses, or within the class package. Note that the subclasses may
reside within different packages, however.
The public keyword is a modifier that can be used in the declaration of classes and
interfaces. (Note that the public keyword cannot be used in the declaration of local
variables.) The public keyword can also be used as a modifier in the declaration of
methods and variables. Classes or interfaces declared as public are visible
everywhere. Methods and variables declared as public are visible everywhere their
corresponding classes are visible.
Note that public classes must have a class name that exactly matches the name of the
.java file in which they appear.
return
short
The short keyword is used to declare a primitive Java data type containing a value
in the range negative 32768 to positive 32767. A short is defined as 16 bits in length,
regardless of what platform the Java bytecode resides on.
The contents of short variables can be cast to or from other numeric types.
squareFeet = 4600;
static
The static keyword is used as a modifier for methods and variables. The keyword
can also be used to define static initializing blocks.
When the static keyword appears in a method or variable declaration, it means that
there will be only one copy of the method or variable that each class object may
The static keyword can also be used to create a static initializing block of code that
runs only once, when the class object is first loaded into memory.
Strictfp
A modifier for the nonabstract java methods or nonabstract class, which when
applied will set a ACC_STRICT access flag set for the method in the class file. This
will allow for the fact that the intermediate results of a floating point operation do
not have to fit 32 or 64 bit size and can be larger than their final containment value.
super
switch
The switch keyword is used along with the keyword case, and sometimes the
keyword default, to create a conditional statement. In a switch statement, the switch
keyword is followed by an expression within parentheses whose value must evaluate
to a primitive Java data type. Once the expression has been evaluated, its value is
compared against the label following each case statement within the switch
statement body. When a label has the same value, the lines following that case
statement are executed. An optional default label is included within the body of a
switch statement when there is no guarantee that the labels provided by each case
statement are the only values the switch expression may evaluate to.
switch ( someExpression )
{
case 1:
{
doCase1( );
break;
}
case 2:
{
doCase2( );
break;
}
case 3:
{
doCase3A( );
doCase3B( );
The break keyword is also, at times, used within the body of a switch statement.
Once the lines following a case statement have executed, the break statement is
included to jump over the remaining body of the switch condition. Without a break
statement, subsequent case statements would continue being evaluated, and
eventually the default statement, if one were included, would execute.
this
The this keyword is used with instance methods and constructors to refer to the
current object. Use of the keyword this in the very first statement in the body of a
constructor means that another constructor in the same class is being called to assist
in creation of the object. For example:
// first constructor
MyClass( String bDay )
{
birthday = formatBirthday( bDay );
// second constructor
MyClass(String nm, String bDay )
{ this ( bDay );
}
}
Note The keyword this must appear as the first statement in the body of a
constructor, otherwise your code will not compile.
Use of the keyword this in an instance method is helpful when a variable using the
same name appears within the method body. For example, when you refer to a class
scope variable in a method containing the variable name x, the class scope variable
would be known as this.x.
The throw keyword is typically used within a try block to indicate that an
exceptional condition has occurred. The throw keyword is followed by an exception
object, derived from the class Throwable, indicating the type of exception being
thrown. A throw statement causes a program to immediately stop and resume at the
nearest catch statement that can handle the specified exception object. Hence, throw
statements may also be outside a try block, if the exception will be caught elsewhere
within the program.
The throws keyword is used in a method declaration to list any exceptions not
derived from Error or RuntimeException that a method can throw. (Exceptions
derived from type RuntimeException are typically avoidable. Exceptions derived
from type Error are usually related to serious system problems; thus, little can be
done about them.)
The following example shows a typical method declaration using the throws
keyword:
The transient keyword is a modifier used in the declaration of variables. Use of this
keyword specifies that the current value of the variable need not be serialized (or
saved) along with other data stored in a class object.
The following example shows the declaration of a variable with the transient
modifier:
The true keyword can be used as one of the two possible boolean values. Strictly
speaking, true is not a keyword of the Java language; rather, it is a literal value that
is assigned to a variable of type boolean.
For an example of how the true keyword can be used, see the keyword boolean.
try
The try keyword is used to indicate a block of code in which an exception might
occur. For each try statement, there must be at least one corresponding catch clause.
If the exception occurs, the catch clause parameter is evaluated to determine
whether it is capable of handling the exceptional condition. If the exceptional
condition cannot be handled by any of the catch clauses corresponding to the try
statement, then control is transferred up the chain of method calls and all the
previous exception types are evaluated until one capable of handling the condition is
found.
Note that if the try statement has a corresponding finally clause, then the body of
the finally clause will be executed no matter whether the try block completes
normally or abruptly, and no matter whether a catch clause is first given control.
try
{
// code within this block may cause an exception.
.
.
.
}
catch( Exception1 e1 )
{
// code within this block is executed only
// when an exception of type Exception1 occurs,
// otherwise it is skipped over.
.
.
The void keyword is used in the declaration of a method to indicate that the method
returns no value.
Note that Java provides only this very limited use of the void keyword. Unlike in the
C language, the void keyword cannot be used to declare the absence of method
parameters, void pointers, and so on.
volatile
The volatile keyword is a modifier used in the declaration of variables. Use of this
keyword specifies that the value the variable contains may change asynchronously,
and, therefore, the compiler should not attempt to perform optimizations with it.
while
The while keyword is used to create a loop construct. In a while loop, the expression
in parentheses immediately following the keyword is evaluated, and if the boolean
result is true, the statements appearing within the loop body are executed. If
multiple statements make up the body of the loop, they must be enclosed with curly
braces. Once the loop body has executed, control transfers back to the top of the
loop where the test is performed again, and the execution of the loop body is
repeated until the value of the expression evaluates to false.
while ( i < 10 )
Appendix 2.2
The program below allows one to find the minimum and maximum value of certain
java primitive data type for a particular JVM implementation. The Screen shot
following the program gives the results of running this program. In this example the
Float class is used to get the sizes of float. Rest of the mapping is as follows:
Integer – int
Double – double
Short – short
And so on.
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public class JavaDataSizes
{
public static void main(String []args)
{
System.out.println(Float.MAX_VALUE);
System.out.println(Float.MIN_VALUE);
System.out.println(Double.NEGATIVE_INFINITY);
System.out.println(Float.POSITIVE_INFINITY);
System.out.println(Double.MAX_VALUE);
12. A Java programmer whose name is John, likes his children so much
that he modifies the header of main method as follows:
public static void main (String [ [ JohnsChildren)
Do you think that John’s program with the modified header
for main method will still work? Explain your reason(s).
13. Which Java package is automatically included in every java program
and its explicit inclusion is not needed?
14. A Java programmer Tyron likes his Mom so much that on his
mother’s birthday, he saves the following Java class and program in a
file called HappyBirthDayMom.java. Will his program compile and
run? Assume that all the code lines inside the class below have no
compile and run time errors.
public class ComplexNumbers
{
//code that will compile
public static void main (String[]args)
{
//code that will compile
}
}
15. In the statement System.out.print (“Hello”); explain the followings:
A. What is System?
B. What is “out”?
C. What is print?
16. Which of the following company was responsible for development of
Java? (A) Microsoft (B) IBM (C) Sun Microsystems (D)
United States Air Force (E) Toyota Motor Company.
17. Java was developed in (A) 1990’s (B) 1940’s (C) 1920’s (D) 1890’s.
18. Will the following java program compile? If yes then what is the
output?
public class Class1{
public static void main (String/* This is needed*/ [] args){
System.out.println("Hello World");
}
}
a. Will compile and the output is:
b. Will not compile as Java does not allow inline comments.
19. Which one of the following is not a java keyword:
a. int
b. float
c. while
d. bool
21. From the list of modifiers given below which one can be used for a locally
declared variable:
a. static
b. const
c. final
d. abstract
e. generic
Given below is the list of java keywords. Answer the question numbers 22 to 31
about this list.
List1
-----------------------------------------------------------------------------------------------
a. abstract, b. Boolean, c. break, d. byte, e. byvalue, f. case. g. cast, e. catch, f.
char, g. class, h. const, i. continue, j. default, k. do, l. double, m. else, n. extends, o.
false, p. false, q. final, r. finally, s. float, t. for, u. future, v. generic, w. goto, x. if, y.
implements, z. import, aa. inner, bb. instanceof, cc. int, dd. interface, ee. long, ff.
native, gg. new, hh. null, ii. operator, jj. outer, kk. package, ll. private, mm.
protected, nn. public, oo. rest, pp. return, qq. short, rr. static, ss. strictfp, tt. super,
uu. switch, vv. synchronized, ww. this,
xx. throw, yy. throws zz. transient, aaa. true, bbb. try, ccc. var, ddd. void,
eee. volatile, fff.while.
22. Which java keywords represent the primitives?
23. Which keywords represent the values of one of the java primitive?
24. Which java keyword if used must be the first uncommented keyword in the
java program?
Given below is the list of java primitives. For question #32 to 37 mark the correct
answers from this list:
List 2.
a. int, b. float, c. double, d. short, e. char, f. byte, g. long, h. boolean
Given below are the possible outputs that may be produced by some java code
fragments. For question numbers 38 to 55, indicate as to which code fragment will
produce which output.
List 3.
a. 3.4028235E38 b 1.4E-45 c. 1.7976931348623157E308 d. 4.9E-324
e. NaN f. Infinity g. -Infinity h. 9223372036854775807
i. 2147483647 j. -9223372036854775808 k. -2147483648 l. true m. -128
n. false o. 127 p. 32767 q. -32768 r. -1
Assume that the code structure is as follows and the structure of statement #1 is
different for each question from #32 to #38.
public class MyClass{
public static void main(String [] args){
statement #1 // See the various possible forms below
}
}
38. statement #1 is: System.out.println(Float.MAX_VALUE);
39. statement #1 is: System.out.println(Float.MIN_VALUE);
40. statement #1 is: System.out.println(Double.NEGATIVE_INFINITY);
41. statement #1 is: System.out.println(Float.POSITIVE_INFINITY);
42. statement #1 is: System.out.println(Double.MAX_VALUE);
43. Statement #1 is: System.out.println(Double.MIN_VALUE);
44. statement #1 is: System.out.println(Float.NaN);
45. statement #1 is: System.out.println(Integer.MIN_VALUE);
56. What will be the output of the following java code snippets? The block of code
that differs is defined in answers a to h.
class Class1{
public static void main(String [] args){
//Block of code. See below for various possible code blocks
}
}
a. String x = null;
System.out.println(x);
b. String y= “null”;
System.out.println(y);
c. String x = null;
x+=x;
System.out.println(x);
d. String y= “null”;
y+=y;
System.out.println(y);
e. String x = null;
String y = "null";
y = y+x;
System.out.println(y );
f. Object y = null;
System.out.println(y );
g. Object x = null;
String y = new String();
y = (String)x;
System.out.println(y );
h. String x = null;
Object y = new Object();
y = (Object)x;
System.out.println(y );
Operators
Operators operate on program variables to perform some operations. There are 3
types of operators in Java.
1. Binary operators: They operate on two variables or two expressions1. The
two variables or expressions are called operands. For example in expression
9 + 5, the 9 and 5 are operands and plus (+) is the operator. Binary
arithmetic operators are: plus (+), minus (-), division (/), multiplication (*),
and modulo or modulus (%).
1
In Computer Science a variable or constant is also at times called an expression. We may use the
name expression for an equation or for s single variable or constant.
Operand 1
Operand 2
FIG. 3.1
We will discuss more operators (like logical types) in future lectures. Java allows
the operators +, -, /, *, and % to be used for all integer and floating-
point data types as well as when operands for these operators are mixed
types. In Java these operators are not allowed to have boolean data
types as operands. For example the following line will give a compile error in
Java, but a similar expression in C++ will not2.
Compile error! boolean data types are
boolean data = true*false; not allowed to be operands to
arithmetical operators in Java!
Among arithmetic operators the division and modulus operators have some special
characteristics in Java. We therefore discuss them first.
Division (/)Operator
We are familiar with evaluations in normal arithmetic that 11/4 will be 2.75. But
will we get the same answer from our Java program? Let us run a short program
and see. Listing 3.1 below does that for us.
2
Corresponding expression in C++ would be:
bool data = true*false; // This will compile in C++.
Listing 3.1
In above listing, we are asking the program to do four different divisions, 11/4,
11/4.0, 11.0/4.0, and 11.0/4. In a normal calculator operation all four will yield the
same results. But as shown by the program output below (Figure 3.2), first output in
this program will not be the same as would be shown by a calculator.
FIG. 3.2
Why is 11/4 = 2 and 11/4.0 or 11.0/4 or 11.0/4.0 = 2.75 in Java?
The reasons are as follows:
As we mentioned before that literal constants, like 11, 11.0, 4, 4.0 have an assumed
data types. When we enter a literal like 11, the program assumes it to be an integer.
But when we enter a literal as 4.0 then program assumes it to be a double. Therefore
the division operator looks at the data types of two operands and proceeds as
follows:
• If both numerator and denominator are integer data types, then division
operator carries out something called “Integer Division”. In integer
division only the number of times the denominator can fully divide the
numerator is reported. The remainder part is thrown away. For example in
case of 11/4, 4*2 = 8. So when we subtract 8 from 11, the remainder is 3. The
remainder is too small to perform another division by 4, so it is thrown away
in the integer division.
• However, if either the numerator or denominator is a floating-point type or
both are floating point types, then the division performed is normal
calculator type division, where remainder is turned into a fraction and added
to the integer division answer. Therefore the 11/4.0 and other divisions
FIG. 3.3
In Java modulo operator can take any integral or floating-point types, as well as
mixed types as operands. For example can we get some thing meaningful out of
'z'%'A', 'Z'%2, 7.2%2.1, 11%4.2, or A%2.1? The Listing 3.2 below shows the
program and the results.
public class Modulus
{
public static void main(String [] args)
{
System.out.println ("The 11%4 in Java = " + 11%4);
System.out.println ("The 7.2%2.1 in Java = " + 7.2%2.1);
System.out.println ("The 11%4.2 in Java = " + 11%4.2);
System.out.println ("The A%2.1 in Java = " + 'A'%2.1);
System.out.println ("The \'z\'%\'A\'in Java = "+'z'%'A');
System.out.println ("The \'Z\'%2 in Java = "+'Z'%2);
System.out.println ("The 9.9%9 in Java = "+9.9%9);
System.out.println ("The 99.9%\'A'\' in Java = "+99.99%'A');
}
}
Question: What will be the output of following Java code fragment? Would any of
the lines cause a compile error?
System.out.println('z'-'A'); System.out.println(145.6%’v’);
System.out.println('z'-2); System.out.println(true*false);
System.out.println('Z'*2); System.out.println('P'%23.4);
System.out.println('a'-'A');
Table 3.2
Let us take an example where we mix one pound of water of zero degree
temperature with half pound boiling water. The goal is to calculate the average
temperature of the mixture. Let us define some program variables below, all being
assumed as double data types.
Then a simple physics rule can tell us that if one-pound water with temperature
equal to FREEZE_POINT was mixed with half-pound water of temperature equal
to BOILING_POINT, then the temperature of mixture, avg_temp is given by
expression:
In above expression on right hand side we have two binary operators the plus (+)
and the division (/). The question arises as to which operator will be resolved first.
Would the program do the operation FREEZE_POINT + BOILING_POINT first.
Or would it do BOILING_POINT/2.0 operation first. This issue is decided by
something called rule of operator precedence, which gives us information as to how
tight the operators bind in comparison to each other.
Figure 3.4 below gives us the precedence rules for some of the Java operators.
3
You may type the Circumference equation as Circumference = 2*3.14159*Radius;
meaning 2 to be an integer. But compiler takes that literal integer and widens it to a
floating-point type when the multiplication with 3.14159 is done.
Same
preced-
Binary
ence
FIG. 3.4
We will discuss the method call operator later on, however, one must understand
that the pair of parentheses operator also forces the evaluation order as the
expressions in the innermost parentheses are evaluated first. We see from above
chart that after parenthesis, the unary operators have highest precedence and the
assignment the lowest. That means that among all operators the
assignment binds weakest. Therefore assignment will be done after all
other operators have been resolved. Operators between a pair of
horizontal lines have the same precedence. For example plus (+) and minus
(-) have same precedence. Operators with equal precedence bind with equal
tightness. The unary operators such as unary plus (+) and unary minus (-) apply
only to non-character literal constants or when assigning the value to a named
constant. The white spaces between the operands and operators in case of binary
operators are ignored. As we add more operators to the list shown in Figure 3.4, we
shall upgrade the Figure accordingly.
Operator Associativity
All Binary operators shown above associate from left to right. 4For example in
2%3*4 the scanning will be done from left to right. 2%3 will be evaluated first,
which is 2, and result 2 multiplied by 4, so final result is 8. Left to right associativity
requires scanning left to right. The Figure 3.5 below discusses left to right
associativity in more detail.
4
The unary negation (-) associates from right to left.
Based on the rules surmised in the Figures 3.4 and 3.5 above, we can analyze that
how the operations will be performed in the expression
Since operator divide (/) binds tighter than the binary addition (+) the first
operation performed will be BOILING_POINT/2.0. Let us assume that
Temp = BOILING_POINT/2.0
Then we see that binary addition (+) binds tighter than the assignment (=), therefore
FREEZE_POINT + Temp will be performed next. Let us assume that
avg_temp = RHS
Listing 3.3
For the first expression, reading from left to right unary minus has the highest
precedence and it associates from right to left. Therefore, a memory location is
created for first –5 and then for the second –5. Then in the second pass (again
reading from left to right) the binary minus binds tighter than the assignment
operator. Therefore second –5 is subtracted from first one. The result is 0 and is
stored into another temporary memory. Finally in the third pass (reading from left
to right) the memory location y is given a value of 0, which is the evaluated result of
the right hand expression.
The second expression in Listing 3.3 cannot be evaluated with out answering the
following question. In expression -5 + - -5, is the second minus sign from
the left a unary operator or a binary operator?
The compiler parses the above expression as follows:
-5 + (-(-5))
6*¾ *5
It has operators multiply (*) and divide (/), both of which bind with equal tightness
(same precedence) and both associate operands from left to right. Therefore
scanning from left to right, 6*3 is done first, which results in 18. Then scanning
again from left to right 18/4 is done next, which results in 4. Finally 4*5 yields 20.
Parenthesis has highest precedence among the operators shown in Figure 3.4.
Therefore using the parenthesis can alter the order of evaluations. For example the
expression 6 *(¾)* 5 will evaluate differently. Because of parenthesis having
highest precedence, the ¾ will be evaluated first. The result is 0. The 6*0 is 0 and
finally 0*5 is 0. Therefore be very careful in applying the operators and understand
the rules of precedence thoroughly. Slight change and placement of parenthesis can
change the value of expression drastically. We will do few more expressions after we
have understood type coercion and type conversion clearly. But let us see few more
examples right now:
Error! Not a valid link.
Evaluate the following expressions
7 * 10 –5 %3 * 4 + 9
Additional use of parenthesis is shown by the following presentation.
Error! Not a valid link.
Table 3.3 shows the syntax and meaning of four increment and decrement
operators.
Operator Syntax Name Action
++val Pre-increment Increase value of val by one and store in
val
++ val++ Post-increment Increase the value of val by one after the
current action involving val is complete.
--val Pre-decrement Decrease value of val by one and store in
val
-- val-- Post- Decrease the value of val by one after the
decrement current action involving val is complete.
Table 3.3: val could be any integral or floating point type
When the pair of plus sign is appended to the front of a variable name, it is called
pre-increment operator. When it is appended to the end of variable name it is called
a post-increment operator. When a pair of minus sign is appended to the front of an
operator, it is called a pre-decrement operator, and it is called a post-decrement
operator when it is appended to the end of a variable name (Table 3.3). Let us first
observe as to what changes are made to the storage location (such as val in Table
3.3) when pre-increment and pre-decrement operators are applied. The Figure 3.6A
shows this action
++val; 6
val
--val; 5
val
FIG. 3.6A
In first line of the code fragment in Figure 3.6, a storage location val is created and
int five is stored in it. The second code line;
++val;
--val;
decreases the stored value back to 5. Meaning of pre-increment or pre-decrement
operations is clear. In these operations the value stored at the variable location must
be modified (increased or decreased) by one, before variable can be used for any
other purpose. The application of post-increment and post-decrement operators
requires that the variable value be changed, after the current action on it is
completed. . Listing 3.4 would clarify as to how the pre and post operators affect
variable values.
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public class PrePostFixOperators
{
public static void main(String [] args)
{
int val = 5;
System.out.println ("Current value of val = " + val);
System.out.println ("The operation ++val sets val = " + ++val);//line 3
System.out.println ("The operation --val sets val = " + --val);//line 4
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Listing 3.4
In Listing 3.4 on line #3 we print the value of variable ++val. Since a pre-increment
operator is used the value of val is increment before it is outputted to the console.
The output shows that the val is increased to six before it is printed to the console.
In line #4 the value of variable –val is printed. The outputted value of five shows
that the value of val is decremented by one before it is outputted.
Situation is different, however, when in line #6 we output value of val++. The output
shows that the value of val printed to console is no different than the previous
output. This expected because the post-increment operator only increases the value
of val, after its current value (five) is outputted. However, if we print the val after
the operation val++ is allowed to complete (line #7) then we get an incremented
value of six. The pre-increment or pre-decrement operators are also given a generic
name called pre-fix operators. Similarly the generic name for post-increment and
post-decrement operators is post-fix operators. When the variable is to be used as a
stand-alone variable, one is free to use pre-fix or post-fix form. However, as seen
from Listing 3.4, when variable is used in some way, then pre-fix operator would
work on the variable before its use, and post-fix after its use. Figures 3.6B and 3.6C
show additional examples as to how the use of pre-fix and post-fix forms alters the
program results.
FIG. 3.6C
- Unary Negation
++ Pre-Increment Right-to-Left
-- Pre-Decrement
* Multiply
/ Divide Left-to-Right
% Modulus
+ Plus
Left-to-Right
- Binary Minus
5
The word “appear” may have been used, because an exception may be thrown prior to the
completion of any evaluation, thus terminating the program abruptly. We shall discuss exceptions
and their handling in subsequent chapter.
Another related guarantee from Java (stated in JLS) is that every operand of an
operator (except the conditional operators6) appears to be fully evaluated before any
part of the operation itself is permitted. The significance of both above Java
guarantees will become clear soon with few examples. Take for example the code
snippet:
int x= 6;
System.out.println (x++ + ++x);
The above code produces an output of 14, because evaluating from left to right, first
the current value of x (=6) as one of the operand is saved for the binary plus
operation. Then since Java guarantees that each operand of an operator must be
fully evaluated before the operation is performed, the post-increment is done on x,
raising its value to 7. Then since the right operand must be evaluated as well, the
pre-increment increases the value of x to 8. The operands are thus 6 and 8, sum of
which is 14. In evaluating the expression in code snippet above we used the
precedence rule that unary ++ has a higher precedence than binary +. However, the
behavior and application of post-increment operator ++ is deduced from Java
guarantee that all operands of an operator be fully evaluated before performing the
operation. A more complex code snippet is given below:
6
Conditional operators are &&, ||, and ? :, which will be discussed later.
The output of above code snippet is 77. This is because, following the evaluation
order left to right; left operand ++y must be evaluated fully, which sets y = 7. The
right operand is parenthesized and involves a postfix operation on y. Therefore the
current value of y is used, giving 10*7 = 70. Performing plus operation will give a
result of 77. However, the post-increment is then done on y and its value is set to 8.
The incremented value of y does not affect the output here. What if we altered the
above code slightly as below?
int y = 6;
System.out.println( y++ + (10 * ++y) );
The output now changes to 86 because of the left to right evaluation order and full
operand evaluation before the operation. Scanning from left to right, the current
value of y = 6, which is saved to be used as the left operand before the plus operator.
However, the next operation on y is a pre-increment. Therefore the post-increment
++ is done before the next operation of pre-incrementing can be done. This sets the
value of y = 7. In evaluating the right operand of +, which is 10*++y, the pre-
increment must be done before multiplication can be done. Indeed here we do use
the rule of operator precedence shown in Figure 3.7, which shows unary pre-fix
operation having a higher precedence than the binary multiplication. The pre-
increment in the expression 10*++y, sets the y = 8. Thus 10*++y evaluates to 80. The
sum of saved value of left hand operand (=6) and right hand operand (80) gives us
an answer of 86.
Once again we warn user to not write code, the way we have shown in
code snippets on last page. All pre and post-fix operations must be done
before or after the variables are used in the expressions or making the
method calls!
7
For whole literal numbers, Java uses an assumed data type int, whereas for non-whole literal
numbers the assumed data type is double. The L and F are needed though not always required to
specify data types other than the assumed types. L indicates that data type of the whole literal
number be taken as long and F indicates to take the data type of non-whole number to be of type
float.
FIG. 3.7
But let us take a look at next code fragment, where storage wise things are a bit
different.
//*********************************************************
double my_double; Value undefined
Type
my_double= 8;
Coercion
int 8 is coerced into double type
8.0 and is stored.
//*********************************************************
FIG 3.9: Automatic type conversion or type coercion needed.
In Figure 3.9, first a double type of memory called my_double is created. However,
since no assignment is made, the value stored is undefined. In the next line
assignment my_ double = 8 is made. Since 8 is int type (lower range), compiler does
an “Implicit type coercion (therefore conversion) for you and stores the value 8.0 in
the storage location my_double and widens the datum to double data size (wider
range). This type conversion is implicit because we did not tell compiler to do it.
Such conversion is another example of Widening Conversion discussed earlier.
8
Recall that the assumed data type for floating point literals in Java is of type double.
Listing 3.6
In Listing 3.6, first we assign create an int called big with a value 1234567890
(bubble#1). Then we assign the value of big to a float storage called approx (bubble
#2). Java will compile this because in data ranking (Figure 3.6, 3.7) float ranks
higher than int. Then we subtract from big the whole number portion of approx
(bubble #3), and print the result. The output, -46, suggests that there was a loss of
(int)approx
is simply that from approx discard the fractional portion and extract only the whole
numbers.
Question:
What will be the result of the following expression? Is the final result floating point
type or Integer type? Is there any widening conversion in this expression? If yes
then explain as to what value is being widened to what type? Is this expression safe?
10.0 / 3.0+5 * 2
Question
What will be the result of the following expression?
55.112 + 'z'%'B' + ','/1.9
Indicate as to what values are being widened to what? Is this expression safe?
the whole number 120 is of type int, but the storage location, where the number is
being stored my_byte, is of type byte. In making this assignment, Java will
effectively convert number 120 from type int to type byte, and then in location
my_byte, the “narrowed” 120 is stored. Java allows this storage and assignment
because the number being stored is lower than the maximum limit of byte type
memory. Such “narrowing conversion” is safe and is done automatically. However,
the following will cause the compile error in Java:
9
As shown in Listing 3.4, this at times may not prevent the loss of precision, however.
The Figure 3.10 does the narrowing conversion but makes it explicit, thus making
code more readable, and allowing for a modification, should such conversion lead to
inaccurate results. Some examples of explicit type casting are given in the Figure
3.11 below.
10
boolean primitive cannot be converted to any other type. Reverse is also true.
1.75f
Then
widens
1 to 1.0f
First widens 7 to 7.0f and 4 to 4.0f and then
performs the float division.
FIG. 3.11
Most of the results of Figure 3.11 are self-explanatory. The operation (float)7/4
will
also give 1.75f because first 7 will be converted explicitly to 7.0f, and
then implicit type coercion will widen 4 to 4.0f, thus 7.0f/4.0f giving
1.75f.
Understand that Java will give a compile error if one would use the C++ style of
type casting given below.
Acceptable in C++ but compile error
int val = int (4.8); in Java.
One may use a form of type casting which will work both in Java and C++. This is
shown below.
Will work in both, Java and C++.
int val = (int)(4.8);
Explicit Type Casting as a Part of problem solving algorithm
Let us see one more example of explicit type casting, where we use the type casting
mechanism to round off currency numbers to nearest cents. Let us say that you
went to supermarket and you bought Cabbage and Oranges. Then you would need
to pay for 2 items and let us say that variables declaring their costs are (Figure
3.12):
Now since you are supposed to round off to a penny, you might as well get the
cost in pennies first.
6. Calculate cost in pennies (Cost_In_Pennies = Total_Price*100)
Now here is the crucial step. If fractional penny is less than 0.5 then you want it
to drop but if it is 0.5 or more then you wish it to round off to 1 penny. (We do
not care about the 1/100th part of a penny). So what you do is that you just add
0.5 penny to the Cost_In_Pennies calculated in step 6. If penny at the first
decimal place was 0.5 or more then adding 0.5 penny will add 1 penny and some
fraction to the total. (Example 0. 62 + 0.5 = 1.12). But if penny at the first
decimal place was smaller than 0.5, than adding 0.5 penny will graduate it to no
more than 0.9 at that decimal place. So step 7 is:
print ( );
In this sense, in Java, the static methods that are members of the same class can call
each other in the manner similar to the functions calling each other in a C program.
FIG. 3.13
If we write a function f(x) = 5*x – 3;
Then we have the following components.
1. Name of function/method – in this case simply f.
2. Parameter of the function – x, enclosed in parenthesis. We can call this a formal
parameter, as it just tells us the parameter name.
3. Definition of the function/method – in this case statement 5*x – 3 is the
definition;
The function/method f shown in Figure 3.13 will create a return value based on
actual value is substituted for x. You can say that when formal parameter x is
replaced by an actual parameter say x= 1, we get the following:
FIG. 3.14
Let us say that the signatures11 of square and cube methods are as follows:
public static double square (double)
public static double cube (double)
This is shown in Listing 3.9 below.
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
import javax.swing.*;
public class ValueReturningMethods1
{
public static void main(String [] args)
{
double number = 0.0;
String Input = JOptionPane.showInputDialog (null,
"Please enter the number to be squared and cubed: ");
number = Double.parseDouble(Input);
11
The method name and its formal argument list is called its signatures. For example main has
signatures as main(String [] args). No two class member methods can have same signatures.
square (number)
transfers the control to method square. The method square takes the value of
number passed to it and performs operation (number*number) and returns the
value to main. main displays the value to the user. Similar sequence involving
method cube is repeated when a call is made to it and the cube of the number is
displayed. Finally main takes the control back and exits the execution. Notice that in
the main method one may call the method square using the following syntax as well:
The square_value can then be displayed. Thus value returning methods can be
called as an argument to another method or they can be called as the right hand
part of an expression in Java. The nature of void methods is different, which we
discuss next.
methods
FIG. 3.15
Let us look at some of the methods that Java libraries provide for us and help us in
writing complicated programs.
The first three methods have same number of parameters, and their types, but the
order of parameters is different, making them identifiable by their signatures. The
last method has fewer numbers of arguments than other three – thus having
different signatures from the all others. This process, where Java allows many
methods to have same name is called “method name overloading”. The ability
to overload method names allows programmers to use the same name for methods
whose algorithms or actions are similar. This facilitates the “economy” of inventing
the method names in Java.
This is so because while compiling a Java program, the compiler will automatically
import a java package called java.lang into users program. The important classes
included in java.lang package are as follows (Table 3.5).
Let us take a closer look at the use of sqrt (x) method of class java.lang.Math. This is
shown in Figure 3.16.
All the instance methods of the String class can be called by using the instance
variable Name created by the declaration above. For example, the String class has
an instance method called toLowerCase ( ), whose purpose is to convert all
characters in a particular string to lower case. If one makes a call to method
toLowerCase with the syntax given below, the result will be that all characters in the
variable called Name will convert to lower case.
Instance
Instance method being invoked.
name
Notice that to call the instance method (in this case the method toLowerCase) one
must qualify it by dotting it with the instance of the String object, which is making
the call. Without such qualification, the instance methods cannot be invoked outside
a class or inside any static method. Soon we show use of some instance methods in
Java class called String.
String Class
Strings are very important in programming. They have become even more
important, with the ubiquitous Internet programming. All the web sites, which offer
web services, may use, user name and a password. These are stored in String data
type forms. Operations on strings, like finding the length of a string, finding a sub
string inside another string, getting a portion of a string returned as a substring are
all important string operations. Java treats all strings as final objects, for example
once created; a java string can never be altered. This type of “string safety” is the
corner stone of java’s excellent security system, a feature missing in practically all
other programming languages, where strings are alterable. We first show the
summary of important methods available in the String class (Table 3.8), and then
we discuss some of them in more detail.
13
Object is a class is Java, from which all other classes are derived. This will be discussed in the
chapter on inheritance. Till then you can think that in executing the method equals(Object
anObject), one can pass a String to check whether the contents of the String passed are same as
String being compared.
Table 3.8
Here we discuss just a few methods available for strings in Java and we will discuss,
rest of them as we proceed further in this book.
Calling the length instance member method of the String class returns the number
of characters (including spaces) in the string.
Converting all characters in a string to all lower case or all upper case
Some times it is easier to compare strings, when both of them have all lower case
letters or upper case letters. String class instance methods toLowerCase and
toUpperCase perform these operations. Example is shown in Listing 3.11.
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public class StringOperation2 1. Method toLowerCase
{ converts all characters in
public static void main(String [] args)
{ its caller to lower case.
String Name = "JOHN Q PUBLIC";
The param can be replaced by any of the seven primitive data types: byte, char,
short, int, long, float, and double. Listing 3.12 shows a trivial application of the
overloaded method valueOf. We need to wait to learn graphics programming in
Java for more potent applications of method String.valueOf.
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
{
public static void main(String [] args)
{ Returns the String containing
long $long = 10000L; number $long*100.9
valueOf is a static or
class method.
Number= " = " + Number;
System.out.println ("The multiplication of "+$long+
" and " + 100.9+ Number);
index1 = My_Name.indexOf('J');
System.out.println ("The first occurrence of character\'J\'"+
" in "+My_Name+" is at index = " + index1);
index1 = My_Name.lastIndexOf('J');
System.out.println ("The last occurrence of character\'J\'"+
" in "+My_Name+" is at index = " + index1);
}
} //Listing 3.13
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Another useful method is lastIndexOf, two versions of which can take a character or
a string as an argument and return the last index in the string, where the string or
character passed as an argument is found. lastIndexOf works in manner similar to
the method indexOf. In last example in Listing 3.13, the method lastIndexOf is
called by the String My_Name with an argument ‘J’, which returns 10, the index of
last ‘J’ in the string “Adam JonesJ”.
FIG. 3.18A
FIG. 3.18B
However if user input is different from the contents of the string My_Name then
boolean info stores a false value and corresponding message is displayed (Figure
3.19).
FIG. 3.19A
Notice that even literal strings can call the instance methods of the String class.
Another form of the method substring takes two integers as arguments and returns
a substring, which begins at the index equal to the first argument and ends at the
second one. The method header and examples are given below.
Note that to get a valid substring, the endIndex must be at least one more than the
beginIndex.
Examples:
"mesquite in your cellar".replace('e', 'o')
returns "mosquito in your collar"
14
The lexicographical ordering method of string comparison will be discussed later.
Questions (In multiple choice questions, more than one answers may be
correct. Choose all that are correct)
1. Answer the questions given in Figure 3.20 below. What value is returned by each
method call?
FIG. 3.20
2. A C++ programmer, while practicing Java writes the following code thinking that
the boolean variable must_be_true would have a value true. Instead he gets the
output shown in Figure 3,21, where variable must_be_true has a false value. Explain
the output for this listing (3.15).
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public class Questions1
{
public static void main(String [] args)
{
String Last = "Doe";
String Result = ("John Doe").substring(5);
boolean must_be_true = ( Result == Last);
System.out.println("Boolean variable must_be_true = " + must_be_true);
}
}//Listing 3.15
FIG. 3.21
3. Consider the following code snippet
String river = “Columbia”;
System.out.println (river.length( ));
What is printed?
A. 6
B. 7
C. 8
D. Columbia
E. river
4.You read the following statement in a Java program that compiles and
executes.
submarine.dive (depth);
What can you say for sure?
A. depth must be an int
B. dive must be a method.
C. dive must be the name of an instance field.
D. submarine must be the name of a class
E. submarine must be a method.
9. A programmer writes the following code to try to print the name of 2001 Space
Odyssey computer HAL 9000. What would this program really print? Can you
correct programmer’s error simply by making changes inside the call to print
method? Show how?
10. What will be printed by the following Java snippets? Explain your answers.
11. The following two programs, first from Java, and second from C++ may appear
to give same output. However, they do not as the sequence of numbers printed is
reverse of each other (tested on Windows OS). What would be the output from Java
program? Why does Java output comes out as expected?
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public class MyClass
{
public static void main (String [ ] args)
{
int num = 5;
print(++num,++num);
}
void main( )
{
int num = 5;
print(++num,++num);
}//Listing 3.17
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
12. Which of the following statements is true concerning Java variables and
assignment?
13. Here is a line of Java code: weeks_in_year = (int) tax_rate; Without having
seen the types of the variables given during declaration, what is the most
reasonable guess concerning them?
Which of the following lines of code correctly uses a method of the Math class?
a. result = Math.sqrt(value);
b. result = value.sqrt();
c. Math.result = sqrt(value);
d. result = Math.value.sqrt();
a. 0, 4
b. 1, 4
c. 1, 5
d. 0, 5
a. 2ab
b. A compiler error.
c. A run time error.
d. 212
a. 7.5
b. 3.54
c. “3.5”4
d. This gives a compiler error.
22. When the program containing the following code in main method is run and the
command line arguments entered are: four four
then what is the output of this code?
What is the data type of the expression passed as an argument to method println?
23. What gets printed when the following program is compiled and run. Select the
one correct answer.
24. Given two non-negative integers a and b and a String str, what is the number
of characters in the expression str.substring(a,b) . Select the one correct answer.
A. a+b
B. a-b
C. b-a-1
D. b-a+1
E. b-a
F. b
25. Given the following declarations, which of the assignments given in the options
below would compile. Select the two correct answers.
int i = 5;
boolean t = true;
float f = 2.3F;
double d = 2.3;
t = (boolean) i;
f = d;
d = i;
i = 5;
f = 2.8;
So far in this book we have used Java classes only as a wordy way of writing C type
programs, which were limited only to, either main method or additional static
methods. In this chapter we explore the true power of Java as an object oriented
programming language. However, we would extend our effort to use Java in C-like
manner, just a bit longer, so that we can illustrate some key Java principles of
object creation and their storage. Suffice to say at this point that in Java, classes are
the templates to create objects of user defined data types, which can store data and
methods in them for data processing1.
We write a simple class called Customer, which is similar to a C struct in the sense
that it has only data members, which are all public. Listing 4.1 shows the class
Customer. This class is a small version of more sophisticated Customer classes,
which may be written in enterprise software development environment.
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
class Customer
{
public String name; //stores name of customer
public long phone_num; //stores phone number
public char credit_rating; //stores credit rating
public String address; //stores street address
public String city; //stores city
public long zip_code; //stores zip code
public String credit_card_num;//stores credit card number
}//Listing 4.1
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
To make members of class Customer, accessible in a manner like member access in
C struct, we use the keyword public in front of each of them. This allows one to
access them by using the familiar dot operator. Some useful operations involving
class Customer may require:
1. Creating an instance or object of class Customer.
2. Inputting data into the object created in step one.
3. Printing the information stored in Customer object.
4. Changing the information stored in Customer object.
The first step requires a Java declaration, which will create an object or instance of
class Customer. Other three steps require operations on such object. All of above
1
Struct in C are not allowed to store methods in them, however, the struct in C++ is just like a class,
except that default access level in C++ struct is public.
In above declaration, the variable Name is actually not the name of storage location
in memory, where the string “John Doe” is stored. Rather it is a reference (or a
pointer), which stores the address of that part of memory, where string “John Doe”
is stored. Schematically we can represent the relationship between the variable
Name, and location where string “John Doe” is stored by the Figure 4.1 below.
Name 5000
“John Doe”
5000
Stores the address
5000 in it
However, before we can even get into explanation of how to create objects of user
defined classes, other than String, in Java, we need to take a slight detour and
The memory available to the operating system or device is divided into two types of
region:
• Stack Memory
• Heap Memory
During execution of Java program all the local variables are stored on the stack,
whereas all the objects are stored on the heap. The stack memory is used just like a
stack data structure, which uses the Last-In-First-Out (LIFO) protocol. This means
that the variables created last on the stack memory are destroyed first, when they go
out of scope. Stack memory uses the memory addresses sequentially. There is no
strict sequence followed in the use of heap memory. Java stores all primitive
data types and references to objects on the stack and all objects on heap.
Let us show an example of the use of two types of memories in a Java code snippet
and how data declared in it are stored in the program memory (Figure 4.2).
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
int val = 6;
int num; // not initialized yet
String Name = “John”; Bottom of stack
double data = 5.005;
String City = null;
data 5.005
FIG. 4.2
City null
Figure 4.2 shows two partitions in the memory – on the left the stack memory and
on right the heap memory. As program proceeds sequentially, it creates storage for
the declared data, on stack sequentially. For example the int variable val is declared
first on the stack (bottom of the stack) and a value of six is placed in its storage
location. The next variable num has a storage location but it is not initialized,
therefore its contents are undefined. Then we declare a String object called Name,
and store the data “John” in it.
Continuing with the Figure 4.2, after declaration of String Name with value “John”,
we declare a double variable called data (=5.005), which is stored on the stack.
Finally we declare another String reference called City, but we set it equal to null3,
and a null value is stored in that reference.
null value in Java: Unlike C++, null does not have a zero value in Java. A null
value can only be assigned to object references and not to the primitives. The null
keyword represents a special value stored in an object reference, which does not
refer to any object on the heap. null cannot be cast to any other type, and should not
be considered to have a known numeric value. A null value can also be seen as a
fundamental initializer for objects, just the way zero value is for integral data types.
Now we come back to the procedure of declaring the objects for the class Customer
defined in Listing 4.1. We were able to create a Java String object, using a simple
2
All references are 4 bytes in size.
3
A null value in Java can only be assigned to object references. Primitive data types cannot be
assigned pointers or references in Java, a paradigm vastly different from C/C++ languages.
Hidden “method”
Variable
added to the class
name
Customer by Java
Data type
Java operator
FIG. 4.3
The left hand side of above declaration is not different from standard declarations
we have used so far. It consists of the data type (in this case Customer), followed by
the variable name (My_Customer). My_Customer is a Java reference, which is
four bytes in size and it is capable of storing the address of a Customer type object,
which would be created on the heap. However, to actually allocate the storage on
heap memory, Java requires the expression: new Customer ( ): on the right hand
side. The use of keyword new followed by class name and parentheses tells
Java to create the storage and its contents for this object on the heap, when the
program runs. Therefore the decision of what to store in an object in Java is only
made when program runs. This type of storage is called “dynamic allocation”. The
dynamically created variables can be deleted, and memory reclaimed, even before
the variables have gone out of scope. In Java such memory reclamation is done by a
process called “garbage collection”, which we would discuss in detail later. Although
when we declare a String object such as:
we are able to do it with out using the keyword new, yet the storage for string “Doe”
is created on the heap at run-time. This facility, where one can create an object with
out using the keyword new is only provided for String class, as its objects are
created so often in Java programs. Creation of all other objects must use the
keyword new.
Class Constructor
Let us analyze the expression for creating an object of class Customer in more
detail. Consider the following Java declarations in a program:
Figure 4.4 shows the memory map at the run time when the program consisting
above declarations is executed.
FIG. 4.4
created an Object of type Customer on the heap. What you may be shocked to
discover is that the right hand side of declaration of object Cust resembles like a
method call (Customer ( )), yet the class definition in Listing 4.1, contains no
methods at all. All Java classes automatically are provided a hidden “method”
whose name is same name as the class name, and it has no return type, and takes no
arguments. This “method” is called by a special name “constructor”. Therefore
The special hidden “method” or constructor added by Java by default is also called
a default constructor. The default constructor provided by Java initializes all class
data members to some fundamental values. In order to show action of this
constructor, and other program details, we design another class called
DriverCustomer, which has main4 and other helper methods that either take a
Customer object as parameter or return it by return mechanism. Listing 4.2 shows
the classes Customer and DriverCustomer; both placed in a file named
DriverCustomer.java. There are certain rules for placing more than one class in the
same java file.
>javac MyClass.java
or
>javac *.java
• All Java classes are allowed to have the main method in them. In a file
containing multiple classes, the main method of any of them may be executed
4
We could have included the main method in class Customer also, but in the spirit of Object
Oriented Programming (OOP) it is considered a better design when the class that is used as a user
defined data type is tested and used by the methods in another class. Such classes are called client
classes.
It contains five static methods, including the main. The methods getCustomer,
printCustomer, and changeCustData, populate, print, and change a Customer
object respectively. The main method calls the other four methods. In Listing 4.2,
we create an object of class Customer by making the call to its default constructor
(Line 53). Java creates a reference Cust, which holds the memory address of the
location where the Customer object5 thus created is located on the heap. Then
program calls (Line 56) the printCustomer method and pass the object Cust to it, to
print its contents created by the default constructor provided by Java (Figure 4.5).
Object created
by default
constructor.
Data in object
Cust after line
58 is executed
Data in object
Cust after line
63 is executed
FIG. 4.5 : Output of Listing 4.2
5
The address of this object in heap memory can be printed by using the code:
System.out.println (Cust.hashCode( )); The source of this and other hidden method in class
Customer will become clear after we have discussed inheritance in Java. However, the address of all
Java Objects cannot be printed by using this method.
Notice that String data type is not initialized to an empty String. Rather all Java
objects are initialized to a null value. In Figure 4.4, we did not show the inner details
of the object Cust on the heap. We can do so now (Figure 4.6).
Stores Zero
z ip _ c o d e Stores null
c ity
Stores ‘ ‘
a d d re s s
c re d it_ ra tin g
phone_num
nam e
c re d it_ c a r d _ n u m
FIG. 4.6 “Schematic” map of the object Cust after being created by the
call on line 53 in Listing 4.2
In Figure 4.6 we have shown all the String data types of same length on X-axis, as
their initial size with null stored in them is expected to be the same. This is also true
of long data types (phone_num and zip_code). The credit_rating, which is the char
data type, will be smaller in size than all others. Upon further program execution,
the map of object Cust remains essentially unchanged except that values in the data
members are altered.
Program calls the method getCustomer (Line 58) to populate the customer fields
with user-inputted values. A second call to method printCustomer prints these
values (Figure 4.5). Then program calls the method changeCustData (Line 63) and
passes to it the customer object Cust, created and populated in the main method.
The method gets user input for new values for the fields of Customer object passed
to it. The main then calls printCustomer again (Line 66) to print the altered
Customer object (lower portion of Figure 4.5).
6
We shall discuss later as to what makes objects immutable.
7
We assume that data shown in the output in the Figure 4.5 are used.
The method changeCustData alters the data values in the Customer type object
passed to it. The state of object after execution of line 63 in Listing 4.2 is shown in
Figure 4.7B. Once again we assume that the data outputted in Figure 4.5 was used
as input.
In comparing the Figures 4.7A and 4.7B, you would notice that the address stored in
Cust, for the Customer type object on heap remains unchanged. However, all values
(data and addresses) stored in the fields of the object themselves have changed. We
expect the values stored in fields like zip_code and phone_num to change as they are
storing primitive data types. But, why would the addresses stored in the String fields
also change? This has to do, once again, with the immutability of Strings in Java.
Inside the method changeCustData, when we make an assignment such as:
cust.name =
JOptionPane.showInputDialog (null, "Enter new customer name");
What if we add the following line as the first line in the body of method
changeCustData (just before line 119), that is before any data input is done?
Do we still expect the method changeCustData to change the data of Customer and
pass it back successfully to the main method? Figure 4.8 shows the output when we
make just this change in Listing 4.2 and recompile and run the program.
FIG. 4.8 Output after adding the line in method changeCustData (See
text).
The results of Figure 4.8 are a bit astounding. Just by adding the line
as the first statement in method changeCustData disables the process of data update
and the object Cust in main method remains unaltered. This is because in the above
statement the reference cust stores a new value supplied by the constructor call on
the right hand side. Since all parameters in Java are passed by value only, this new
value stored by reference cust stays a local value, and the values stored by the object
You would recall that pass by value mechanism sends only a copy of the variable in
the caller method to the called method. Therefore, when method changeCustData
receives, from main, a reference to Customer type object, an additional reference is
attached to the Customer object on heap, which is then passed to the method being
called. Just before the code execution begins in method changeCustData, the state of
object pointed to by Cust in main can be shown by the Figure 4.9.
Reference
Cust in the
main
method
cust 3000
Notice here, because in call by value mechanism, only a copy of the variable is
passed to the called method, the object with name “John Doe” in it has two
references Cust and cust attached to it. Cust is in main method and its copy cust is
passed to the changeCustData method. But, as soon as the method changeCustData
executes the code line:
cust 12000
FIG. 4.9B: State of system after the statement cust = new Customer( ) is
executed in the method changeCustData as its first statement
Once the reference passed to a method is assigned to a new object on heap (as in
Figure 4.9B) then any changes made by the method are only done locally to this new
object. It is no longer attached to the object, whose reference was passed to it at the
time of call.
Key to remember is that it is not the object that is being passed to the method.
Rather it’s the pointer or reference to the object (on heap) that is being passed to the
above method. And Java’s pass by value mechanism ascertains that method
changeCustData cannot alter the memory address stored in the reference cust in the
caller method. However, subject to the conditions that Customer object is mutable,
and method changeCustData does not assign the reference passed to it to another
memory location, the data in the object pointed to by its argument cust can be
changed. We show a simple example in Appendix 4A (Listing A4.1), where we print
the memory address of an object (MyObject an instance of class MyClass) before
passing its reference to the method myMethod, in the method locally and after the
call to MyMethod is finished. All three addresses are same. That proves that in
Java, when we pass reference to an object to a method, the data stored in that
reference is passed by value, which cannot be altered in the caller method by the
method being called.
The below will not give a compile error, yet the program will crash upon execution,
with a cryptic message similar to the one shown in Figure 4.10.
FIG. 4.10
Most important word to notice in the above message is the word
“NullPointerException” This is Java’s way of telling you that in your program, you
have attempted to use an object reference which has a null value stored in it. In our
code snippet above we tried to call the length ( ) member method of class String
using a String type reference which has a null value stored in it. We show another
example of use of a null reference, which is connected Binky Pointer Fun Video
illustrating the hazard of using Java references with null value in them. Let us look
at the code in Listing 4.3.
class IntObj
00002 {
00003 public int value;
00004 }
00005
00006 public class DriverIntObj
00007 {
00008 public static void main(String [] args)
00009 {
00010 IntObj X = null;
00011 IntObj y = null;
00012
00013 X = new IntObj( );
00014
00015 X.value = 42;
00016 /*Uncommenting and compile/running the line below will
00017 crash the program with NullPointerException message*/
00018 //y.value = 13;
00019 // The line below will work as y points to the pointee of x.
//This is called sharing
Listing 4.3 shows that when a memory location is shared by more than one
reference, then any of them can alter its contents.
Question:
1. For Customer class in Listing 4.1, we write the following code in the main
method:
2. What will be the output if the following lines are added on lines 24 and 25 of
Listing 4.3.
y.value+=y.value;
System.out.println (x.value);
8
Thanks to Professor Nick Paralente at Stanford University, who is original author of the Binky
Video and the Table 4.3.
9
Other possible storage techniques may include linear data structures, such as linked list or non-
linear structures, such as binary trees or graphs. These topics are discussed in a data structure
course.
Declaring a class member private blocks direct read and write access to
it by using the dot operator.
The modified customer class will then be written as follows (Listing 4.4).
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
class Customer
{
public String name; //stores name of customer
public long phone_num; //stores phone number
public char credit_rating; //stores credit rating
public String address; //stores street address
public String city; //stores city
public long zip_code; //stores zip code
private String credit_card_num;//stores credit card number
}//Listing 4.4. The access to field credit_card_num is made private
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Notice that now the code snippet shown below in main would give a compile error.
10
Classes, which use other classes in their code or as data members, are called client classes. For
example the Customer class is the client of String class.
Only instance methods have messenger/receiver relationships with the class objects.
For example when one calls the Math library static method sqrt in the manner
below:
Questions
1. In the code snippets below, which identifier or portion is the messenger and which
one is a receiver?
A]
String Greeting = “Hello”;
int len = Hi.length ( );
B]
String Distance = "Smile".substring (1, 5);
C]
int val = (new Integer (55)).intValue ( );
String getCity()
Return the city for the customer
String getCreditCardNumber()
Return the credit card number for the customer
char getCreditRating()
Return the credit rating for the customer
11
We will skip coding of methods of this type, until we have learned about control structures in Java.
Listing 4.6 gives the code for expanded class Customer and its driver class.
00001 import javax.swing.*;
00005 class Customer
00006 {
00011 private String credit_card_num;
00015 private String name;
00019 private long phone_num;
00025 private char credit_rating;
00030 private String address;
00034 private String city;
00038 private long zip_code;
00039
00040 //member methods
00045 public String getCreditCardNumber( )
00046 {
00047 return credit_card_num;
00048 }
00049 //************************************************
00054 public void setCreditCardNumber(String credit_card_num1)
00055 {
00056 credit_card_num = credit_card_num1;
00057 }
00058 //***********************************************
00063 public String getName()
00064 {
00065 return name;
00066 }
00067 //***********************************************
00072 public void setName(String name1)
00073 {
00074 name = name1;
00075 }
00076 //***********************************************
00081 public long getPhoneNumber()
00082 {
00083 return phone_num;
00084 }
00085 //***********************************************
00090 public void setPhoneNumber(long phone_num1)
00091 {
00092 phone_num = phone_num1;
00093 }
00094 //***********************************************
The diagram in Figure 4.11A abstracts the details of the class Customer12.
12
This is actually an incomplete diagram as the methods inherited from the java.lang.Object class
are not shown. We would discuss that after study of inheritance.
Setters 3000
City 3000
Custom
. er ( )
.
Java provided
. default constructor
FIG. 4.11A
Since, in addition to the data members, now class Customer contains member
methods, we show them in while ovals lying half way in the class and outside it. This
indicates that these public methods form the interface between the class and its
external client. The oval setters represents all the set methods in the class (Figure
4.11B), and getters as all the get methods (Figure 4.11C).
Fig. 4.11B
Setter oval in
Figure 4.11A
Qualified name of
class instance variable
called name FIG. 4.13
------------------------------------------------------------------------------------------------------------
Code in Figure 4.13 is simpler at least in one way, that the programmer can use the
identifier for the argument to the method setName, same as the identifier for the
instance variable to store customer name. This simplifies the process of name
selection. We already mentioned that this reference is not available inside the static
member methods. It also cannot be used to select static class members. This is the
summary of the characteristics of this reference:
• All non-static member methods and constructors in Java
are provided a reference to the class itself indicated by the
reserve word this13.
• this reference can be used to perform member selection for
only non-static members, inside only instance or non-static
methods/blocks14.
• this reference is not available outside the declared class. In
this sense, it can be considered as a hidden argument passed
to all non-static class member methods and blocks.
Understand that if we replace the code in Figure 4.13 as below (Figure 4.14), it will
not be a compile error!
13
A bit later we shall see that this keyword can also be used as to make constructor calls, in which
case it acts like a class name.
14
Inside a class, Java allows declarations of blocks, which can be static or non-static. Blocks are
essentially unnamed member methods, which have no-names and cannot take any arguments. They
can only be used to cause some side affect (input, output) or set the values of class level data
members. We discuss them later on after we discuss constructors.
This method simply copies the data in Customer type object Customer1 into the
calling object. The line 209 in Listing 4.6 shows the necessary syntax (Figure 4.15).
address = Customer1.address;
FIG. 4.15
-----------------------------------------------------------------------------------------------
15
Borrowing the term from psychology, we can call the same type of object passed as a method
argument as “gregarious object”.
In this call we can see the messenger/receiver relationship between a method and its
object rather clearly. Here the messenger, the method setName sends a message to
its object Cust1, asking to change its name field from current value to the user
inputted one. Receiver Cust1 obliges by changing its name field as the code in its
method setName executes. Figure 4.17 shows the dynamics of messenger/receiver
relationship between object Cust1 and its method setName.
FIG. 4.17A
FIG. 4.17B
In Similar fashion the receiver object Cust1 interacts with messengers setAddress
and setCity on code lines 236 and 238 and changes them to the user inputted values.
Finally the line 241 prints the altered object Cust1. The results of the execution of
Listing 4.6 are shown in Figure 4.18 below.
public void withdraw( double amt) // withdraws amt from the balance
{
//code to be filled
}
Question:
If the bank using the BankAccount class here introduced a condition that every
customer has to maintain at least $25 minimum balance in their accounts, then
would the default constructor provided by Java maintain the class invariant?
16
Methods, which put no responsibility on user of any kind are called total methods in computer
science. A total method will handle all errors that are caused by the user data input. Total methods
cannot be written with out the use of a technology called “exception handling”, which we discuss
later. All methods cannot be written to behave as total methods.
numerator/denominator
one can surmise the invariant for the Fraction class. This invariant is that
denominator can never be zero! Obviously Java provided default constructor for
class Fraction will fail to maintain this invariant.
In second reason in the list above we mention that immutable objects are created in
their final state by the constructor. If variety of final states are required for an
immutable object, then obviously one constructor would be inadequate. Imagine if
the class java.lang.String , which creates immutable objects had only Java provided
default constructor? No one would be able to create a String other than the one that
contains empty character set.
17
Most books define explicit constructor as the one which carries one or more arguments. We extend
this definition to include those constructors, which have private or protected access levels, even if
they are argument-less. We define the explicit nature of a constructor lying in the fact that it is
explicitly different from the default constructor that Java would automatically provide.
18
The package private members of a class are allowed read and write access using the dot operator
with in all classes in that package. Making a member package private requires leaving out the access
control specifier in the member declaration.
Having established that in our class design we may need user defined constructors,
we explain how they are designed. An explicit constructor carries one or more
parameter in its argument list or is declared private or protected19. Foe example
take the case of class java.lang.String. Apart from having a constructor such as:
String Empty = new String ( ); // creates a zero length string
String Name = new String (“John”); //works the same was as = “John”
Which creates a string with contents “John”. This technology, where a class is
provided more than one constructor is also called “constructor overloading”.
Table 4.5 shows some examples of explicit constructors, and constructor overloading
from various Java classes.
Java Class Explicit ConstructorAction by constructor
java.lang.Math private Math ( ) Prevents instantiation
of Math class
public String (String Str) Instantiates a String
object with string Str
java.lang.String public Instantiates a String
String(StringBuffer buffer) object with contents
same as String Buffer
object buffer
public Integer (int value) Sets the int field of
Integer object to the
value int
java.lang.Integer public Integer (String Str) Creates an Integer
object whose int field
has the numerical value
contained in String Str
Table 4.5
19
Protected access control is provided by the keyword protected, which we shall discuss in more
detail in chapter on inheritance.
//Assume that we have filled the code lines 45 to 216 from the //Listing
4.6 here.
}
Listing. 4.7A
The explicit constructor shown by code lines 61 to 71, simply takes all seven fields of
Customer class as arguments, and sets each field to the corresponding value passed
to it. For example the first code line sets the address field to the address1, the value
passed to the constructor call. You would notice that we have included in the Listing
4.7A, an argument-less constructor shown in code lines from 46 to 49. Currently we
put no code in this constructor. The reason for including this code-less & argument-
less constructor is as follows. Java provides a default constructor for a class, as long
as no user written constructors are present. However, as soon as user includes even
a single class constructor, then Java takes away the constructor it would have
Listing 4.7B shows the class DriverCustomer4 used to test our explicit constructors
in two forms.
00001 import javax.swing.*;
00002 public class DriverCustomer4
00003 {
00004
00005 public static void main(String [] args)
00006 {
00007 printSeparator( );
00008 Customer Cust1 = new Customer ("22334455","John Doe",9142367789L,
00009 'A',"1122 Pine Avenue", "Georgia",90509);
00010
00011 Cust1.printCustomer( );
00012 Customer Cust2 = new Customer(
00013 JOptionPane.showInputDialog(null, "Enter customer credit card number"),
00014 JOptionPane.showInputDialog(null, "Enter customer name"),
Long.parseLong(JOptionPane.showInputDialog(null, "Enter customer Phone number")),
JOptionPane.showInputDialog(null, "Enter customer credit rating").charAt(0),
00017 JOptionPane.showInputDialog(null, "Enter customer address"),
00018 JOptionPane.showInputDialog(null, "Enter customer City"),
Long.parseLong(JOptionPane.showInputDialog(null, "Enter customer Zip Code")));
00020 printSeparator( );
00021 Cust2.printCustomer( );
00022 System.exit(0);
00023 }
00027 public static void printSeparator( )
00028 {
00029
System.out.println("=============================================");
00030 }
}//Listing 4.7B
20
This is one of the major Java Gotcha for students. They would write a code without any
constructor, and all the code calling default constructor works fine. Then instructor may suggest that
include an explicit constructor in the code as an added functionality. All of a sudden the code lines
calling the default constructor cause compile error. This simply because upon inclusion of any user
coded constructor Java takes away the default constructor it provided.
Notice that here we are calling the method showInputDialog of JOptionPane class
directly inside the call to constructor to get the user input for the customer credit
card number. Above forms of use of explicit constructors are shown only for
understanding their functioning. In enterprise software development, extensive data
validation is done before those data are passed to the constructor. After object
Cust2 is created by direct user input from user it is also printed to console. The
output of Listing 4.9B is similar to the bottom two third of Figure 4.5. We
summarize the function of Java constructors as follows21:
21
Thanks to Roger Whitney at SDSU, from whose web site this summary is taken from.
We can also use an initialization block to initialize the value of instance variable
num. In using initialization block the class LongObj of Listing 4.8A will change to
the one shown in Listing 4.8B
------------------------------------------------------------------------------------------------------------
class LongObj
{ 3. Initialization block.
private long num ;
{
num = 1000L;
}
public long getLong( ){
return num;
}
}
// add the code for class LongObjDriver from Listing 4.8A here
//Listing 4.8B
Order of Evaluation
Java allows one to use all three techniques, direct assignment, initialization block,
and constructor call to initialize class instance variables. However, it follows certain
order of evaluation. In object construction, the following order of evaluation is
followed.
1. Direct assignment is executed first.
2. Then the assignment or any other code in the initialization blocks
is executed. There is no limit on number of initialization blocks
used. Initialization blocks are executed in the order from top to
bottom.
3. Finally the constructor is called. If constructors are chained, then
they are called in the order of their chaining.
If all three initialization methods are used, then the final value of the instance
variable will be the one dictated by the last constructor call. Listing 4.8C shows the
example for class LongObj.
FIG. 4.20
Then since the initialization block is executed next in order, the code in the block
(line 17 & 18) prints the value of num initialized during the direct assignment. Then
line 19 sets the value of num to 2000. Since constructor is executed last, the control
shifts to line # 7, which is the first line in constructor body. The value of num set in
the initialization block is printed (line 8). Then constructor initializes the num to a
value of 3000 (line # 9) and this value is printed by the call to method println on
lines 10 & 11. In the main, the final value of the num field of constructed object
My_Long is printed on line 35 & 36, which is the same as set by the constructor.
The expanded BankAccount class also has the getters, which simply return the vale
of the private data members of the class. We also add a method printAccount, which
simply prints the contents of the object of type BankAccount We design a class
DriverBankAccount to test the chained constructors of our BankAccount class. Both
classes are shown in Listing 4.9 below.
00001 public class BankAccount
00002 {
00006 private String Name;
00010 private double balance;
00014 private int num_acts; 1. Argument-less
00015
constructor
00020 public BankAccount( )
00021 {
00022 this("name to be entered");
00023 System.out.println ("From argument-less constructor.");
00024 }
2. One argument
00031 public BankAccount(String name1) constructor.
00032 {
00033 this(name1,0.0);
00034 System.out.println ("From one argument constructor.");
00035 }
this ( )
where the parentheses include one or more arguments. Using the syntax
this("name to be entered");
the argument-less constructor (code line 22) calls the one argument constructor
which begins on line 31. This almost appears like a void method call, except it is not.
The operator this now acts like a replacement for the class name. We notice that
argument-less constructor calls (line 22) one argument constructor, which calls
(line33) the two argument constructor , which calls (line 44) the final constructor in
chain and the three argument constructor then initializes all the class data members
(lines 57 to 59). We show the action of these chained constructors through the
Listing 4.9B class DriverBankAccount.
This triggers a chain of constructor and output calls illustrated by Figure 4.22
below.
The completion of execution of each constructor takes place in the exact opposite
sequence.
Chaining constructor is a great way to provide special default values to the class
variables and have the flexibility of leaving some variables at default values, while
Java requires that no program statements precede the call to constructor using the
keyword this and it must be the first line in the constructor body. For example the
following would be a compile error:
Compile error! No
public BankAccount( ) statements can
{ precede the call
System.out.println ("Argument-less constructor."); using this as a
this("name to be entered"); constructor.
}
However value returning static methods from same class, or instance and static
methods from other classes can be called to provide one or more arguments passed
to this. Of course the argument type and method return types must match or Java
must be able to do a safe implicit conversion. Assume that we add a static method
called setDefaultName ( ) as a member of class BankAccount as follows:
One can use the call to static methods of the same class inside the call to this because
the static part of an object is already built prior to building the dynamic part using
the constructors.
return this;
}//FIG. 4.23
The method deposit here returns a BankAccount type object after adding the amt to
the balance and then returns the current state of the object by returning the self
reference this.
How can one use this form of method deposit? One can cascade several calls to
deposit method when the code snippet given below is executed in the main method
(Figure 4.24).
------------------------------------------------------------------------------------------------------------
BankAccount Act1 = new BankAccount("John Doe",0.0, 1);
Act1 = Act1.deposit(100).deposit(200).deposit(300).deposit(400);
FIG. 4.25
In the code snippet in Figure 4.24 the second line makes the cascaded calls to the
method deposit. Parsing from left to right, the first call Act1.deposit(100) returns
the object after incrementing the balance by 100. Then this returned object makes
the second call to the deposit method as deposit (200), which returns the object with
balance equal to 300. This returned object then makes the third call to the method
deposit as deposit (300) which returns the object with balance equal to 600. This
process goes on until all the cascaded calls are completed and the final balance is
1000.
FIG. 4.23
The output maps with the lines 7, 8, 10, 11, and 17 & 18 of Listing 4.10A.
We mentioned that even calling any of the static method of a class will make all
static initializations and run all static blocks in it. The code snippet run in main in
Figure 4.24 does just that.
System.out.println(BankAccount.getStatic( ) + " is the final value "
+ "of static variable stat_var as printed\n in the main method");
FIG. 4.24
The first statement in the argument list to method println makes a call to the static
method getStatic of the StaticVar class. This forces to run all the static blocks of the
class, thus producing an output in the Figure 4.25 below.
FIG. 4.25
Because the static assignments and initialization blocks are run first, we see the
output from the two initialization blocks first. Then the getStatic method returns a
The detailed order of construction of Java object will be discussed under title
“Advanced Object Construction” in the topic on inheritance.
FIG. 4.27
--------------------------------------------------------------------------------------------
Constants as class data members
Both static and instance data members can be declared as constants by using the
keyword final in the declaration. Some typical declarations may look like as follows:
From above declarations we may have given an idea that direct initialization is the
only way to set the values of class level constants. This is not so. All the methods
available for initializing the class variables are also available for constant
initialization as unlike C++, Java does not require that constants be initialized in the
line in which they are declared. However they must be initialized before their use.
There are three issues related to the packaged classes in Java, which deserve
discussion.
1. Placing the packaged classes.
2. Compiling the packaged classes.
3. Importing the packaged classes to other classes.
4. Compiling and running an application with imported package in
them.
Let us discuss them all one by one.
The convention is to use all lower cases in package name. A package name does not
have to have dots in it. For example one can simply use the package name Print.
However, if another company also uses the name Print for their package of Java
classes then a client would not be able to use classes from same named packages in
the same program. Therefore the reverse domain name schema makes sense, which
requires dots in the package names.
FIG. 4.28
If package name is net.Gandhi.print, then we must create three folder such that
folder print is located inside the folder gandhi, which in turn is located in folder net.
All the classes inside the package net.gandhi.print must be located in the folder
print. Therefore the path to the folder containing the classes in above package
would be:
…………..\net\gandhi\print In creating directory structure,
replace the dots in package name
by forward slash.
While the java files in unnamed packages are compiled by being in the folder or
directory where the class is located, the packaged classes are compiled by being in a
directory or folder in which the last folder in the package is located. For example to
compile the classes in the package net.gandhi.print, the DOS command line must
look like the Figure 4.29 A.
FIG. 4.29A
If we type the following command then the output would show the print folder in
our listing, which has the classes in our package (Figure 4.29B).
This will create .class files inside the folder print. Usually in finished form the
packaged classes do not contain a main method as their purpose lies in being used as
a software component (example String class). However, during testing and
debugging, temporarily, a class may be provided a main method. In such case the
package statement (the first uncommented line in the java file) must be commented
out and class must be compiled and run in the usual manner. Once class is fully
debugged, the package statement is commented back in and class is recompiled
23
This scheme applies to windows. The structure in Unix would be different
p.rint ( “Hello”);
the console must print out Hello. This saves the effort of typing the whole line such
as System.out.println to get an output. Since the source code of packaged classes is
not revealed to the client, we do not provide it here. Rather the Table 4.7 gives a
summary of just a few of them.
static void rint(char var)
Prints char var to the console without line feed.
static void rint(char[] var)
Prints char array var to the console without line feed.
static void rint(java.lang.Character var)
Prints Character var to the console without line feed.
static void rint(java.lang.Character[] var)
Prints Character var array to the console without line feed.
static void rint(double var)
Prints double var to the console without line feed.
static void rint(java.lang.Double var)
Prints Double var to the console without line feed.
static void rint(double[] var)
Prints double var to the console without line feed.
static void rint(java.lang.Double[] var)
Prints Double array var to the console without line feed.
static void rint(float var)
Prints float var to the console without line feed.
static void rint(java.lang.Float var)
Prints Float var to the console without line feed.
static void rint(float[] var)
Prints float array var to the console without line feed.
static void rint(java.lang.Float[] var)
Prints Float array var to the console without line feed.
static void rint(int var)
Prints int var to the console without line feed.
static void rint(int[] var)
Prints int array var to the console without line feed.
Table 4.7
Needed so that
Must include the full path to the
java can locate
folder in which the folder net is
files in current
located.
directory as
For example if client installed the net folder in a directory such as C:\GandhiSoft,
then the path name to be used after the flag classpath would be C:\GandhiSoft, and
the compile command line will become
If the package is located in the folder C:\GandhiSoft, then the execution command
becomes:
Figure 4.30 shows the sample output from the experiment done on my computer.
FIG. 4.30
The compile statement in Figure 4.30 is:
C:\_Test1>javac –classpath .; C:\Courses\Java\LectureNotes\Topic04JavaClassesAndObjects
PrintApp.java
Understand that how the package developed by you is installed on client machine is
a different issue. There are many options. You may just ship the folder with your
package to the client (after removing .java files from it) along with the javadoc
documentation, or you may have an installer install it on the client machine. In
addition the client may need the instruction on how to use or set the classpath.
class MyClass
00002 {
00003
00004 }
00005
00006 public class DriverMyClass
00007 {
00008 public static void main(String [] args)
00009 {
00010 MyClass MyObject = new MyClass( );
System.out.println("Printing the address of MyObject after constructor call in main.");
00012 System.out.println("The address of MyObject = " + MyObject.hashCode());
00013 myMethod(MyObject);
System.out.println("Printing the address of MyObject after call to myMethod.");
00015 System.out.println("The address of MyObject = " + MyObject.hashCode());
00016
00017 }
00018 public static void myMethod(MyClass MyObject)
00019 {
00020 //MyObject = new MyClass( );
System.out.println("Printing the address of MyObject locally in myMethod.");
00022 System.out.println("The address of MyObject = " + MyObject.hashCode());
00023 }
00024
00025 }//Listing 4A.1
Figure 4A.1 gives the output for the Listing A.1.
FIG. 4A.1
The Figure 4A.2 fives the output if the line 20 in Listing 4A.1 is uncommented and
the program is recompiled and run.
FIG. 4A.2
Why does the output in Figure 4A.2 show a different address for MyObject inside the
method MyMethod now? Explain.
Chapter to be written ☺
Chapter 6 Looping Control Structure
First let us understand the concept of standard input and output. You may not have
been aware of the fact that your computer is always in standby mode to either
accept data from keyboard or to display data on monitor console. We call the data
stream flowing from keyboard to computer memory as “standard input stream”,
and the one flowing from computer memory to monitor as “standard output
stream”. The situation is very similar to the one shown in Figure 8.1 below.
FIG. 8.1
In Figure 8.1 the keyboard may be replaced by an ASCII file and monitor by
another or same file. You may consider these data streams as “files” which are
always open as long as your program is running. You may have seen at least one
manifestation of always-open output stream, when a device error would give you
warning through “blue screen of death” (Figure 8.2).
FIG. 8.2
In Figure 8.2 the operating system halts your program and injects the warning data
in the output stream flowing to your monitor.
Because Java knows that the inward flow of data to a program or outward flow,
written to a file may be interrupted due to the failure of devices, it takes special
precautions during IO, to prevent data corruption. This precaution is exercised
using a technology called “exception handling”, which we shall discuss in detail in
chapter 12. To handle such error conditions, Java requires that programmer
enclose the code accepting user input1 or file output, in special blocks, which upon
impending failure, activate objects to inform user of the failure that took place.
These objects are of type Java class IOException2 in java.io package. Since we need
to wait to learn more about the exception handling, until we do, we tell main and
other methods to exempt us from the requirement of enclosing data input/output
part of the code in special “java required blocks”. This exemption3 is granted if we
put the line:
throws IOException
after the header of main or any other method performing IO. The line above uses
the Java keyword throws and the phrase “throws IOException” effectively inform
compiler and JVM that IO errors (and resulting IOException) will not be handled
by the method. Thus we alter the header of this “exempted” main as:
1
Input using a JOPtionPane’s method showInputDialog is exempted from this requirement.
2
The IOExceptions are also called “checked exceptions” as they are checked by the compiler at
compile time.
3
We state emphatically that exemption from IOException which we are seeking here, only for the
ease of student learning, shall never be sought while developing enterprise software!
The step one requires instantiating an object of BufferedReader class by calling its
constructor. The constructors in Table 8.1 are provided.
4
In this chapter by name file we would always mean an ASCII file.
5
It can be quite wasteful to read character one by one and make a trip each time to the program
memory to transport it.
6
We are not ready to discuss as to why we cannot create an object of class java.io.Reader. This has to
do with fact that certain Java classes are created not be instantiated, but to act as a template for
other classes as their children. These “un-instantiable” parent classes are called abstract classes. We
shall discuss abstract classes in chapter nine.
Question: Why do we not use the InputStream object directly? Answer is because it
only extracts the stream in bytes and not in character sets. Therefore a conversion
from bytes to character set is needed, which is done by binding it to an object of
InputStreamReader.
Question: Then why not use the InputStreamReader class object instead of
BufferedReader class object? Answer is that InputStreamReader is not buffered,
thus it is inefficient. And due to this non-buffering it can only read character-by-
character, rather than line-by-line.
7
If all this explanation appears labored, then I assure that once you have learned inheritance, it
would all become crystal clear.
Listing 8.1 shows a simple example where the object bindings shown in Figure 8.5A
and B are executed.
00001 import java.io.*;
00002 public class KeyBoardInput
00003 {
00004 public static void main(String [] args)throws IOException
00005 {
00006 InputStream Key_Stroke = System.in;
00007 InputStreamReader Isr = new InputStreamReader(Key_Stroke);
00008 BufferedReader Kb_Input = new BufferedReader(Isr);
00009 System.out.print ("Please type a long string and press enter: ");
00010 String Input = "";
00011 Input = Kb_Input.readLine( );
00012 System.out.println ("You have typed : "+ Input);
00013 System.out.println ("Please type another string and press enter: ");
00014 int ch = 0;
00015 int counter = 0;
00016
00017 while((ch = Kb_Input.read( )) != (int)'\n')
00018 {
The lines six, seven and eight in Listing 8.1 perform the requisite object bindings
shown in Figure 8.5. The BufferedReader class methods readLine (line 11) and read
(line 17) are used to get user input (Table 8.2) from the input stream.
int read()
Read a single character.
String readLine()
Read a line of text.
Table 8.2
The method readLine reads a line of text terminated by end of line character (EOL)
(‘\n’), or line feed character (‘\r’). It returns the line read as a String. On the other
hand the method read, simply reads the inputted stream character by character, but
returns an integer value of it.
You may recall from DeMorgan’s rules discussed in chapter five and its application
to loops in chapter six that the loop pre-test condition must be a negation of loop
termination condition. The loop to read user input character by character using the
method read must terminate when the character ‘\n’ is read in the stream.
Therefore the loop termination condition is:
Since the method read returns an int, we cast the character ‘\n’ into an int (Right
portion of Figure 8.6). The advantage of using the assignment:
ch = Kb_Input.read( )
inside the loop expression (line 17) is that we condense two priming reads (one
outside the loop and one inside) into one. Since the character read, ch, is an integer,
we need to cast it back into a character before we print it back to the console (Line
21). The stream is closed by using the close method of InputStream8 class (Line 23).
Figure 8.7 shows the typical output generated by the Listing 8.1.
FIG. 8.7
Reading from an ASCII File and End of File (EOF) Controlled loops
The BufferedReader class object can be used to read data from a file in the manner
similar to the keyboard input. Analogous to the InputStreamReader class, Java
provides us another class called FileReader, which is also of type class Reader. The
8
Recall that object System.in is of type InputStream.
FIG. 8.8B
On line seven & eight the user is prompted to enter the full path to file name in the
pop up dialog box. Then in line nine an object Freader of type FileReader is created.
This object is created only if a valid file is found. For example if file does not exist or
input failure occurs, then the error message similar to Figure 8.10 is issued.
FIG. 8.11
When an input file is read (Figure 8.11 ( a)) the file reading marker is placed at the
beginning of the file. In Listing 8.2, the object Buff_Freader will read the file from
beginning, line by line. However, when the end of the file is reached, then readLine
method reads EOF character and returns a null. This forms the basis of designing
our EOF controlled loop (Lines 16 to 22). We call readLine inside the loop
expression, thus eliminating the need for priming read outside the loop. The loop
termination condition must be:
The negation of above condition gives us the loop pre-test condition, which is:
A file can be read character by character using both, either the BufferedReader
object or directly using the FileReader object Freader. We create a new FileReader
object In_File (Line 26). The read method works exactly in the manner described
earlier, when we discussed Listing 8.1. However, when the EOF character is read
the method read returns a value of –1. Therefore or loop pre-test condition (Line 34)
ascertains that code in the loop body is iterated, until a –1 value is returned by read
method. The results of second loop (Lines 34-44) are identical to that of the first one,
except for the fact that no input buffer is used, when the object In_File reads the
file.
ALG 8.1
1. Open both files
2. Set the boolean variable are_same to true;
3. Prime read one character each from opened files
4. while end of file is not reached in either file
4.1 If characters read from two files are not same
4.11 Set are_same to false
4.12 break out of the loop
5. If characters read from each file are not same
5.1 Set are_same to false
6. If are_same is true then print message that files are identical
7. else print the message that files are different.
Following the algorithm ALG 8.1, the source code (Listing 8.3) prompts the user for
the names of files to be compared and opens them (Lines 9 to 14). The boolean
variable are_same is set to true. Then priming read is done on both files (Lines 16-
17). The read method will return –1 if either file is empty, in which case the loop
invariant is not met and program sets are_same to false (Lines 30-31) and skips to
line 37 to print that files are not identical. The loop invariant is met only when both
files are not empty, in which case the loop body compares them character-by-
character. As soon as a mismatch is found the boolean variable are_same is set to
false and loop is exited. The Lines 30 & 31 are executed only in a special case when
up to the length of smaller file, it is identical to the bigger one. Notice that we could
have made loop invariant to be:
In above constructor the first argument is of type called Writer. We have mentioned
earlier that in Java, due to property of polymorphism when a class is expected as an
argument to a method/constructor, then an object of a related class can be passed to
it. A class related to Writer is FileWriter, one of whose constructor is given below:
Figure 8.12A shows the schematics of code to execute the steps above.
9
Be sure to not provide an existing file name, as it will be overwritten!
FIG. 8.14
The output file must print the patient ID, their average blood pressure and the total
number of patient’s in the file. The algorithm for the whole program is given below
by ALG8.2.
StringTokenizer class
The new Java class used in this algorithm is java.util.StringTokenizer.
Unfortunately, Java does not have an input stream extraction operator like cin>> in
C++, which would eat and throw away the white space and just spit out the data
read in the stream. Therefore we use the class StringTokenizer that can take a
string as an argument and return the space de-limited tokens. Tokenization can be
done de-limited by other characters and on other basis. The constructor for
StringTokenizer class used in the ALG 8.2 is:
public StringTokenizer(String str)
Constructs a string tokenizer for the specified string. The
tokenizer uses the default delimiter set, which is " \t\n\r\f":
For example the Table 8.3 gives the sequence in which the tokens will be returned
by the method nextToken from the String: “John Doe lives in Torrance, CA.”.
Token sequence Token extracted from String “John Doe lives in
Torrance, CA.”
1 John
Output of Listing
2 Doe
8.4B (below)
3 lives
4 in
5 Torrance,
6 CA.
Table 8.3
We show a small Listing (8.4B) illustrating the use of StringTokenizer class.
-----------------------------------------------------------------------------------------------
import java.util.*;
Lines nine to 16 create BufferedReader and PrintWriter class objects, which bind to
input and output files respectively. Lines 19 & 20 print the header for the output
file. Line 23 runs an EOF controlled loop and create the string Line with containing
the line read from the file. The StringTokenizer object Token is bound to the String
Line read from the file (Line 26). The nested loop structure (lines 28 to 40) gets the
tokens from the StringTokenizer object Tokens and first token is patient ID is
printed directly to output file. The second token (see Figure 8.13 for structure of
input file) has the number of blood pressure readings for one patient. We run a for
loop (lines 36 & 37) to sum up that many blood pressures. Line 39 writes the
average blood pressure to the output file for one patient. The loop guided by method
hasMoreTokens is exited, when all tokens from the object Tokens are exhausted.
The last line in the scope of EOF control loop (line 41) increases the patient counter
by one.
Once the EOF is reached in the input file, the pretest condition in loop (Line 23) will
evaluate to false and loop is exited. Line 45 prints the total number of patients, and
Lines 47-49 close both data files and release system resources. The file shown in
Figure 8.13 creates an output similar to Figure 8.14.
Pseudo code:
Open the input data file
Read first character
Read second character
Loop Design
while not end of file
if first character is ‘!’ and second character is ‘=’
increase counter by one
set first character memory = value stored in second character
read next character into the second character memory
Exit loop
Display number stored in the counter.
We take user input for the name of input file and bind it to a BufferedReader object
Buff_Freader (Lines 8-10). The object Buff_Freader opens the input file and reads
the first character (Line 14). An if structure tests for input file being empty, and if
true, displays a message to that affect and exits program (Lines 16-20). For this
program to be useful, the file must have at least two characters. The program
checks if the second character is an EOF (in which case the read method will return
–1). If so then the if structure in lines 24-29 displays a message and program exits.
Inside do while loop (Lines 31-38), first test is made to see if first character is ‘!’ and
second one ‘=’. If both of those assertions are true, then the counter is incremented
We will not understand this algorithm and source code properly, unless we see it in
action by using a code walkthrough example. The example is shown in Figure 8.15.
FIG. 8.15
The box on left shows the contents of the file. The table on right shows the states of
the three storage locations previous (declared as prev in Listing 8.5), current, and
count. When first two characters are read, the previous contains ‘(‘ and current ‘x’.
The count will be zero because the if condition on line 33 of Listing 8.5 evaluates to
false. Then contents of current storage location are saved in previous, and current is
set to next character, which is ‘ ‘. Count is still zero. In fourth iteration of the do
while loop the previous contains the character ‘!’ and current ‘=’. Only then the if
condition on line 33 evaluates to true and counter is advanced to one.
Appending to a file is useful when for example we are keeping data on customers in
a file, and when we need to add a new customer, we can just add the data for new
customer at the end of an already existing file. Let us use our Customer class
discussed in Chapter four and design a data entry program to input customer
information. In the event of encapsulation and data abstraction we use the form of
the customer class, where all fields are declared private and getters and setters are
provided for all private data members. Listing 8.6A shows the modified Customer
class, only in the sense that an extra method appendToFile has been added to it. We
only show this extra method.
00001 import javax.swing.*;
00002 import java.io.*;
00006 class Customer
00007 {
//Insert here Lines 11 to 217 of Listing 4.7 in chapter 4
00255 public void appendToFile (String File_Name) throws IOException
00256 {
00257 //check that object at least has a name
00258 if(name==null)
00259 {
00260 JOptionPane.showMessageDialog (null,
00261 "No entry will be done with out customer name.");
00262 return;
00263 }
00264
00265 PrintWriter Append = new PrintWriter (
Method appendToFile takes the output file name as a String. Generally for an
object such as Customer, the name field must be populated before it is written to the
file. We check for that and if null is stored in the name field then no data are written
to the output file (Listing 8.6A lines 258-263). If name field is populated then the
constructor for FileWriter class, which will append to file is called and is bonded to
the object Append of PrintWriter class (Lines 265-266). println method of
PrintWriter class is used to append Customer data to the output file. Finally the
output file is closed (Line 271).
Listing 8.6B shows the class DriverCustomer4 to test the upgraded Customer class.
00001 import javax.swing.*;
00002 import java.io.*;
00003 public class DriverCustomer4
00004 {
00005
00006 public static void main(String [] args) throws IOException
00007 {
00008 printSeparator();
00009 String Input = "";
00010 boolean done = false;
00011
00012 while(!done)
00013 {
00014 Input = JOptionPane.showInputDialog(
00015 "The program will do entry for Customer data to an output file "
00016 +" [Y]es or [N]o?");
00017 Input = Input.trim( );
00018 if(Input.equals("N") || Input.equals("n"))
00019 {
00020 System.out.println ("End of program");
00021 System.exit(0);
00022 }
00023 else if(!Input.equals("Y") && !Input.equals("y") )
00024 {
00025
00026 JOptionPane.showMessageDialog (null,"Invalid choice"
00027 +" click OK to proceed.");
Few ways in which the errors can creep up in user response are:
• Invalid user response when user is prompted about their choice to
continue program.
• Zero length String entered for the file name.
The flag control loop in Listing 8.6B (Line 12) sets the user input in motion. The
user is prompted to enter their choice to execute or exit the program (Lines 14-16).
We use the trim method of String class to ascertain that any leading or lagging
Output Formatting
You may have noticed that in outputting the floating-point numbers, Java does not
format the fraction part to any particular significant number of figures. Special
Java class is used to manipulate the significant figures for floating point numbers. A
java package called java.text has classes, which help us format the floating-point
number output as well as outputting the currency data, and dates for a locale. Main
classes in package java.text are described below (Table 8.4).
Class name in Purpose
package java.text
DecimalFormat Assists formatting of floating-point numbers.
NumberFormat This is an abstract class10, however, it is used to
format numbers. including currency.
DateFormat Another abstract class, which assists the
formatting of time and dates depending on
locale.
Table 8.4
We show applications for the use of various output formatting classes.
Currency Formatting
Currency calculations must be exact. It is best to convert the input currency data to
smallest unit for the currency, do all calculations in smallest unit and then convert
to respective higher units. For example in USA the smallest unit of currency is one
cent, and the higher unit is dollar. Therefore it is best to convert user-inputted
currency data to cents, and then do all calculations using cents and then output
dollars and cents. NumberFormat class can be used to round off output to nearest
cent and display proper currency sign in output. Listing 8.7 shows an example of
10
An abstract class cannot be instantiated, but it may have some usable static methods, and some of
them may return an instance of this class.
System.out.print("Enter the time period in years for which deposit is kept: ");
00023 double deposit_time = Double.parseDouble(Keyboard.readLine());
The program takes the user input for principal deposit in floating point numbers
but converts from double to integer by multiplying by 100 (assuming that input was
in dollars) (Lines 16-18). Then user is prompted to enter the data for deposit period,
compounding frequency per year, and the interest rate (Lines 19-27). The total
accumulation is calculated using the standard compound interest formula (Line 29-
30). The important point in this program is to understand the procedure of currency
formatting. NumberFormat class has overloaded method called
getCurrencyInstance, whose two forms are shown below (Table 8.5).
public static final NumberFormat getCurrencyInstance()
Returns a currency format for the current default locale.
In Line 33 (Listing 8.7) we get the NumberFormat object Currency using the call to
argument-less method getCurrencyInstance11. Since this Listing is compiled in USA,
the object Currency can be used to format the currency data for USA. The
overloaded method format of NumberFormat class is used to perform actual
formatting. Table 8.6 shows the details of method used in output Lines 34-35.
public final String format(double number)
Returns the String version of the number, consistent with the pattern stored
in its caller.
Table 8.6
The method format takes the total accumulation and interest earned in dollars and
rounds off to nearest cent and outputs with dollar sign (Lines 34-37). Figure 8.16
shows the example of output.
11
In Java methods, which have names such as get…….Instance, are called factory methods. Factory
methods are static and return instance of their member class. They are used in place of constructors
to return an instance of a class. For example, the NumberFormat class is an abstract class, which
cannot be instantiated. It, however, has number of factory methods, which can return its instance.
Overloaded factory method getCurrencyInstance is one such method.
In Figure 8.16 the user input has been italicized and highlighted. The output
produced by Lines 34-35 without formatting would show the total accumulation to
be = 1283.3586785035118. The use of format method of NumberFormat class
instance correctly rounds off above number to 1283.36 and appends the $ sign in
front as well as adds the comma after the significant figure indicating thousand
dollar. One can perform calculations and outputs for locales other than the default.
Line 40 gets the NumberFormat object by calling the form of getCurrencyInstance
method that takes a Locale object as an argument. Locale.UK is a public static
member of class Locale. Curr_UK is the NumberFormat object which when used to
call its format method could format the argument to output form for UK currency.
Lines 41-45 output the corresponding data assuming that same deposit was made in
Britain in pounds. Table 8.7 shows the results of call to Currency.format method
where Currency is the NumberFormat object created on Line 33 of Listing 8.7.
Call made Output
System.out.println (Currency.format (13.384)); $13.38
System.out.println (Currency.format (13.385)); $13.38
System.out.println (Currency.format (13.38501)); $13.39
System.out.println (Currency.format (13.3851)); $13.39
System.out.println (Currency.format (13.3854)); $13.39
System.out.println (Currency.format (13.3855)); $13.39
System.out.println (Currency.format (13.3856)); $13.39
System.out.println (Currency.format (13.386)); $13.39
System.out.println (Currency.format (-13.386)); ($13.39)
Table 8.7
Among other things it is interesting to note (last row in Table 8.7) that when a
negative floating-point number is passed to format method, for Locale being USA it
prints a value ($13.39) as in USA it is usual to place parentheses around negative
currency number.
Half-even rounding criterion
will be $1.25. However, if we need to round off 1.245, then the distance with both
1.24 and 1.25 is equal (each is 0.005). In this case the half-even principle dictates
that rounding is to be done towards the even neighbor. Therefore the statement:
System.out.println (Currency.format(1.245));
Will create an output of $1.24. Similarly in Table 8.7 the values 13.384 and 13.385
rounds off to 13.38 because for 13.384 the distance towards 13.38 is lower, whereas
in case of 13.385, the distance towards two neighbors (13.38 & 13.39) is same, but
even neighbor 13.38 is chosen. For all other values in Table 8.7 the distance towards
13.39 is lower than towards 13.38.
12
IEEE 754 standard describes this rounding procedure in detail.
13
Mantissa is a part of number after the decimal point or the fractional part of a number.
“0.0000”
Integer part Mantissa
of the part of the
number number
“0.####”
FIG. 8.18
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
The part before the decimal point is the integer part of a number. The part after the
decimal point is called “mantissa”. Inside the format string, the placement of zero
(0) means that display either the digit or zero for the lagging digits in the mantissa.
Zero in the integer part will be shown only if the number is less than one. The
placement of character # means that show the lagging digit in the mantissa only if it
is present otherwise leave the lagging digit location(s) blank.
Figure 8.19 shows code and corresponding output when the last format string in
Table 8.8 is used. In Figure 8.19, the code lines shown in Figure 8.17 are combined
into one line.
FIG. 8.19 In above Figure the creation of DecimalFormat object and call to format
method are combined in one step.
Table 8.9 gives the summary of the meanings of characters used in building the
format string.
Character Meaning
0 Display a digit. If no digit is present then display zero.
# Display a digit. If no digit is present then does not display
anything.
, Used only for the integer part of a number. Counting from
right, display separator comma as dictated by the pattern.
Used to format the mantissa and placement of decimal
. point accordingly. Can introduce a decimal point even if
there are no fractional parts in the number. For example
the statement System.out.println ((new
DecimalFormat("###.")).format (2L)); will output 2.
% When placed in the format string anywhere (except the
first character) multiplies the number with 100 before
displaying and appends the % sign in end. If placed as the
We show a simple example (Listing 8.8) using some of the display formats from
Table 8.8 and characters from Table 8.9.
00001 import java.text.*;
00002 public class FloatingPointFormatting
00003 {
00004 public static void main(String[] args)
00005 {
00006 System.out.println("This program will simply display various formats "+
00007 "in which normal, large and small floating point number can be displayed.");
00008 System.out.println("For example we display the value of Pi in various formats");
00009 DecimalFormat DF = new DecimalFormat("0.0");
00010 System.out.println("The value of Pi rounded to first significant figure = " +
00011 DF.format(Math.PI));
00012 DF = new DecimalFormat("0.00");
00013 System.out.println("The value of Pi rounded to two significant figures = " +
00014 DF.format(Math.PI));
00015 DF = new DecimalFormat("0.00000");
00016 System.out.println("The value of Pi rounded to five significant figures = " +
00017 DF.format(Math.PI));
00018 DF = new DecimalFormat("00.0000000");
00019 System.out.println("The value of Pi rounded to seven significant figures"+
00020 " but also showing a leading zero = " +
00021 DF.format(Math.PI));
00022 DF = new DecimalFormat("0.00");
00023 double area = Math.pow(Math.PI,3.0);
00024 System.out.println("The area of a circle of radius = " + Math.PI +
" cm " +"\n" + "Displayed in format 0dot00 is "+ DF.format(area)+ " cm square.");
00026 //radius of earth = 6378100 meters
00027 double vol =4.0*Math.PI*Math.pow(6378100,3.0);
00028 System.out.println("The approximate volume of earth in format 0dot00 = " +
00029 DF.format(vol)+ " cubic meters.");
00030
00031 DF = new DecimalFormat("##.####E0");
00032 System.out.println("Now displaying format ##.####E0");
00033 System.out.println("In scientific notation the approximate volume of earth = " +
00063 }
00064 }//Listing 8.8
Figure 8.20 shows the output for the code of Listing 8.8. The lines numbers are
added to the output intentionally.
01 This program will simply display various formats in which normal, large and small
floating point number can be displayed.
02 For example we display the value of Pi in various formats
03The value of Pi rounded to first significant figure = 3.1
04 The value of Pi rounded to two significant figures = 3.14
05 The value of Pi rounded to five significant figures = 3.14159
006 The value of Pi rounded to seven significant figures but also showing a leading zero =
03.1415927
07 The area of a circle of radius = 3.141592653589793 cm
Let us first define as to how we would refer to line numbers from Listing 8.8 and
Figure 8.20. For example, L8.8#01 will refer to line number one from Listing 8.8. Or
L8.8#01-03 would refer to lines one to three from Listing 8.8. Similarly the
abbreviation F8.20#01 or F8.20#01-03 would correspond to line number one or line
numbers one to three respectively from Figure 8.20.
14
The value of Pi is 3.14159265……
will print –34.101, as the half even rounding criterion is used and the output
mantissa is confined only to 3 significant figures. Notice that the minus sign is
added, even though it is not the part of format string. There are situations, however,
for example in writing financial reports, where parentheses are placed around the
negative numbers. As indicated in Table 8.9, the format string can take two
patterns, first for positive numbers, and second separated by semicolon (;) for the
negative ones. Therefore if we wished to show negative numbers inside parenthesis,
the format string of the following type can be used (Figure 8.21):
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
“00.000;(00.000)”
Positive sub
pattern Negative sub
pattern
FIG. 8.21
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
and then the code line such as below,
will print the number –34.1009 as (34.101). Understand that the only prefix and
suffix in the negative sub pattern are used in formatting the output. For example in
Figure 8.21, in the negative sub-pattern, the prefix is ‘(‘ and suffix is ‘)’. At the time
of this writing (April 2004), Sun’s API for DecimalFormat class states “If there is an
explicit negative subpattern, it serves only to specify the negative prefix and suffix;
the number of digits, minimal digits, and other characteristics are all the same as
the positive pattern. That means that "#,##0.0#;(#)" produces precisely the same
behavior as "#,##0.0#;(#,##0.0#)". Due to an unfixed bug in the DecimalFormat
Therefore we recommend that until this bug is fixed, except for the prefix and
suffix, the sub-pattern for negative and positive numbers must be identical!
The Listing 8.9 shows a simple program to format the negative numbers.
00001 import java.text.*;
00002
00003 public class NegativeNumPattern
00004 {
00005 public static void main(String[] args)
00006 {
00007 DecimalFormat DF = new DecimalFormat("00.000");
00008 double num = -34.1009;
00009 System.out.println("The number " + num + " using the pattern\"00.000\""
00010 +" is printed as " + DF.format(num));
00011 DF = new DecimalFormat("00.000;(00.000)");
00012 System.out.println("The number " + num +
00013 " using the pattern\"00.000;(00.000)\""+" is printed as "
00014 + DF.format(num));
00015 DF = new DecimalFormat("00.000%;(00.000%)");
00016 System.out.println("The number " + num +
00017 " using the pattern\"00.000%;(00.000%)\""+" is printed as "
00018 + DF.format(num));
00019
00020 num = -34098.2004;
00021 DF = new DecimalFormat("0,000.000%;(0,000.000%)");
00022 System.out.println("The number " + num +
00023 " using the pattern\"0,000.000%;(0,000.000%)\""+" is printed as "
00024 + DF.format(num));
00025
00026 //showsBug();
00027 }
15
To find the Java version in your machine type java –version on command line. The output may
look like the following:
java version "1.4.2_03"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.2_03-b02)
The Figure 8.22 shows the output for the Listing 8.9.
The number -34.1009 using the pattern"00.000" is printed as -34.101
The number -34.1009 using the pattern"00.000;(00.000)" is printed as
(34.101)
The number -34.1009 using the pattern"00.000%;(00.000%)" is printed as
(3410.090%)
The number -34098.2004 using the pattern"0,000.000%;(0,000.000%)" is
printed as (3,409,820.040%)
FIG. 8.22
The suffix and postfix parenthesis are applied around the negative numbers as per
provision by the negative sub-pattern.
If Str is null or has zero length, then throw an exception or exit the method.
If width is negative or zero then set width equal to the length of Str.
If length of string is equal to width, then print the string and exit method.
If character at index zero of Str is a digit or character ‘$’ or ‘-‘ or ‘(‘
If right justification print is true then
Print the leading fill characters (which is equal to difference of width
and number of characters in Str)
Print Str
Else
Print the String
Print the fill characters
Else
If length of the Str is equal to width then
Print Str
If left justification print is true then
If length of Str is less than width then
Print the Str
Print numbers of fill characters equal to the difference
between length of Str and width
Else
From Str, print only the number of characters equal to width
Else
If length of Str is less than width then
Print numbers of fill characters equal to the difference
between length of Str and width
Print the Str
Else
From Str, print only the number of characters equal to width
00058 else
00059 {
00060 if(!just)
00061 {
00062 if(Str.length()<width)
00063 {
00064 //print left justified and pad up to width with fill
00065 output.print(Str);
00066 for(int index = 0; index<(width - Str.length());index++)
00067 output.print(fill);
00068 output.flush();
00069
00070 }
00071 else // Str is non-numeric and greater than width
00072 {
00073 //only print the substring up to the width
00074 output.print(Str.substring (0,width));
00075 output.flush();
00076 }
00077 }
00078 else
00079 {
00080 if(Str.length()<width)
00081 {
00082 //print right justified and pad up to width with fill
00083 for(int index = Str.length(); index<width; index++)
00084 output.print(fill);
00085 output.print(Str);
00086 output.flush();
00087
00088 }
00089 else // Str is non-numeric and greater than width
00090 {
00091 //only print the substring up to the width
00092 output.print(Str.substring(0,width));
00093 output.flush();
00094 }
00095 }
00096
16
The use of constructor PrintWriter (OutputStream out, boolean autoflush) automatically flushes
the buffer during the call to println method when autoflush is set to true.
For centered printing, the number of fill characters would be field width minus the
length of the string to be printed. This number may be odd or even. If this number
were even, then the number of fill character on each side of the string to be printed
would be even. Otherwise we need to make an arbitrary choice as to which side of
the string (left or right) must have the extra character. We choose that right side of
the string has the extra fill character if the number of fill characters needed in
centered printing are odd. L8.10A#139-147 show as to how the above algorithm is
executed. The remainder of the difference of width and the string length when
divided by two is found (L8.10A#141). This value would either be zero or one. The
number of pad characters is given by the value half of the difference width minus
the string length (L8.10A#142). The numbers of pad characters are first printed
((L8.10A#143-144). Then the string is printed (L8.10A#145). Finally the right side
pad characters are printed (L8.10A#146-147).
The testing strategy for the class FixedWidthOutput includes printing the numeric
and non-numeric strings of length equal to, greater than, and lesser than the print
field width. Print formats include left justified, right justified and center justified.
Figure 8.23 shows the results. (The first three characters in Figure 8.23 are line
numbers, which are not the part of output).
001 Outputting string "A really really really long String of length = 49" in column width = 49
002 A really really really long String of length = 49
003 Outputting string "A really really really long String of length = 49" in column width = 40
004 A really really really long String of le
005 Outputting string "A really really really long String of length = 49" in column width = 59 left
justified padded with character *.
006 A really really really long String of length = 49**********
007 Outputting string "A really really really long String of length = 49" in column width = 59 right
justified padded with character *.
008 **********A really really really long String of length = 49
009 Proceeding to demonstrate numeric outputs.
010 Printing the numeric String -90009.90009 of length = 12 in column width 12
011 -90009.90009
012 Printing the numeric String -90009.90009 of length = 12 in column width 7
013 -90009.90009
014 Printing the numeric String -90009.90009 of length = 12 in column width 22
0015 right justified, padded with character *.
0016 **********-90009.90009
017 Printing the numeric String -90009.90009 of length = 12 in column width 22
018 left justified, padded with character *.
019 -90009.90009**********
020 Printing the numeric String -90009.90009 of length (after formatting) = 13 in column width 13
021 (90009.90009)
022 Printing the numeric String -90009.90009 of length (after formatting) = 13 in column width 8
023 (90009.90009)
024 Printing the numeric String -90009.90009 of length (after formatting) = 13 in column width 23
025 right justified, padded with character *.
026 **********(90009.90009)
027 Printing the numeric String -90009.90009 of length (after formatting) = 13 in column width 23
028 left justified, padded with character *.
029 (90009.90009)**********
030 Now testing centered printing. For numeric values we use negative currency.
031 Printing the currency String of length (after formatting) = 11 in column width 22
032 center justified, padded with character *.
Java allows one to provide a separate pattern for the negative numbers, which
includes a prefix and/or a suffix. The format string "00000.00000;(00000.00000)"
provides a left and right parenthesis for the negative number as is customary in
Locale USA (L8.10#51). Using this new format string val is printed in field width
less than and equal to its width (L8.10#53-59). In both cases the full numeric
encased in a pair of parentheses is printed (F8.23#21 & #23). The results from right
justified and left justified printing (L8.10##61-69) in larger field widths are similar
(F8.23##26 & #29), as the leading and lagging fill stars are printed.
Centered printing is tested next using a negative currency, where the initial value of
the currency is set to val = -9999.98456 (L8.10#73). The format string for val is then
created using the getCurrencyInstance method of NumberFormat class (L8.10#74).
This currency string is then center justified printed in field widths that are 11
*****($9,999.98)******
printing five stars before the number and six after it (F8.23#33). You may recall that
it was coded into the algorithm that if in center printing, the number of extra
columns is an odd number, then extra fill character is printed to the right side of the
printed string. The numeric currency string prints in entirety even when field width
is lower than its length (F8.23#36).
Finally center printing of non-currency string tested. The significant result in this
test is that if output field width is smaller than the string length than lagging
characters are chopped off. Code line L8.10#90-93 output the result (F8.23#42)
where the string “A short String” is printed shortened by five columns as
“A short S”. The decision to chop off the lagging characters is arbitrary, but logical,
as the printing of leading characters gives a fair idea about the contents of the whole
string.
Parameters:
pathname - A pathname string
We should become clear about the terms pathname and abstract pathname. The
abstract pathname for a file/folder is the full path name, which starts with the drive
letter (in Windows) and terminates with the file/folder name. The abstract
pathname has two components:
Every name in the abstract pathname, except for the last one is a
directory or folder. The last one could be a directory or a file. For example the
Figure 8.24 shows the directory structure to get to the folder
Topic02IntroductionToJava. If we were to use the file HelloWorld.java from this
folder, then the abstract pathname for
FIG. 8.24
DOS style abstract pathname
this file would be:
C:\_Courses\_Java\Topic02IntroductionToJava\HelloWorld.java
On a Unix system, the corresponding abstract pathname may look like as follows:
/_Courses/_Java/Topic02IntroductionToJava/HelloWorld.java
The UNC pathname system is used for computers that are networked together on a
Windows 9x, NT, 2000, or XP network. In such network, each computer is given a
name, and there may be a shared folder, which is accessible to all network members.
Assume that the name of the computer, which contains the shared folder _Courses,
is ComPC. Then the abstract pathname string (assuming the file structure similar to
the one shown in Figure 8.24) would be:
\\ComPc\_Courses\_Java\Topic02IntroductionToJava\HelloWorld.java
However if a file and a class using it reside in the same folder, then one can simply
pass the file name to the constructor of File class. The constructor then converts that
file name into an abstract pathname by getting additional information from the
operating system.
Notice that we state of two components for abstract pathname, the first one is
optional. Therefore the abstract pathname can have two forms, which are:
1. Absolute pathname: which requires the part one of the two components,
and which ascertains that no additional information is required by JVM to
locate the file.
2. Relative pathname: If absolute pathname is not given then JVM needs
additional information to locate the file. JVM attempts to locate the file
“relative” to the directory in which it was invoked. For example when we
only provide the name of a file that resides in the folder, in which JVM was
invoked, it is found because JVM first looks for it in the current directory.
Any pathname that is not absolute will be interpreted as a relative pathname.
It appears that on Windows system, either file name provided must be absolute, or
the file must be in the folder in which JVM is invoked.
Table 8.11 gives the summary of important methods from class java.io.File. The
important point in understanding the description of File class methods is, that once
a File object is created by passing a pathname string to the File class constructor,
then the File object thus created represents that directory or file.
17
Deletion will not be done if an abnormal program termination, for example invoking of an
exception took place.
Class IOManagement
We design a class IOManagement, whose member methods would create the objects
of File class, and use its methods to facilitate input/output in Java programs. Clients
of class IOManagement would only be able to access some of its static methods and
would not be able to instantiate it. The class would have the methods that would
fulfill the following goals:
1. Return a BufferedReader object to read from keyboard.
2. Return a BufferedReader object to read from a file.
3. Return an object to write to a newly created output file in the buffered mode.
4. Return an object to append to a new or existing file in buffered mode.
5. Return a String, which has the description of main properties of a File object
passed to the method.
Table 8.12 gives a summary description of the member methods for class
IOManagement. Notice that method getFileName and constructor are private
members. The method getFileName is only used internally by other class methods.
All methods are static.
getFileName
private String getFileName(String Name)
throws java.io.IOException
Gets the String for the name of input file that exists and is not empty, not
hidden, can be read, and output file which either does not exist or is intended
to be re-written or appended by the user and has write permission.
Parameters:
Name - is the name of the file to be opened for reading or writing.
Returns:
The valid String with the filename.
getFileReader
public static BufferedReader getFileReader()
throws java.io.IOException
Gets the BufferedReader object bonded to an existing input file.
Returns:
The BufferedReader object for an existing input file.
getFileWriter
public static PrintWriter getFileWriter()
throws java.io.IOException
Gets the PrintWriter object bonded to an existing output file to write in
buffered mode.
Returns:
The PrintWriter object to a existing output file.
getFileWriterAppend
public static PrintWriter getFileWriterAppend()
throws java.io.IOException
Gets the PrintWriter object that will append to an existing file, in buffered
writing mode.
Returns:
The PrintWriter object to a existing output file to append to it.
getKeyboardReader
public static BufferedReader getKeyboardReader()
throws java.io.IOException
Gets the BufferedReader object to read from keyboard
Returns:
The BufferedReader object to read from keyboard.
getProperties
public static String getProperties(File My_File)
The ALG 8.5 gives the algorithm for the method getFileName.
In ALG 8.5 Section 3.34 ascertains that the input file is actually a file, is not hidden,
has read permission, and has data in it; otherwise the user is iterated through to
enter the input file name again. Section 3.35 ascertains that if output file exists then
it has write permission, it is a file, it is not hidden and user wishes to overwrite or
append to it; otherwise user is iterated through to enter the output file name again.
Listing 8.11 shows the source code for the class IOManagement.
00001 import java.io.*;
00002 import java.util.*;
00003 public class IOManagement
00004 {
00009 private IOManagement(){}
00017 private static String getFileName(String Name)throws IOException
00018 {
00019 boolean done = false;
00020 String File_Name = "";
00021 BufferedReader KB = getKeyboardReader();
00022 do
00023 {
00024 System.out.println("Type the " + Name + " file name and press enter key.");
00025 File_Name = KB.readLine();
00026
00027 if(File_Name == null || File_Name.length() == 0)
00028 {
00029 System.out.println("No file name entered.");
00030 done = false;
00031 }
00032 else
00033 {
00034 File FR = new File(File_Name.trim());
00035 boolean isExisting = FR.exists();
00036 if(Name.equals("input")&& (!isExisting))
00037 {
00038 System.out.println("The input file does not exist.");
00039 done = false;
00040 }
00041 else if(Name.equals("input")&& isExisting)
FIG. 8.25 A
FIG. 8.25B
The method getFileWriter binds the output file name to a FileWriter object, which
in turns binds to a BufferedWriter object, which finally binds to a PrintWriter
object, and method returns this composite object to the caller. The method
getFileWriterAppend works in a manner similar to the method getFileWriter, with
one difference, that the object FileWriter is built to append to the output file. This is
done by calling a FileWriter constructor, where the second argument (a boolean) is
set to true to indicate that output file must be written in the append mode
(L8.11#138).
Method getProperties
The method getProperties gets a File object and returns a string, which displays the
properties of the file object passed to it provided that the object is bonded to a file or
directory. The code first checks whether the object passed is an existing file or
directory or not (L8.11#160). If object exists then its absolute path and abstract path
is concatenated to the string to be returned (Str). Inside the first if block, the
method has two if/else-if blocks. The first block executes if the File object is a file
(L8.11#168-187). Following tests are done on the file object and the relevant
information is added to the string Str.
1. Date on which the file was modified last (L8.11#169-170). Understand that
the method lastModified returns the time as a long number. To convert it to
an actual date format, we pass it to the constructor of class java.uti.Date and
then call toString method for Date class to convert to regular date format.
For example the code line such as:
The else-if block (L8.11#188-208) performs the above tests (1 to 5) if the File object
is a directory, and concatenates the results to string Str. The abstract pathname
stored in the object File may be an absolute pathname or a relative one. The
program can find the parent of the file object only if the pathname stored is absolute
one. Therefore the method performs a test whether the File object has an absolute
path stored in it (L8.11#209). If that is true then the name of the parent is added to
the information string Str (L8.11#211-212). If the File object does not exist then the
string returned indicates that the file/directory does not exist.
Line (L8.12#9) calls the method getFileWriter from IOManagement class. This
method also calls the getFileName method (L8.11#124), which prompts the user to
enter an output file name. When user enters the file names html, a directory
(F8.26# 22), no_write, a file with read only access (F8.26#25), and a hidden file
hidden (F8.26#28), the user is iterated through the do-while loop in method
getFileName (Listing 8.12) each time with appropriate message printed for the user.
Then user enters a filename sys (F8.26#31), which exists. Since this is a pre-existing
file the program asks user if they would like to overwrite this file or append to it
(F8.26#32-33). If user response is not ‘Y’ or ‘y’, then they are iterated through
again, until a valid yes response is received (F8.26#34, F8.26#37, F8.26#40, F8.26#42,
and F8.26#46). If user provides the name of an existing output file then loop
iteration stops only under two conditions. Either user wishes to overwrite or append
Finally in Listing 8.12 we test the method getProperties from class IOManagement
(L8.12#11-13). User is prompted to provide the name of a file or directory whose
properties are needed. A File object is created, and the last line in Listing 8.12 print
the string returned from method getProperties. The user is prompted to provide the
file/directory, whose properties are needed (F8.26#54). The user provides the
directory html (F8.26#55). This directory has some html file in it. Program lists its
properties (F8.26#56-63). It is important to note that length method in File class
gives a size only for files, and it will always show a size of zero for anything that is
not a file or for an empty file. Lines F8.26#70-71 show that if method getFileReader
is called and a name of non-existing file is given, then such file (CreateIt) is simply
created.
Five more tests are done on method getProperties (Run #1 to Run #5, Figure 8.26).
In Run #1 the name of a non-existing object DoesNotExist is provided, and as
expected by executing the line L8.11#213-214, the program prints that such object
does not exist (F8.26#78). In Run #2 a hidden directory HiddenDirectory is
provided and passed as File object to method getProperties. Its properties are
printed in Figure 8.26, (F8.26#84-91). The line F8.26#91 confirms the hidden status
of this directory.
Understand that the parent of a file or directory is printed only when the path
provided to the program is absolute path. For example in Run #4 the absolute path
to file IOManagement.java is provided (F8.26#109-110). This path is:
C:\_Courses\_Java\_LectureNotes\_Topic08StandardInputAndOutputInJava\
FixedWidthOut\IOManagement.java
Run #5 shows that when the full path to a directory is given (F8.26#126-127), then
its parent directory is also printed (F8.26#137-138). As long as the abstract path
stored in the File object is absolute path, its parent can be determined and
displayed.
FIG. 8.27
The file shown in Figure 8.27 is an ASCII file, where data are stored in the following
order: Part Name (either one word or many words joined by underscore), number
of units, and unit price. For example in above figure, the first set of data lists Chisel,
whose 50 units are in store and unit price is $9.99. The report is required in the
format shown in Figure 8.28.
Inventory
Table
Inventory
summary
FIG. 8.28
Notice that in inventory summary in the lower part of the report, the total cost of
inventory would be the sum of TOTAL VALUE column in the main report above it.
Class Status
IOManagement Written and tested
FixedWidthOutPut Written and tested
InventorySummary To be Written and tested
InventoryTable To be Written and tested
DriverInventory To be Written and tested
Table 8.13
One must know that several designs are possible to satisfy a certain set of user
requirements. In a sophisticated design one would produce three design alternatives,
which would include high end, middle end, and low-end solutions. The detail of
overall design methodology is discussed in chapter one of this book. Here we jump
first directly to designing the attributes and constants each of our un-designed
classes would need and then we decide on “intelligence” (which comes in forms of
class methods) to be imparted to each class.
All constructors and methods must maintain the above invariants. For the sake of
simplicity we do not, for now, write our code to maintain the above invariants. Later
on, when we have learned the technology of exception handling, we would revisit
this topic and introduce the technology for maintaining the above invariants.
All other constant data members would be initialized to values given in the last
column of lower table in Table 8.14. Table 8.15 summarizes the two constructors
provided. Additional constructors may be provided for testing purposes.
18
A class can have inner classes, in which such data member also add to the “intelligence” of
enclosing class. We discuss inner classes later.
19
In an improved design we may not need the instance variable cost_of_inv. Rather it can be derived
from the multiplication num_items*ave_cost.
Table 8.15
In addition to two constructors the class InventorySummary has only one method,
which is used to print the summary report. Table 8.16 gives the design summary of
method printInvSummary.
Algorithms
The algorithm for the constructor is straightforward. Therefore we only discuss the
algorithm for method printInvSummary (ALG 8.6).
Listing 8.13A gives the source code for class InventorySummary, which conforms to
above design specifications.
00001 import java.io.*;
00002 import java.text.*;
00007 public class InventorySummary
00008 {
00011 private final int col = 80;
00015 private final boolean right = true;
00019 private final boolean left = false;
00023 private final char fill_char1 = ' ';
00027 private final char fill_char2 = '*';
00031 private final String Head1 = "The total cost of inventory = ";
00035 private final String Head2 = "The lowest cost item = ";
00039 private final String Head3 = "The highest cost item = ";
00043 private final String Head4 = "The average cost of inventory item = ";
00047 private final String Head5 = "The cost standard deviation = ";
00051 private final String Head6 = "Total number of units in inventory = ";
00056 private final String Message = "Not Calculated";
00060 private double cost_of_inv;
00064 private double lowest_cost;
00068 private double highest_cost;
00072 private double ave_cost;
00076 private double std_dev;
00080 private int num_items;
00087 private String Title;
00091 public InventorySummary()
00092 {
00093 Title = "Summary of";
00094 }
00107 public InventorySummary(double ci, double lc, double hc, double ac,
00108 double sd, int ni, String Title1)
00109 {
00110 cost_of_inv = ci;
00111 lowest_cost = lc;
00112 highest_cost = hc;
00113 ave_cost = ac;
00114 std_dev = sd;
00115 num_items = ni;
00116 Title = "Summary of " + Title1;
00117 }
private:
InventorySummary
InventorySummary Summary 2000
private:
//Other data members Data members
Constructors
Constructors
printInvSummary
Member methods
The class InventoryTable has three instance variables: Title, Summary and column.
Title is a String data type, which forms the overall title for the report. Summary is
the InventorySummary object, which when filled and printed fulfills the
responsibility for printing the summary part of the inventory report. Generally
most inventory tables have fixed number of columns, but here for the sake of
flexibility, we use an integer variable for number of columns.
The class InventoryTable has 11 instance constants, of which six are unique to this
class, while other five have the same values and names as they do in Class
InventorySummary. In an upgraded design we could cut down on this duplication,
by designing a separate class, to just store all the constants. The constant strings
simply indicate the headings of columns in the inventory table (Figure 8.28).
Table 8.18 provides summary of constructor and methods for class InventoryTable.
Parameters:
Pwriter - is the object passed to print the header of the inventory table to either a file
or console.
col_width - is the width in number of columns in which the table header is to be
printed.
Parameters:
Pwriter - is the object passed to print the header of the inventory report to either a
file or console.
Parameters:
Pwriter - is object bonded to an output file or console.
Buff_Freader - is an object bonded to an input file.
Parameters:
Pwriter - is object bonded to an output file or console.
Buff_Freader2 - is an object bonded to an input file.
Parameters:
Buff_Freader2 - is an object bonded to an input file.
Algorithms
Most of the work in class InventoryTable is done by the private method
printInvTable, whose algorithm is described in ALG 8.7. The method has the
following purposes:
1. Print header for the inventory table.
2. Read input data file to get raw data.
3. Print inventory table
4. Get the necessary data for the instance data member Summary and fill it.
The client program (Listing 8.13C) creates an object Table of type InventoryTable
(L8.13C#7). It uses IOManagement class methods getFileReader and getFileWriter
to get the user input for the input and output file names (L8.13C#8-9). The Table
object calls member method printReport (L8.13C#11) and passes to it the
BufferedReader and PrintWriter objects created earlier. The printReport method
triggers the chain of method calls depicted in Figure 8.30 and prints the inventory
report to the user specified output file. Figure 8.31A shows the console output from
the Listing 8.13C, whereas Figures 8.31B and 8.31C show the input and output files
respectively.
FIG 8.31A
FIG 8.31C
Questions (Multiple choice questions may have more than one correct answer)
1. Which of the followings can be used for standard input in a java program:
A] keyboard
B] ASCII input file
C] Mouse
D] All of above
2. Which of the followings can be used for standard output in a java program:
A] Console
B] ASCII output file
C] Computer Speakers
D] All of above
3. Which Java package is needed to be imported in order to write to a file?
4. Which of the BufferedReader class constructor allow one to specify a size for the
input buffer?
5. Which of the member method from BufferedReader class reads the input
character by character?
6. Which of the member method from BufferedReader class reads input line by
line?
7. Write the headers for the following member methods from BufferedReader
class: read, readLine, close. Which of these method(s) is/are overloaded?
8. (T/F) The BufferedReader class has an argument-less constructor.
9. When reading from the keyboard what is the function of InputStreamReader
object that is passed as an argument to the BufferedReader constructor?
A] It converts characters flowing from keyboard into bytes
B] It converts bytes flowing from keyboard into characters
C] It buffers the input
D] It corrects any user errors during data input
E] It acts as a pipe between objects InputStream and BufferedReader.
10. The object InputStream used during reading from keyboard is:
A] System.in B] System.out C] Of type PrintStream
D] Of Type PrintWriter E] Of type InputStreamReader
11. What is returned by read method when the end of file is reached?
A] null B] ‘\n’ C] 32 d] –1 E] 65
12. What is returned by readLine method when the end of file is reached?
A] null B] “\n” C] 32 d] –1 E] 65
13. (T/F) For character-by-character non-buffered reading from an ASCII file,
one can simply use a FileReader object bonded to that ASCII file.
14. What is true about FileReader class?
A] It does not have a method with name read
B] It does not have a method named readLine
C] It does not have a constructor that can take the input file name as
a String
Appendix
00001 import java.io.*;
00002
00003 public class KeyBoardInputUsingIOException
00004 {
00005 public static void main(String [] args)
00006 {
00007 InputStream Key_Stroke = System.in;
00008 InputStreamReader Isr = new InputStreamReader(Key_Stroke);
00009 BufferedReader Kb_Input = new BufferedReader(Isr);
00010 System.out.print ("Please type a long string and press enter: ");
00011 System.out.flush( );
http://www.horstmann.com/
Some of our analyses in early chapters showed that as the computer program
accepts data from the user (human or other machines), they need to be stored, and
programmer needs to specify program variables to hold the user data. Naming the
individual memory locations for data persistence during the life of the program
works when the amounts of user data are small. However, if user had large amount
of data that needed processing, then method of naming individual memory locations
to store data becomes tedious. We discuss with some examples.
We further enlighten the concept of arrays by taking two examples; let us say
storing the blood pressure data on patients in a Doctor’s office by declaring one
variable for each patient’s blood pressure. This method is shown in Figure 9.1
below.
Lecture10_3Var.ppt
5000 7000
Variable
names
FIG. 9.1
Obviously if it was a matter of just storing the blood pressure of three patients, then
construct shown in Figure 9.1 will suffice, but what if 1000 patients blood pressure
data were required to be stored? In that case, the Java data structure called arrays
is very useful and a graphical representation of it to store blood pressure of large
number of patients is shown in Figure 9.2 below. We also show the process in the
power point presentation below.
Error! Not a valid link.
As seen in Figure 9.2, Java allows us to declare a large number of variables, whose
data type is same, by a simple declaration like
1
See Table 4.2 in chapter four for other types.
An array like the one in Figure 9.2 is called a one-dimensional array, whose
characteristics are summarized in the Figure 9.3.
ArrayName [index]
FIG. 9.3
Figure 9.4 gives syntax for single line general declaration of arrays in Java as
follows.
DataType [ ] Array_Name = new DataType [IntExpression];
OR
DataType Array_Name [ ] = new DataType [IntExpression];
FIG. 9.4
Note that in array declaration the length expression in square bracket can be any
integer type expression except long data type. The array length expression must
evaluate to a specific positive value at run time. For example all array declarations
below are legal.
Table 9.1 shows few examples of array declarations that would cause compile error.
Array declaration which would cause Reason for compile error
compile error
DataType [ ] Arr = new DataType [ 9.5 ]; Array length cannot be floating point
type expression.
DataType [ ] Arr = new DataType [ 10L ]; Array length cannot be long type
expression.
DataType [ ] Arr = new DataType [ true ]; Array length cannot be a boolean
value.
Some of you may be surprised to note that array length cannot be a long type
expression, even though long data is an integer type. You may recall that the
maximum allowed value for long type variable is 9.22…E18. You would also recall
that byte data type takes one byte for each of its variable (the smallest data type in
Java). Imagine that if long data type were allowed to be the length expression for an
array, then under some accidental programming condition, one may end up
declaring an array, which, even for byte data type, would require 9.22…E18 bytes
of memory, which is equivalent to 9.22 exabytes. Needless to say that such memory
requirement will crash the program instantly.
FIG. 9.6
But if we make the following assignments,
FIG. 9.7
then the state of array changes to the one in Figure 9.8
Unassigned
components
are still null.
FIG. 9.8
A Common Mistake
A common mistake in using Java arrays is to declare an array of objects, but then
forget to make a constructor calls for the array components to allocate memory for
them, and then try to use them in some form. Because in absence of constructor call,
only a null object is stored, the attempt to use a null object causes Java Virtual
Machine to throw a null pointer exception. The compiler will not save you, because
having a null stored in an object reference is not a compile error. Listing 9.1 below
shows the error, its results and Listing 9.2 shows the solution.
>javac CommonMistake_Array.java
>java CommonMistake_Array
Exception in thread "main" java.lang.NullPointerException
at CommonMistake_Array.main(CommonMistake_Array.java:11)
Listing 9.1
In 9.1, the program will compile, but it will crash when executed because the
reference Arr[0] stores a null as there was no constructor call made to allocate
memory on the heap. Thus when we try to set the field of null object Arr[0] to value
five the program crashes. Solution to this problem is shown in Listing 9.2.
>javac CommonMistake_Array.java
Value 5 as
>java CommonMistake_Array expected is
5 printed.
Listing 9.2
Of course the ideal solution is to make a constructor call soon after the array is
declared (Listing 9.3).
Listing 9.3
FIG. 9.9
Three reference types in Java are array operator [ ], interface, and class. We have
already discussed the class reference types. It is important to recall that all reference
types only hold the address of no-name objects on the heap. Figure 9.10 shows the
FIG. 9.10
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Notice that array reference num only stores the address of the first element in the
array located on heap. In that sense the array name is no different than the String
reference Name, which also stores the address of object with “John” in it.
When the array declaration has no value on right hand side, then the array
reference contains an undefined value, which must be initialized to a definable value
prior to its use. Multiple arrays of same data types can be declared on the single
line. For example the statement below declares five different arrays of int data type.
int [ ] foo_one = new int [5], foo_two = new int [10], foo_three;
foo_three = new int [40];
The first statement creates and initializes the array references foo_one and foo_two,
whereas the second statement initializes foo_three.
For an int type array the above syntax could boil down to the following statement
type:
Figure 9.11 shows the schematic picture of int array Arr in the program heap
memory.
There is an alternate form available for implicit array sizing, which is more
appropriate when an un-named array is to be passed to a method as an actual
argument. This alternate declaration has the following type of syntax.
No length is specified when followed by initialization list.
Question: What will be the value stored in the third element of array
Arr2 in above declaration?
The alternate syntax for implicit array sizing declarations given below are legal but
these forms are not encouraged for usage.
Question: What will be the value stored in the third element of array
Arr4 in above declaration?
Due to efficiency concerns one must use the implicit array sizing technique only
when the number of array elements involved is small. The reason for this would be
discussed after we have discussed the read and write access to array elements in the
next section.
Microsoft PowerPoint
Presentation
Figure 9.12A shows the initial state of an int array of five elements.
FIG. 9.12A
Figure 9.12B shows the state of the array, when a value of –5 is stored in the third
array cell.
FIG. 9.12C
Since stand-alone variables have read access, it is true of array elements as well
(Figure 9.13A).
FIG. 9.13A
An array of five elements is created and populated in Figure 9.13A. The second code
line prints the value stored in the second array element, which is eight. Figure 9.13B
shows the console output, when statements to print the contents of randomly chosen
array cells are executed.
FIG. 9.13B
Now we discuss as to why for large arrays the implicit array sizing or direct array
assignment must be avoided. Take for example the declaration:
Compiler, in order to make above assignment would need to break down the above
code as follows and create its byte code.
Not only this, but the JVM will have to interpret the above byte code one line at a
time. Needless to say that for large direct assignment arrays, whole process would
be very slow. Therefore it is best to use direct assignment only for small size arrays.
The listing 9.4 will print 22, the length of array arr. Notice the syntax to access the
length of a Java array:
length data member
Array name arr.length storing the array length
FIG. 9.14
In above Figure, on the right hand side, first the array int_arr calls its member
method clone to clone itself. However, the value returned by clone method is not
type int [ ]. Rather it is of type java.lang.Object, which is a Java class. Therefore the
cast operator (int [ ] ) is needed to be applied on the return value before it can be
copied to the clone_arr, which is of type int [ ]. Lines 19-20 print the cloned array.
Figure 9.15 shows the typical output from Listing 9.5.
FIG. 9.15
Figure 9.16 shows the schematic structure of object referred to by reference Arr and
created by the following program statement.
2
Once again, this issue will become clearer after discussion of inheritance in next chapter.
Parameters:
src - the source array.
srcPos - starting position in the source array.
dest - the destination array.
destPos - starting position in the destination data.
length - the number of array elements to be copied.
FIG. 9.17
The method arraycopy takes two non-null arrays src, and dest as arguments. The
method copies length number of elements from src into the array dest. The copy
FIG. 9.18
Line 21 declares an int array called Source of size MAX. Source is filled with
random numbers and printed (L9.18#23-27). A Destination array of type int is
created whose size is 2*MAX (L9.18#31). The method arraycopy from System class
is called to copy MAX/2 elements from Source to Destination (L9.18#37). The copy
starts at index srcPos in Source array and corresponding copy location in
Destination array is destPos. The values of MAX (=10), srcPos (=2), and destPos
(=5) are given as class constants (L9.18 #8, 12, and 16).
Second line of Figure 9.18 shows the entire Source array created by Math.random
generated values. Since srcPos is set to a value of two and length to be copied to
MAX/2 = 5, the values to be copied from source array are: 5, 9, 9, 6, and 4. Last line
of output shows that exactly same elements are present starting index destPos = 5 to
index nine in Destination array. L9.18# 41-42 and L9.18#48-49 print the copied
elements from Source and Destination arrays respectively, which are identical.
An integer array of size ten is declared and filled with random numbers using the
for loop. The array is subsequently printed. Depending upon the numbers generated
by method Math.random ( ) different set of values would be stored in the ten array
elements. Listing 9.7 gives us a “bare bone” technique to populate and print arrays.
However realizing the fact that any real array would be entered into the program
memory from user input (file, database, or keyboard); we can develop an advanced
version of this technique. We design a class called ManageArray, which has the
following goals:
• Take user input for an integer array3 either from the keyboard or from an
input file.
• Display the array read from keyboard or file on the console.
• If array was read from the keyboard, then give user an option to write or
append it to an output file.
• Handle all input errors in user response during menu choices.
3
The limitation of data type of the array restricted to int type can be removed in the more advanced
versions of ManageArray or one can use methods in class java.lang.reflect.Array class (to be
discussed later).
Obviously, the member methods of class ManageArray would need to read data
from keyboard and files as well as write to files. For all file authentication purposes
the methods of class ManageArray use our previously developed class
IOManagement (developed in chapter 8). Table 9.2 gives the summary of the design
of class ManageArray.
Table 9.2
The methods of class ManageArray tested by the class DriverManageArray work as
follows. Inside a do while loop the method getUserResponse is called that asks user’s
choice to populate array either from a keyboard or from an input file. In first user
choice the method fillFromKeyboard is called, whereas the method fillFromFile is
called for other user choice. Both fill methods create a StringTokenizer object,
which stores the array tokens. This StringTokenizer object is passed to the print
method, where the array is created and printed. Listings 9.8A and 9.8B show the
classes ManageArray and DriverManageArray.
00001 import java.io.*;
00002 import java.util.*;
00003
00009 public class ManageArray
00010 {
00014 private static PrintStream Console = System.out;
00015
00020 private ManageArray(){}
00021
00029 public static char getUserResponse(int flag) throws IOException
00030 {
00031 BufferedReader KB = IOManagement.getKeyboardReader();
00032 char choice = ' ';
00033 boolean done = false;
00034 String Input = "";
00035
00036 do
00037 {
00038 if(flag == 1)
00039 Console.println("Enter 1 to provide data from keyboard or 2 from a file.");
00040 else if (flag == 2)
00041 Console.println("More data? [Y]es or [N]o?");
00042 else
00043 Console.println("Append your array to an output file ? [Y]es or [N]o?");
00044
00045 Input = KB.readLine();
00046 if(!(Input == null)&&!Input.equals(""))
00047 {
00048 Input = Input.trim();
00049 if(flag == 1)
00050 {
00051 if(Input.equals("1")|| Input.equals("2"))
00052 done = true;
00053 else
Sidebar 9.1
The design of class ManageArray shows an element of functioning of Software
Engineering. The lines 31, 86, 107, and 152 use the static member methods of class
IOManagement to get a keyboard reader, file reader, and file writer objects. Many
user errors can occur in getting the file related objects. For example the path of the
file may be wrong, the path given may not be a file, the file may be hidden. The
input file may not exist, may not have the read permission, or may be empty. The
output file may not have write permission. Since the designer and producer of the
class IOManagement already took care of all those error conditions, its client
ManageArray class does not have to worry about any of those details and can safely
use its methods to get requisite file reader and writer objects. Thus in this manner,
the IOManagement class is used as a “pre-tested” and qualified software component
by the software component class ManageArray. This is not too different from the
“assembly line” concept used in automobile manufacturing, where pre-
manufactured and tested components are assembled together to form the final
product - an automobile.
Line 4 of Figure 9.19 shows that user enters 1, in order to supply data from
keyboard. Since the value returned by method getUserResponse would also be 1, the
line 18 of Listing 9.8B executes and user is routed to method
fillFromKeyboard of class ManageArray. This method calls the method
getKeyboardReader from class IOManagement to get a BufferedReader object KB
(L9.8A#86). The method prompts user to enter the integer data to be stored in the
array as space de-limited tokens (L9.8A#87-88). User input is stored in the local
String Input. Understand that user may again errantly enter a null or an empty
string. The method fillFromKeyboard checks for those conditions (L9.8A#91) and if
indeed the string Input is anything other than null or empty character set, it is
passed to the StringTokenizer constructor, and its object St is created (L9.8A#93).
The object St is passed to the method print with boolean flag value equal to true
(L9.8A#94).
The purpose of print method is to create the array from the tokens stored in
StringTokenizer object passed to it, and display such an array to console and write
to file as needed. Method print first checks the array length by counting the tokens
stored in the StringTokenizer object St passed to it (L9.8A#127). If length is zero
then user is informed that no data were inputted and method print exits
(L9.8A#129-133). Otherwise an int array of length len, which is equal to the number
of tokens stored in the incoming object St, is created (L9.8A#135). The methods
hasMoreTokens, and nextToken of StringTokenizer class manage to fill the tokens
parsed as integers into the array arr (L9.8A#137-139). The array arr is then printed
using the technique similar to the one shown in Listing 9.7. Since user enters the
array from keyboard (F9.19#5-6) and the flag value passed to method print is true
(L9.8A#94), the if block starting at line 146 of print method is executed. This block
calls the method getUserResponse with an argument value 3, so that user is
prompted to indicate their choice whether they would like to write or append this
array to an output file (L9.8A#42-43)4 (see line 9 in Figure 9.19). The user chooses to
append the array entered to an output file (F9.19#10). In Listing 9.8A a PrintWriter
object is created by calling the getFileWriterAppend method from class
4
Technically the user is only prompted to append to a file. However if a file does not exist, then the
append mode will create it.
val
Prints val*val
to console
FIG. 9.20
In this example, using a loop, we pass each individual element of array called base
from main to a method called PrintSquare, which prints the square of each element
it receives. The method PrintSquare does not differentiate between an array element
and a single atomic data as long as the data type is same. Notice for example that in
first loop iteration in main, the value base[0] (=3) is passed to the method
FIG. 9.21
The arguments sent to the method to process array are the name of the array and its
logical processing length. The length parameter can be omitted if entire array need
to be processed. Figure 9.21 shows the example of finding an average of the numbers
in an array, when the array called base is passed to the method average.
FIG. 9.22
Pay attention to the syntax as to how the array name is used as formal argument to
the method average, compared to when the method is called from main.
The argument to average method contains the array data type, a square bracket,
and array name. In Figure 9.22 the header for method average can be written as:
The actual call to the method in the main is different as it just has the array name in
it. For example the call statement is:
A compile error will be caused if square brackets were to be included in the method
call. For example:
When an array is passed to a method, then the copy of the address of its base
element or its first element is passed as a parameter. For example in Figure 9.22 in
multiply2(base);
for(int i=0; i<base.length; ++i)
System.out.print(base[i] + “ “);
System.out.println( );
}
6 14 4 8 10
FIG. 9.22
In Listing shown in Figure 9.22, the array called base is passed to the method
multiply2. There each element is multiplied by a factor of two. Effectively then the
array base has changed in the main method as well. The console output in Figure
9.22 shows the changed state of the array as modified by method multiply2. So in
process of passing an array, since the address of base element is passed, effectively,
entire array is available to the calling method to modify it. Understand that the
method to which the array is passed can also assign that array reference to another
array. Java allows its array reference types to print the address stored in the array
name by using a method called hashCode (which is available to all Java reference
types). Output from Listing 9.9 proves that when the arrays are passed to methods,
the copy of the address stored in the array name is passed.
5
One must exercise caution is using the method hashCode in printing the address of a reference type.
It will not work if the object is immutable. In Java identical immutable objects print the same
hashCode, even if they are stored in two different memory locations.
Other possible action that method processArray can take is to reassign name nums
to another int array on heap as shown in the code snippet below.
There may be situations in which we wish that the method to which we pass the
array to couldn’t re-assign that array name. This can be accomplished by passing
the array to the method as a final reference. If the header of method processArray is
changed as follows:
then inside the body of processArray, the following code will cause compile error.
FIG. 9.24
Since the reference Names in the method processArrayOne points to the same array
as in main, the method has the random read/write access to the array. The method
changes the names stored in first four array elements (L9.10#56-59), changing the
state of the array as shown in Figure 9.25.
In the same vain, when an array is passed to a method in C++, if the keyword const
is placed before the array data type, then the method is allowed read only access to
the array. For example the method with the following header in C++ will have read
only access to the array called “Names”.
The header for the method processArrayThree given below looks almost like its
C++ counter part.
Unfortunately, even in C++ the use of const_cast operator can remove the
restriction of no write access originally imposed on a constant array. For example
the code below in C++ will not print the values 1, 2, 3, 4.
Anonymous Arrays
As mentioned earlier, one form of Java’s implicit array sizing declaration technique
allows the programmer to pass an anonymous array to a method as an argument. In
Listing 9.11 the main method passes an anonymous array to the caller method print,
which in turn prints it.
6
Even in C++, however, the use of const_cast can overturn the lack of write access to array which
was originally passed as a const.
Testing ArrayClass
Listing 9.12B shows two methods main1 and main2 used to test the
creation and printing of static arrays and instance arrays respectively.
00001 import java.io.*;
00002
00003 public class DriverArrayClass
00004 {
00005 public static void main(String[] args) throws IOException
00006 {
FIG. 9.28A
Assuming that user entered array length to be five and bottom portion of Figure
9.28A shows the names entered on the console input then a message to the affect that
number of names entered exceed array length is displayed (Figure 9.28B).
FIG. 9.28C
Comparing Figures 9.28A and 9.28C one notice that the output does not print the
presidents Herbert Hoover and Franklin Roosevelt as the array length was not large
enough and was not expanded to include them. All the singers hard coded in the
declaration of array Singers are displayed.
FIG. 9.28D
FIG. 9.28E
Notice that extra names are excluded.
An array exactly like the one above will not compile in Java (as null in Java is not a
primitive value). However Java will print a char array, just by passing it to the
method println as below even though the array Names is not a String.
This special facility to print an array in Java aggregately is not extended to data
types other than char! Printing a char array aggregately is the only aggregate
operation Java allows on arrays.
Swapping of values
A common programming need is to have a method that would swap the value of two
variables of same type passed to it. For example in C++ a swap method written
below can be coded in such a manner that upon completion of method call the
values stored in variables num1 and num2 would be swapped.
Swap in C++ can be coded such
void swap (int & num1, int & num2) that after method call the values
stored in num1 and num2 are
swapped.
Method Swap2
We illustrate above logic by exemplifying the method swap2, which accepts two
arrays, both with length one as arguments.
//watch PowerPoint presentation swap2.ppt now.
The main declares int arrays D1 and D2, each of length one and former storing a
value of 33, and later a value of 55 (L9.13#17-18, see also Figure 9.30A).
FIG. 9.30C
FIG. 9.30D
This changes num1[0] value to 55. Finally the original value of num1[0] saved in
temp is copied into num2[0] (Figure 9.30E).
Understand the general principle followed by the technology used by method swap2.
The data to be swapped are wrapped into objects, which are mutable, and then
references to these mutable objects are passed to swap method, which alters the
objects and the caller method then gets them in altered state. The principle
embedded in swap2 would swap any data type in Java. However, the limitation the
method has is that one must define a different swap method for different data type –
in other words the swap2 is not generic. A generic version of swap2 is designed in
swap3, which uses two StringBuffer objects as argument.
Method swap3
Strings in Java are immutable. Once its constructor constructs a Java String, it can
never be altered. However, the objects of class java.lang.StringBuffer are mutable.
A StringBuffer object can store a Java String and then allow modification on it.
Unfortunately the StringBuffer objects cannot be concatenated using the plus (+)
operator. Because StringBuffer is mutable, its object passed to a method allows the
method to alter it. Table 9.4 shows summary of important constructors and methods
of class java.lang.StringBuffer.
In order to swap primitives the values passed to swap3 are first converted into an
object of their wrapper class, and then the StringBuffer forms of these objects are
passed to the swap3 method. For example (L9.13#34), Data1 has a value of 1000. It
is wrapped into a StringBuffer object as follows (L9.13#40) (Figure 9.31):
FIG. 9.31
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
First the primitive Data1 is wrapped into int wrapper Integer by calling Integer
class constructor and passing Data1 to it as an argument. Then toString method of
class Integer returns a String version of wrapper Integer. Finally the String version
of Data1 wrapped into an Integer is passed to the constructor of StringBuffer class
to create a StringBuffer object C1 in Figure 9.31. A process that reverse engineers a
StringBuffer object back into a primitive would be needed after the call to swap3 is
finished.
7
We shall discuss protected access in the next chapter. Basically the protected members are available
to the class declaring them as well as to its subclasses.
The constructor Vector (int initialCapacity), allows user to predefine the initial
capacity. This is best used in those situations where user knows in advance as to how
many elements would be stored in the Vector, thus setting initialCapacity equal or
slightly larger than that.
Vector class has a long list of member methods and Table 9.5C summarizes them.
Summary of Methods for class java.util.Vector
void add(int index, java.lang.Object element)
Inserts the specified element at the specified
position in this Vector.
boolean add(java.lang.Object o)
Appends the specified element to the end of this
Vector.
boolean addAll(java.util.Collection c)
Appends all of the elements in the specified
Collection to the end of this Vector, in the order that they
are returned by the specified Collection's Iterator.
boolean addAll(int index, java.util.Collection c)
Inserts all of the elements in in the specified
Collection into this Vector at the specified position.
void addElement(java.lang.Object obj)
Adds the specified component to the end of this
vector, increasing its size by one.
int capacity()
Returns the current capacity of this vector.
void clear()
Removes all of the elements from this Vector.
java.lang.Object clone()
Returns a clone of this vector.
boolean contains(java.lang.Object elem)
Tests if the specified object is a component in this
vector.
boolean containsAll(java.util.Collection c)
Returns true if this Vector contains all of the
Method add(int index, Object element), adds the object element at the index passed
to it. The index can neither be negative, nor larger than the size of the Vector. If
there already is an element at the location index, then that and all lagging elements
are shifted to the higher index by one. Assume that a Vector Vec1 has the following
elements before add method is called.
Vector Vec1
[ “John”, “Mary”, “Ted”, “Adam”, “Tom”, “Pete”]
Method insertElementAt (Object obj, int index) works exactly like the method
add(int index, Object element). No elements are ever overwritten or removed in the
process of using methods with name add in them.
Methods clear and removeAllElements work exactly in the same fashion and
remove all elements from a Vector thus setting the size to zero. For example, a call
like Vec1.clear( ) on Vector in Figure 9.33B would result in deletion of all names and
a Vector of size zero.
Method Object remove(int index) removes the member at location index and
returns it to caller as a Java Object. On the other hand the method
void removeElementAt(int index) simply removes the element at location index.
Method int indexOf (Object elem, int index) starts to search forward for the
object elem from the location index, and if found returns the index of its first
occurrence. Obviously the returned value would be larger than the value of index
passed to the method. Method int lastIndexOf (Object elem, int index)
searches backwards starting from location index in the vector and if found returns
the index of first match. If found then returned value would be lower than the value
index passed to the method.
The method String toString( ) would return a String representation of the caller
Vector. For example the code snippet below would print all the names in the Vector
separated by comma and enclosed in square brackets.
Will print the following on console
String Str = Vec1.toString ( );
[John, Mary, Ted, Marcy, Adam,
System.out.println (Str); Tom, Pete, Jefferson, Jeff]
Vec1 is described in Figure 9.33B.
Method Object clone( ) would return a clone of caller Vector. This works exactly
the way clone method for array shown in Listing 9.5 works. The method
Object[ ] toArray ( ) returns an array of elements in the caller Vector in the
order in which they are arranged in the Vector. Method
Object elementAt (int index) returns the member of Vector at the location
index. On the other hand the method Object firstElement ( ) returns the element
at index zero in the Vector. The method Object lastElement ( ) returns the
element at the index size-1 in the Vector, where size indicates the number of
elements in the Vector.
Before calling the swap4, the caller method, two int variables value1 and value2 are
declared (Figure 9.34A) (Also see lines #75 -76 of Listing 9.13).
FIG. 9.34A
Two vectors Vec1 and Vec2 are then created and value1 and value2 wrapped in
their respective Integer wrappers are added to the location zero into Vec1 and Vec2
respectively (Figure 9.34B) (See also lines #81-83 & #85 in Listing 9.13).
8
Recall that Vector can never store primitives.
FIG. 9.34D
FIG. 9.34E
Notice that clear method only deletes the contents in the storage locations whose
addresses are stored in the Vector. The storage locations themselves are not
“garbage collected”. The locations whose addresses are stored in the Vector are
available to store new objects. Then in order to perform the swap, the contents of
Obj2 are added to the first location in V1, and that of Obj1 to the corresponding
location in V2 (Figure 9.34F) (See also Lines #161-162 in Listing 9.13).
Discussion of swap6
swap6 is usable for all primitive and String arrays (L9.14#63-128). It can be
modified to work for user defined data types. The header of method swap6 is given
below.
public static void swap6(int num1, int num2, Object Obj_Arr)
Integer I2 = new Integer (5); Will print true as Obj stores address of
Object Obj = I2; Integer I2, which is indeed and Integer
if (Obj instanceof Integer) instance.
System.out.println (true);
On the other hand if the selection structure in the above code is replaced as follows:
The code will print false, because Obj is not an instance of Double. The instanceof
operator works only when the object on its left hand side and reference type on its
right hand side, two of them, are “related”. When we learn inheritance and
polymorphism, it will become clear that Object Obj and reference type Double are
related in the sense that Double is also of type Object. Instanceof operator would
give a compile error if compiler can decide that variable on its left is not convertible
to the type specified on the right. For example the following would be a compile
error.
Compile error because at compile
Integer I2 = new Integer(5); time it can be determined
if(I2 instanceof Double) unambiguously that I2 is not
System.out.println (true); convertible to type Double.
9
Further details of RTTI are discussed in a separate chapter later.
Method swap6 comprises a system of nested if/else blocks, where each block tests to
decode the identity of the array Obj_Arr at runtime. For example the first block
pre-test condition is:
Notice that data type (or reference type) of int array is int [ ], which is used on the
right side of instanceof operator. The expression inside the if parenthesis would
evaluate to true if indeed Obj_Arr is of type int [ ]. If Obj_Arr is a reference to an
int array, then the if expression evaluates to true and first block in swap6 (L9.14#66-
71) is executed. To perform swap for sake of convenience, Obj_Arr is cast to arr, an
int [ ] type (L9.14#67). Then algorithm of swap2 in Listing 9.13 is used to swap the
values in the array (L9.14#68-70). Understand that references arr and Obj_Arr
point to the same array. Therefore the swap made is reflected in the original array
passed to swap6.
00002 2 3 3 1 8 5 3
00003 Calling the method swap5
00004 After swapping values at index two and five, the array is:
00005 2 3 51 8 3 3
00006 Before swapping values at index 1 and 4, the array is:
00007 7 3 2 0 47 8
00008 Calling the method swap6
00010 7 42 0 37 8
00011 Before swapping values at index 1 and 6, the String array is:
The method takes a BufferedReader object and a boolean flag as arguments. For
true value of the flag, user enters the data into the array from the keyboard,
whereas for false value from the input file. In either case the data input is stored in a
StringTokenizer object St (L9.15#41 & 71). Then the method creates int array of
size equal to the number of tokens in the object St (L9.15#57 & 73) and assigns the
local array reference arr to it.
The local array reference arr is initially set to point to the constant zero length
array ZERO_LEN_ARR (L9.15#29). For Java methods returning an array as a
value, it is important to return a zero length array rather than a null reference, for
cases where an empty array must be returned. Assume that a method in our case
study on Inventory report in chapter eight were to returns an array of number of
items in the inventory file. If for some reason the inventory is totally empty, the
method must return a zero length array rather than a null value, as processing a
zero length array would be easier for a client than processing a null value.
Therefore never initialize an array reference to a null value. Rather create a zero
length array as a way of initialization and reassign to a new length as needed.
The standard procedure for getting the tokens from the StringTokenizer object St,
parsing them is used to populate the elements of arr (L9.15#59-60 & 75-76). Finally
the method returns arr (L9.15#79). Figure 9.36 shows the typical results from the
Listing 9.15.
Listing 9.16 shows the complete program to find largest double value and other
methods to perform statistical calculations in a randomly generated array.
00001 import java.util.*;
00002 import java.lang.reflect.*;
00003 import java.text.*;
00004
00005 public class Statistics
00006 {
00007 protected static final double [] ZERO_LEN_ARR = new double[0];
00008 protected static final int MAX = 20;
00009 protected static DecimalFormat DF = new DecimalFormat("0.00");
00010
00011 private Statistics(){}
00012
00013 public static void main (String[] args)
00014 {
00015
00016 Random RN = new Random(System.currentTimeMillis());
00017 double [] dbl_arr = fillArray(RN);
00018 System.out.println("Printing only the filled portion of the array.");
00019 printArray(dbl_arr,MAX/2);
00020 printStatistics(dbl_arr, MAX/2);
00021
00022
In Listing 9.16 the algorithm for method findLowest is similar to ALG 9.3, except
for the fact that step four is altered as follows:
Our purpose in developing Listing 9.16 was to be able to process portion of an array
(called logical length) to find statistical parameters, such as lowest, highest, mean,
and standard deviation values. In fact the methods findLargest, findLowest,
findMean, and findStdDev are static methods that can be used by all clients of class
Statistics. The danger in using a partial array of course is that client class has to
ascertain that precondition of logical length (count) passed to processing methods is
neither negative, not larger than the physical length of the array. If the precondition
is violated then the method may try to access an out of bound array element,
will return a Double value of the primitive at the location index. We then build a
StringBuffer object containing values of all array members (L9.16#134-135 or 137-
138). We use StringBuffer instead of String as former is more efficient and its
mutability is not a problem in printArray method. In order to access the members
of the array through its Object reference arr, we use the static method get
(L9.16#134). The method printArray prints the StringBuffer object Val after
building it through the iteration over the logical array length (L9.16#135 or 138).
Since the main in Listing 9.16 uses an array of randomly generated double values
(using methods from class java.util.Random, the output for it would vary from one
run to another. However, the Figure 9.37 shows one of the typical output.
FIG. 9.37
The object RN of type Random is first created in main by passing to its constructor
a long value to seed the random number generation mechanism (L9.16#16). A
suitable seed value is obtained by calling the method currentTimeMillis ( ) from
System class, which returns the current time in computer clock as a long parameter.
Then the method rnd uses the method nextDouble to generate and return 50 times
of the random number generated by latter (L9.16#52).
Listing 9.17
At compile time the compiler is not able to check for the out of bound array indices.
Therefore it will let you store data in memory locations that is not with in the
bounds of array size. The program crashes upon running because it is trying to
write the data in a memory block that is not assigned to it, and JVM crashes it. In
fact situation will be very serious if JVM did not crash the program, in which case
the program can overwrite into memory blocks used by other programs, causing
some other program to crash. Similar problem may arise when you try to print out
of bound array elements. In Java the low bound is always zero. So accessing a
negative array index is meaningless. The upper bound is one less than the maximum
length of the array. Accessing array index beyond the upper bound is also
meaningless though Java compiler will not give an error if you did that. Easiest way
to avoid out of bound array index in Java is to always use zero value as a lower
bound and the value less than the length field of array, which is accessible by using
dot operator with the array name (arr.length is array name is arr). As illustrated in
Listing 9.16 that when logical length is passed to a method for array processing, the
code should always check to ascertain that it is smaller than the physical length.
We also cannot compare arrays for equality by doing an aggregate comparison. For
if(Arr1 == Arr2)
System.out.println(“They are equal”);
To see whether all elements of an array are exactly equal to all the elements of
another array, one may either do a member wise comparison or use the equals
method from class java.util.Arrays. Listing 9.18 shows both techniques. Figure 9.38
shows the output for Listing 9.18.
00001 import java.util.*;
00002 import java.lang.reflect.*;
00003
00004 public class CompareArrays
00005 {
00006 private CompareArrays(){}
00007 protected static DecimalFormat DF = new DecimalFormat("0.00");
00008 public static void main (String[] args)
00009 {
00010 int [] Arr1 = {1,2,3,4,5};
00011 System.out.println("\nPrinting Array1");
00012 printArray(Arr1, Arr1.length);
00013 int[] Arr2 = { 1,4,6,8,9,10};
00014 System.out.println("Printing Array2");
00015 printArray(Arr2, Arr2.length);
00016 int [] Arr3 = {1,2,3,4,5};
00017 System.out.println("Printing Array3");
00018 printArray(Arr3, Arr3.length);
00019 System.out.println("Testing equals method from Arrays class.");
00020 //use of equals method from class Arrays
00021 if(Arrays.equals(Arr1,Arr2))
System.out.println("Array1 and Array2 have same contents in same order.");
00023 else
00024 System.out.println("Array1 and Array2 are not equal");
00025
00026 if(Arrays.equals(Arr1,Arr3))
System.out.println("Array1 and Array3 have same contents in same order.");
00028 else
00029 System.out.println("Array1 and Array3 are not equal");
00030 //use of isEquals method developed below
00031 System.out.println("Testing isEqual method.");
84 if(count>len)
count = len;
99 System.out.println(Val.toString());
}
} //Listing 9.18
FIG. 9.38
In Listing 9.18, first we create three arrays Arr1, Arr2, and Arr3 (L9.18# 10,13 &
16), of which Arr1 and Arr3 are clones of each other, and Arr2 is different from
both. We print all there arrays (Figure 9.38 Lines 1 to 6). Program then uses the
equals method from Arrays class which uses the syntax similar to the line
(L9.18#21) to test for equality of two arrays passed to the method. If arrays are
identical in number, element values and element order then the equals method
returns true, else it returns false. Test results (Figure9.38) indicate inequality of
Question: How would one test, when two arrays have same
data, but the order in which data is there, may be different?
In order to see if the two arrays have same data but in different order, we would
first check for the lengths of two arrays for equality. If lengths were equal, then we
would need to sort the two arrays in ascending or descending order and then use
equal method of Arrays class to test for the equality. Fortunately the Arrays class
makes the task of sorting most arrays almost trivial. Table 9.7 shows the summary
of methods for the class java.util.Arrays.
Except for character array one cannot print an array by doing aggregate operation.
int [ ] Arr1 = new int[50];
System.out.println(Arr1); //Will only print address stored in Arr1
Java does however allow character array to be printed aggregately. For example, a
character array char_arr as shown below is allowed to be printed aggregately.
char [] char_arr= {'h','e','l','l','o'};
System.out.println (char_arr);
The above array char_arr will print hello on a DOS screen.
We are aware of the fact that all printable characters on keyboard have ASCII
values ranging from 32 to 126. What we can do is to create an integer array of 128
elements and as we read a character in the text, we increment the value stored in
that array cell number by one, whose index is equal to the ASCII value of character
just read. For example, we know that the ASCII value of character ‘A’ is 65. Then
each time we read the character ‘A’ in the data file, we increment the value stored
in the array cell with index 65 by one. A typical character frequency-counting array
may look like the figure 9.39 below (provided, the case is ignored).
FIG. 9.39
ALG 9.4 gives the short algorithm for such a program below.
ALG 9.4
Listing 9.19 gives a class DeEncrypt, whose methods implement the algorithm 9.4.
The Pentagon had hoped to retain control of the postwar effort, so the
decision is a victory for Secretary of State Colin L. Powell. It will
probably also help placate United Nations and European critics, who
have complained that Iraq should be governed by a civilian during this
interim period to lessen the appearance of a military occupation.
"The ambassador goes with the full blessing of this administration and
the full confidence of everyone in this administration," Mr. Bush said
in the Oval Office today, as Mr. Bremer sat between him and Defense
Secretary Donald H. Rumsfeld.
Mr. Bremer "is a person who knows how to get things done," the
president added.
"That is not a current and accurate chart," Mr. Powell snapped. "And it
will be even less accurate within the next few days."
But after several days passed and the White House still had said
nothing about Mr. Bremer, Mr. Rumsfeld issued an unusual statement of
support for Mr. Garner, saying he "is doing a truly outstanding job for
the nation; any suggestion to the contrary is flat untrue and
mischievous."
Mr. Rumsfeld also noted pointedly, "The White House has made no
announcements regarding other appointments."
That announcement finally came today. With Mr. Rumsfeld looking on,
smiling, the president hailed Mr. Bremer "as a can-do person."
Mr. Bremer served in the United States Foreign Service for 23 years and
is chairman and chief executive of the crisis-consulting practice at
Marsh Inc., a division of the Marsh & McLennan Companies. Before
joining the company in October 2000, he worked for Kissinger
Associates, the international consulting firm headed by former
Secretary of State Henry A. Kissinger. He has also served on the
president's Homeland Security Advisory Council.
"It was a very good meeting," the sheikh, Muzahem al-Tamimi, told
Agence France-Presse. "We are happy he came to see us. He asked my
opinion of the future of Iraq."
The United States also released more Iraqi prisoners of war, and
officials announced that all would soon be let go.
The military prisoners "will be gone within the next few days and
civilians within four or five days," said Maj. Stacy Garrity of the
800th Military Police Brigade at Camp Bucca, in southern Iraq, the main
detention facility. At its height, the camp held 7,000 prisoners, who
have been steadily released since hostilities began winding down, with
2,000 remaining.
Mr. Ashcroft and other law enforcement officials vowed to recover the
stolen artifacts and return them to Iraq.
10.2 Write the method findSmallest above such that it returns an array of integers
where the first value is the smallest value in the array and second value is the index
where the last occurrence of this lowest value takes place. The proto-type will then
become:
int [ ] findSmallest2(final int[ ] nums int length)
10.3 Modify the method findLargest in Listing 9.16 such that it returns an array of
integers of size three such that, the first integer is the largest value, second is the
index where (in ascending order) the first occurrence of largest value takes place,
and last value is the index where last occurrence of largest value takes place. The
header of the method is as follows:
int [ ] findlargest1(final int[ ] nums int length)
10.5 Write a method find ( ) which takes an integer array, its logical length, and an
integer key as arguments. The method returns a true if key is found in the array,
otherwise it returns a false. The header of find is as follows:
boolean find(final int [ ] nums, int length, int key)
10.6 Write a method findLargerThan which takes same parameters as the method
find in exercise 10.5, but returns the number of integers in the array nums that are
larger than the integer key. The header of findLargerThan is given below:
int findLargerThan (final int [ ] nums, int length, int key)
10.7 Write a method findSmallerThan which takes same parameters as the method
find in exercise 10.6, but returns the number of integers in the array nums that are
smaller than the integer key. The header of findSmallerThan is given below:
int findSmallerThan (final int [ ] nums, int length, int key)
Data1 = Integer.parseInt(C1.toString());
Data2 = Integer.parseInt(C2.toString());
System.out.println("After calling swap3 the value of \n" +
"Data1 = " + Data1 +"\n"+
"Data2 = " + Data2);
C1 = new StringBuffer("Mary");
C2 = new StringBuffer("John");
for(; pass_number<size;pass_number++)
{
Largest = (Comparable)Array.get(Arr,0);
index_largest = 0;
for(int index = 0; index<size-pass_number; index++)
if((Largest.compareTo(Array.get(Arr,index)))<0)
{
Access Modifiers
The access modifiers regulate the access of java classes, fields and methods. There
are four different access modifiers.
1. public
2. private (An outer java class cannot be declared private. But
inner classes can be declared private).
3. protected (An outer java class cannot be declared protected.
But inner classes can be declared protected).
4. No modifier is specified.
A minimal java class declaration may be done as follows:
//************************************************* Note the absence of
class MyClass package name! This
{ means that class is in an
unknown package and is
//---------------- not accessible outside it!
}//Listing 10.1
//**********************************************
Listing 10.2
//**********************************************
Why is above form useful? Because now the class MyClass2 being declared as public
becomes accessible to rest of the world by virtue of being part of a named package1.
All Sun Java Classes are defined in this manner (All public, all members of some
named package.)2
Modifiers private and protected are not used for the outer
classes, but they can be used for the inner or nested classes. We
will discuss additional modifiers for classes after we have discussed the topic of
inheritance.
1
The package naming requires that name must be unique. Sun uses the system of reverse domain
notation. For example the packages from Oracle Corporation may have names such as
com.oracle.packagename. Since the name com.oracle will be unique, all packages become unique,
with out any chance of naming conflict and confusion.
2
The details of compiling packages are given at the Web site below:
http://www.yoda.arachsys.com/java/compiling.html
We also must understand that static variables have only one copy for all the
instances of a class, whereas non-static variables will have number of
copies, equal to the number of instances for that class.
3
Methods and variables must be package-private(no access modifier used), public, or protected in
order to be accessed inside another class in the same package. Public methods and variables are
accessible everywhere.
FIG. 10.2
As shown in Figure 10.2, the public field in the class “a class” is visible inside all of
its subclasses as well as inside all the client4 classes.
Protected fields and methods are visible and accessible in the derived classes and in
the classes in the same package, but not in any other classes. We discuss the
protected fields in more detail after we discuss the inheritance. The Figure 10.3
below shows the visibility of protected fields in more detail.
4
Client classes are the one, which may make use of “a class” either as a local variable or as a class
level variable.
Private fields and methods are not visible outside the class they are declared. Private
fields can only be accessed, outside their native class by using a public method to
allow access to them. Figure 10.4 shows the visibility of private fields and methods in
more detail. The sub-classes inherit the private members of super
class, but have no access to them. To access the private but inherited
members, the super class must have a public method available, which can get the
access to the private fields.
a class
A rea of
Client 1 visibility.
C lients and
Subclass 2 subclasses,
Client 2 both m ust
Subclass 1 lie inside
the
package
FIG. 10.5
Inheritance
When we write a Java classes, we try to model a part of the reality of the world. For
example, when we write a complex number class, we model the behavior of complex
numbers in the class. However, in reality the things are related. By modeling the
related things together, we can see that how modeling one thing, can
help us model something related to it. Using Java’s mechanism of establishing
inheritance relationship between classes can model reality more effectively. Let us
take an example of vehicles in the world. Every vehicle has at least one property –
speed. We can write a class called vehicle, which has one data member called speed.
However, there are many kinds of vehicle in the world. For example, the vehicle
may be a wheeled vehicle, which will move on roads and surfaces or it may be an
airplane that will fly in air. Both vehicles such as airplane and vehicle with wheels
have a relationship with general concept vehicle. We can say that an airplane is-a
vehicle. We can also say that a vehicle with wheels is-a vehicle. When objects have
this “is-a” type relationship between each other, then an inheritance relationship
exists between them. Using this concept of “is-a” type relationship, we can set up an
inheritance hierarchy between vehicles of various types as follows (Figure 10.6).
FIG. 10.6
Now, at each level of above inheritance hierarchy, new properties are added to the
system of related objects. For example, we may ask the question, as to what is the
most common property to all vehicles? Obvious answer is that all vehicles have
speed. So now, we take this system of inheritance relationships and start filling it
with properties. This is dynamically presented below.
Microsoft PowerPoint
Presentation
We can see that all vehicles have a property speed, and all airplanes have a property
called “engine thrust”. We keep adding one or more new property at each level of
inheritance derivation in our system. The Figure 10.7 below shows the result.
FIG. 10.8
At each level of inheritance, the class, which is the source of inheritance, is called a
base class or a super class. Moreover, the class that results from inheritance is called
a derived class of subclass. The phrase subclass should not be taken to mean that
somehow the derived class is “lesser” in some way. In fact, if anything it has more
data members. In the present system that we have built here, the Vehicle class is the
base class or super class, where as the with respect to the vehicle class, the class
FIG. 10.9
FIG. 10.10
FIG. 10.11
Generally in java classes that are not expected to be extended, the data members are
declared private. One characteristic of private data members is that, they are visible
to the methods in the class, but invisible to rest of the world. Inheriting from a base
class with all data members declared private complicates the matter somewhat. Java
allows another form of access specifier for the data members of a class, which makes
them invisible to world outside the class and its package, but visible to derived
classes. This specifier is called “protected”. As shown in Figure 10.3, the protected
data members are visible in the derived classes and in the client classes in the same
package.
By making the field of class Vehicle, for example in this case, the speed protected,
has the affect of class Airplane having two fields, speed and numberOfwings.
Similarly, the class Jet has three fields, speed, numberOfwings, and enginethrust.
What we do now is that we add fields, constructors, and a method called describe ( )
to all classes in the Figure 10.7. This results in the code given in Listing 10.5 below.
In Listing 10.5, the method describe for each class has a single output statement
describing the type of vehicle the class represents. The process by which a derived
class provides a specialized version of a method with same name as in its super class
is termed as overriding the super class method. If Vehicle class has a method called
describe and none of its sub classes have a method named describe then all sub
classes would inherit the describe method from class Vehicle. However if any of the
sub class provides a method named describe with same header, then sub class is free
to implement it in any way it chooses. Overriding methods of class super class
java.lang.Object is an important topic in Java, which will be discussed shortly. We
now show the source code for various classes from the Figure 10.7.
public Vehicle()
{
this(0.0);
System.out.println ("From Vehicle CTOR #1");
}
public Airplane()
{
this(0);
System.out.println("From Airplane CTOR #1");
}
public Proplane()
{
this(0);
System.out.println("From Proplane CTOR #1");
}
public VehicleWithWheels()
{
this(0);
System.out.println("From VehicleWithWheels CTOR #1");
}
public Car( )
{
this(0.0);
System.out.println("From Car CTOR #1");
}
public Car( double init_speed)
{
this(init_speed, 0);
System.out.println("From Car CTOR #2");
}
public Car( double init_speed,int nWheels)
{
this(init_speed, nWheels, 0.0);
System.out.println("From Car CTOR #3");
}
Listing 10.6
We create an instance Temp of class AnyClass by calling the operator new and
calling the default java provided constructor. Then we call an instance method
hashCode( ), to print the hash code for the Temp. The resulting output is shown in
the Figure 10.13 below.
FIG. 10.13
The class AnyClass does not have a method called hashCode. Therefore, where did
the method hashCode come from? It actually came from the class Object, which is
the super-class for AnyClass. Moreover, the Object part of AnyClass instance Temp
is built, when during the constructor call new AnyClass( ), the Object class
5
If derived class constructor does not make an explicit call to the super class constructor, then Java
will automatically call the default super class constructor.
Veh1.describe( );
Veh1 now points to an
Veh1 = new Car ( 60, 4, 20); object of type Car.
Therefore, in order to build an instance of Jet class, the constructor calls are made
in the following sequence (Figure 10.15).
Jet part is
Jet Constructor call created Last!
The Figure 10.14 shows the output statements coded in the constructors of Vehicle,
Airplane, and Jet class, when the Jet class constructor in the Listing 10.17 is called.
These output statements are:
From Vehicle CTOR #2
From Airplane CTOR #3
From Jet CTOR #4
There is no output statement in the Object class constructor so we do not see a
similar statement from that. However, the sequence of other three-constructor call
is similar to the sequence shown in the Figure 10.15. General conclusion drawn is as
follows:
I'm a Jet.
I am propelled by a fast jet engine.
The mechanism where JVM will correctly bind an object to “its” method at run
time is called dynamic binding, late binding, or run time binding.
6
All the static or class method calls are resolved at the compile time.
7
We describe up-casting and down casting between references related by inheritance in the chapter
on Runtime Type Identification (RTTI).
One can see that all Jet class methods are called properly and they give proper
results by following the procedure described in the Listing 10.8.
Interfaces in Java
The fundamental unit of programming in java is a class, but in object oriented
programming, the fundamental design unit is a reference type. Interfaces are a way
to define reference types with out defining a class. This adds to Java’s power of
object-oriented programming. Interfaces define reference types in abstract form as
a collection of public method headers and static constants. Interface contains no
implementation of methods; therefore, we can say that an interface is an expression
of pure design. On the other hand, the classes are mixture of design and
implementation. Java classes can implement interfaces by using the keyword
implements. For example if I design an interface called ElCaminoCollegeInterface
and then get a class Student to implement it, then class Student would be written as
follows:
In above list the entities inside square brackets are optional. Inside an interface only
return type, method name and argument list are required. Abstract methods can be
specified with in classes also, in which case they would need the keyword abstract
attached in front. Most important thing is that abstract methods have no method
body.
The class implementing a java interface uses keyword implements to implement it.
(see below).
8
Abstract class cannot be instantiated, though it can be used as a reference type. We discuss abstract
classes shortly.
However, as soon as the method printHello in class MyClass is commented out, all
statements inside the main will give a compile error shown in the Figure 10.17.
DriverMyClass.java:7: cannot resolve symbol
symbol : method printHello ( )
location: class MyClass
MC2.printHello();
^
.\MyClass.java:1: MyClass is not abstract and does not override abstract method
printHello() in MyInterface
public class MyClass implements MyInterface
^
2 errors
FIG. 10.17 Comment [p7]: Listing 10.9
The main thrust of compile errors is error #2, where compiler indicates that class
MyClass is breaching the contract with interface MyInterface by not overriding or
implementing the method printHello. If one declares the class MyClass abstract
using the syntax:
will compile, however one still cannot instantiate the abstract class MyClass to
create instance MC2. Therefore classes not overriding or implementing the methods
from their implemented interface must be declared abstract explicitly by using
keyword abstract.
}
public interface SomeInterface extends Interface1, Interface2
{
}
Note that keyword “extends” is used when an interface extends another interface.
}//Listing 10.10B
As one knows that a door has two main processes – open the door or close the door.
Therefore the interface Door is given two abstract methods open and close, and in
this case, both are void method and take no arguments. Now, lots of objects in world
have doors. Homes have doors. Cars have doors. Trucks have doors. To the degree
that behaviors of all doors (in cars, homes, trucks) is same (they all open or close),
the classes for these objects can all implement interface Door. In this sense the
interfaces design behavior of objects! Of course all classes implementing Door
interface can implement their interface methods open and close in their own way.
For example the message printed by the close method of class HomeDoor may be
different from the one for class CarDoor as per its needs.
The diagram simply means that CarDoor is a subclass or derived class from
interface Door. If contract to implement methods open and close is kept then a
reference of type Door can hold the address of object of type CarDoor. Therefore
the first statement in the main method of class Test Door given below compiles fine.
Now the Instance1 (which is a Door type reference) can be used to call any of the
methods inherited from interface Door by the class CarDoor. Thus Intance1.open
would execute the code inside the open method in CarDoor class. Implementing an
interface, apart from forming a contractual relationship of implementing interface
methods, also provides an additional reference type for a class. The output of
Listing 10.10C is shown in Figure 10.19.
In C++ Person,
Person Student, Voter, and
StudentVoter can
all be classes!
Student Voter
StudentVoter
Voter
Student
StudentVoter
Codes for classes and interfaces in Figure 10.21 are shown in Listing
10.11. The UML diagram for Figure 10.21 is shown in the Figure 10.22
String getName( );
int getAge( );
}
Listing 10.11 Part A Comment [p13]: Figure 10.22
Interface Voter extends interface Person. That means that the methods in the
Person interface are also automatically inherited by the interface Person. We
however, include some static constant strings in the Voter interface to hard code the
possible party a student voter may be member of. We also include a method
getParty( ) in the Voter interface, which returns the party of the student voter as a
string. The coded Voter interface is shown in the Listing 10.11 Part B.
String getParty( );
}
Listing 10.11 Part B Comment [p14]: Figure 10.22
After coding the two interfaces, now we can code the necessary classes. First, we Comment [p15]: Figure 10.22
code the class Student, which derives from interface Person. Class Student has
name, age and gpa as fields, and we have shown all the necessary chained
constructors (Listing 10.11 Part C). Since Person interface is implemented by the
class Student, we provide the implementation of the methods getAge( ) and
getName( ). We also code some helper methods such as getGpa( ), and toString( ).
The method getGpa( ) is unique to class student, as only a person, who is a student
can have gpa. The toString ( ) method overrides the corresponding method in the
Object class. The code for the class Student is shown in the Listing 10.11 Part C.
public class Student implements Person
{
protected String Name;
protected int age;
protected double gpa;
//Chained constructors
public Student()
{
this("");
}
The class StudentVoter extends Student and implements interface Voter. Note that
since class Student already implemented the abstract methods from Person class,
the class StudentVoter need not do that, unless it wishes to provide a specialized
version of the interface methods by overriding them. The general rule that applies
here is that if any of the super-classes implement the methods of an interface, they
are already available to all sub-classes. However, the StudentVoter must implement
the abstract method getParty( ) from the Voter interface. The StudentVoter class
introduces two new fields, the date of last vote (lastvote) and Party of the
StudentVoter (Party). This is because the StudentVoter inherits all the fields from
the Student class, it in effect, has five fields and needs six chained constructors. It
has helper methods such as getLastVote and over-rides the toString method from
object class9. Listing 10.11 Part D shows the code for the class StudentVoter.
9
We discuss overriding the Object class methods in more detail later.
}
public StudentVoter(String Init_Name, int init_age, double init_gpa,
int init_lastvote, String Init_Party)
{
super(Init_Name, init_age,init_gpa);
this.lastvote = init_lastvote;
if(Init_Party.equals(StudentVoter.PARTY1))
this.Party = PARTY1;
else if(Init_Party.equals(StudentVoter.PARTY2))
this.Party = PARTY2;
else if(Init_Party.equals(StudentVoter.PARTY3))
this.Party = PARTY3;
else if(Init_Party.equals(StudentVoter.PARTY4))
this.Party = PARTY4;
else if(Init_Party.equals(StudentVoter.PARTY5))
this.Party = PARTY5;
else
{
System.out.println("Bad party name. Setting party to none.");
this.Party = PARTY5;
The class TestDiamond is written to test the diamond inheritance formed by the
interfaces and classes and is shown in Listing 10.11E. We create three objects, two
of type StudentVoter and one of type Student. The references used to point to them
are StudentVoter, Student and Person. In creation of all objects we call the
constructor with largest number of arguments for that class. The object STVoter1 is
of type StudentVoter. It can be printed directly by the System.out.println because
the method toString ( ) of StudentVoter class is overrides the object class toString
method to correctly print the StudentVoter objects. The methods getName, getAge,
getGpa, getParty are easily called using STVoter1 because STVoter1 is a
StudentVoter Type reference pointing to a StudentVoter type object.
We can see very clearly from the results that the polymorphic method selectionSort
works nicely as it takes an array of mixed Student and StudentVoter type objects
and sorts them in the alphabetical order by the name. Becoming able to write
polymorphic methods is another main advantage of inheritance in Java.
Abstract Class
1. The abstract class has at least one abstract method. An
abstract method is a method, which has no body or definition.
It just has a signature and return type.
2. The usefulness of abstract class lies in it being
extended by other classes or other classes being derived
from it.
3. An abstract class cannot be instantiated, though it can
be used as a reference type for the sub class objects.
Abstract_Shape_I
nher.ppt
A shape is a general abstract concept. We know that a shape can have area and in
some cases volume. A shape certainly has a name. However, shape is abstract
enough that we can define an abstract class called Shape to model it. We would
never need an instance of class Shape because there is no real object in the world
that is called “Shape”.
Now there can be many types of shapes. A point is a shape, which is infinitesimal in
size. However, it has properties such as coordinates x and y in the Cartesian system.
Therefore, the Class Point can extend the general concept of Shape to a concrete
form. Hence, we derive the class Point from Shape.
A Square has a center point just like a Point and a class Square can inherit the
coordinates x and y from class Point. Nevertheless, Square shape has additional
property like a length or edge. Therefore, we derive the class Square from Point.
Finally, a Cube has the same properties or fields as the Square does – like a central
point, and an edge, but has a volume, which square does not have. Yet, no new fields
are needed if we were to derive the class Cube from class Square.
Implemented
Methods
Abstract
Method
A class can also become abstract if it derives from an abstract class and
does not provide implementation for the abstract methods for its
parent. The keyword abstract would be then required in class
declaration.
public Point()
{ Default and
this(0);
explicit
}
constructors,
public Point(int a) all chained
{ together.
this(a,0);
}
public Point(int a, int b)
{
this.x = a;
this.y = b;
}
abstract method from
public String getName() the parent class Shape
{ implemented.
return "Point";
}
class Square
The source code for the class Square is given below in the Listing 10.14.
public class Square extends Point
{
protected double edge; New field edge is
added. It inherits x
public Square() and y.
{
this(0.0);
}
class Cube
The source code for the class Square is given below in the Listing 10.15. Does not
need any new fields.
public class Cube extends Square
{
public Cube()
{ Constructors
this(0.0);
}
public Cube(double edge1)
{
this(edge1,0,0);
}
The UML(Unified Modeling Language) diagram for all these classes is given on next
page (Figure 10.26).
The purpose of this program is to get from the user the properties of shapes and
then display properties, such as central coordinates of shape, and if relevant then
display its area and volume. The coordinates of the center of a Shape, be it a point,
square or cube would not change with its type. In Lines (L10.16#15-20), user input
for Shape’s center x, y coordinates are accepted and parsed. The user is prompted
to input the edge of the Shape or zero if the Shape is a point (L10.16#21-23).
Understand that all instantiable objects such as Point, Square and Cube are derived
from super class Shape. Therefore the reference type Shape can hold the address of
any of them. We declare a general Shape type reference Gen_Shape (L10.16#24). If
data for edge entered by the user were zero, then it is certain that the shape is a
point. In that case the first if block is executed (L10.16#24-31). Inside the if block the
final point object is constructed with user provided center coordinates x_coord and
y_coord (L10.16#27), and a super class reference Gen_Shape points to this derived
class Point object. An Output String is built to describe the properties of this Shape
object, first by getting its name, and central coordinates by calling member methods
getName and toString (L10.16#28). Then to add its area and volume to the overall
description, the methods area and volume are called (L10.16#29-30). Understand
that class Point does not actually have the coded area and volume methods, and it
automatically binds to its super class Shape’s implemented methods area and
volume for their execution. The JOptionPane outside the else block displays the
properties of the Shape (L10.16#52). Figure 10.27 shows the system of displays when
the user constructs a Point shape.
User is given, through the display, all the correct properties of Point type object
constructed by them (Figure 10.27). Notice that even though point object created on
Line (L10.16#27) was represented by a Shape type reference (Gen_Shape), due to
the property of dynamic binding, Java correctly recognizes the object to be of Point
type and only calls the methods from Point class to build the property String
Output.
If edge value selected is not zero then user may wish to construct either a square or
a cube (both these shapes having an edge). In that case the else block in Listing
10.16 (L10.16#32-50) is executed. And if after entering the center coordinates of 10,
Here also though reference of type Shape (Gen_Shape) holds the address of Cube
object created at line (L10.16#45), Java does the correct dynamic binding by calling
the appropriate methods for area and volume for the Shape object Cube. We shall
soon discuss advantages of extending other Java abstract classes called adapter
classes, which implement some methods for a Java interface but leave one of more
methods unimplemented. Adapter classes simplifies coding in creating some
graphical user interface programs.
Local classes like Listing 10.17 can be defined inside any method, constructor or
initialization block10. Local classes can access, with in scope, locally defined constant
reference types11 or class level static variables directly. The instance fields of locally
defined final class variables can also be accessed. The method in which local class is
declared can return their instance as a method return value or pass their instance as
a parameter to another method.
10
An initialization block is located at the class level as a stand-alone block (bounded with curly
braces). The initialization blocks may be marked as static or may be unmarked. Code in all static
blocks is executed “once” when program is run first time. Non-static or unmarked blocks are
executed each time a class constructor call is made.
11
Local constant reference types can be declared as follows:
final AnyClass Var1 = new AnyClass( );
Note that in this case the reference Var1 is constant, which means that Var1 cannot be used to point
to another object of type AnyClass later in the program sequence. This does not however make the
object to which Var1 is pointing to immutable (or unchangeable). The java objects are immutable
only if their class is defined as final and they have no methods available to change their state after
construction.
The listeners are added to graphical or GUI components by invoking one of their
method which has a name similar to:
Object of a class that would have
event handling method is passed
as an argument.
addSomeListener ( ).
In addition, a method that adds a listener will take as its argument an object, which
can invoke an event handling method or event handler. The process of adding a
listener is called “registering” a GUI component with the event listener. The object
passed as an argument to addSomeListener method, is a java class that has the
event handling method in it.
Listing 10.18 A &B show one of the technique to create a simple awt and swing
windows.
1. Create object of
import java.awt.*;
Frame class.
public class TryWindow1
{
static Frame aWindow = new Frame("My awt Window!! Do Not Touch.");
3. Make the
Frame
aWindow.setVisible (true);
visible.
}
}//Listing 10.18A Comment [p32]: Figure 10.29
The program imports the java.awt package and creates a static data member of type
Frame called aWindow, which is initialized by calling the Frame class constructor
that takes a String as an argument. We shall see soon that the String in the Frame
class constructor argument shows up as the header of the Window Frame created.
The Frame class inherits the method setBounds called in the main from one of its
super class called Component. The Figure 10.30 shows the overall inheritance
hierarchy for the Frame class.
Frame class would inherit all public and protected methods from all of its four
super classes. The method setBounds (inherited from Component class) has the
following header and details (Figure 10.31).
public void setBounds(int x, int y, int width,
int height)
Moves and resizes this component. The new location of the top-
left corner is specified by x and y, and the new size is specified by
width and height.
Parameters:
x - the new x-coordinate of this component
y - the new y-coordinate of this component
width - the new width of this component
height - the new height of this component
FIG. 10.31 Comment [p34]: Listing 10,18A
In calling method setBounds the first two arguments provide the x, and y
coordinates of top left corner of the Frame, and other two, its width and height. The
method setVisible also inherited from Component class can make the Frame visible
or invisible (Figure 10.32).
public void setVisible(boolean b)
Shows or hides this component depending on the value of
parameter b.
Parameters:
b - if true, shows this component; otherwise, hides this
component
FIG. 10.32 Comment [p35]: Listing 10.18A
Since we wish the Frame aWindow to show up, we pass the argument true when
calling method setVisible. The execution of main in Listing 10.18A gives a GUI
shown in Figure 10.33.
Height = 150
Width = 400
The Frame object having the title passed to it as a String in the constructor call
shows up with its top left corner placed at the location x = 50 pixels and y = 100
pixels, with 450 pixel width and 150 pixel height. It is important to understand at
this point that in Windows and other GUI programming the top left corner of the
display is considered as origin (0,0). The y-axis is positive downward on left edge of
the monitor and x axis is positive from left to right emanating from top left corner of
the monitor. Unfortunate thing with this Frame window is that it would not even
close by clicking on X on its top right corner and user would need to use Control +
Alt + Delete in order to shut it down.
The JFrame window from swing package is closeable by clicking on X on top right
corner and is better behaved. Listing 10.18B shows the code for creating a JFrame
window and Figure 10.34 shows its look and feel.
import javax.swing.*;
It is should not be surprising to see that methods setBounds and setVisible apply to
JFrame equally well as JFrame actually derives from Frame class (Figure 10.35).
java.lang.Object
java.awt.Component
java.awt.Container
java.awt.Window
java.awt.Frame
javax.swing.JFrame
FIG. 10.35 Comment [p39]: Listing 10.18B
We mentioned that Window created by Frame class in Figure 10.33 is not closeable.
This has to do with the fact that Frame window has not been given “intelligence” to
close when user hits on X button on top right corner. How is this intelligence
imparted to a window? Few pages ago we mentioned that when user clicks mouse or
presses a key, the operating system fires an object called window event and send
that to the program. For program to do anything about it a listener must be present
to listen for messages from operating system. In Listing 10.18A, there is no such
listener present. Listeners are Java Interfaces, which contain some predefined
method headers. The interface that must be implemented for closing the window in
Listing 10.18A (thus close the window by clicking on x button) is called a
WindowListener in java.awt.event package. Table 10.1 gives the methods included
in the interface WindowListener. Any class implementing WindowListener
All methods in Table 10.1 can also be called event handlers. For example when
user would click the top right X button to close window (when properly added), the
method windowClosing would be activated and code inside it would be executed
to close the window. So our task of writing a closeable awt window program breaks
down as follows:
1. Write a class that implements WindowListener Interface and in that provide
bodies for all seven methods inherited from the interface.
2. Register the Frame object, which created the Window with this class (or
listener).
Best way to perform task #1 is do declare an inner class which would implement a
WindowListener interface. There are ways around it, that can avoid using inner
classes, but such avoidance in the long run reduces one’s learning of GUI
programming, and is not worth even to begin with. Therefore we first digress and
discuss inner classes in Java.
Inner Classes:
Java allows one to define classes as members of classes. Some time such classes are
also called nested classes. However, the Java Specification document points out a
subtle difference between the inner classes and nested classes. First, let us discuss
However, a nested class can be declared static. For example, the declaration like
below is OK.
}
Needed because NestedClass is
public class InnerClass enclosed and needs to be qualified by
{ its outer class. Since Nested class is
static, just the class name is enough
}
}
for qualification!
The qualified constructor name is simply the outer class name dotted with the static
class name. One can see that a static inner class can be instantiated with out the
need to instantiate its outer class first! This is not true for instantiation of a non-
static inner class. The latter requires, that for its instantiation, an object of its outer
class be present first. Therefore in Listing 10.19, first we create an instance of Outer
class called Temp_Outer. The left hand side of expression for instantiating the non-
static InnerClass remains similar to the one for static NestedClass. However, its
constructor call must be associated and qualified with the object of Outer class as its
instance cannot exist independently. Therefore in Listing 10.19 we use the following
syntax to create an object of InnerClass (Figure 10.36):
The dot operation between instance of Outer class Temp_Outer and new operator
may shock some of you. However one must understand that no property of
(including instantiation) an inner non-static class can be independent of an instance
of outer class as it is not different compared to an instance variable. Therefore you
may consider that an “unqualified” name for the constructor of non-static class
inner class, outside its enclosing class does not exist. In fact the object Temp_Outer,
after the line in Figure 10.36 is executed would schematically look like the one given
in Figure 10.37.
Comment [p43]: Listing 10.19, Table 10.1
Object Object
Temp_Outer Inst_Inner
FIG. 10.37
aWindow.setBounds (50,100,400,150);
aWindow.setVisible (true);
}
}//Listing 10.20A Comment [p44]: Figure 10.37, Table 10.1
Comment [p45]: Figure 10.37, Table 10.1
One lengthy process in Listing 10.20A is to implement the seven methods inherited
from WindowListener interface. The truth is that the only event handler needed to
System.exit(0);
}
}
}
}
//Listing 10.20B Comment [p46]: Figure 10.37, Table 10.1
The Window created by Listing 10.20B looks similar to the one created in Figure
10.33, except for the fact that now it is closeable. The method dispose that is called
inside the event handler windowClosing, is inherited by the Frame class, from its
super class java.awt.Window, which has the following description (Fig. 10.38).
public void dispose( )
Releases all of the native screen resources used by this Window, its subcomponents,
and all of its owned children. That is, the resources for these Components will be
destroyed, any memory they consume will be returned to the OS, and they will be
marked as undisplayable.
The Window and its subcomponents can be made displayable again by rebuilding
the native resources with a subsequent call to pack or show. The states of the
recreated Window and its subcomponents will be identical to the states of these
objects at the point where the Window was disposed (not accounting for additional
modifications between those actions).
FIG. 10.38 Comment [p47]: Listing 10.20B, Table 10.1
Following sequence of events takes place when the user clicks on X button on top
right corner of the window created by Listing 10.20B.
new AnyClass( );
In a form such as shown by the above statement, they can only show an output from
the constructor being called (if any). Anonymous classes are more useful when they
are instantiated and used to return them as values from methods, or provide some
other “one time” functionality. The rules as to which local and class level
parameters anonymous classes can access are same as for the local classes discussed
earlier.
Although one of the better practices for adding listeners for Java graphical
components is shown in Listing 10.20B, where nested class is used, at times the use
of local class or an anonymous class can also achieve the same purpose. In Listings
10.21A the programs simply show up a Java graphical window with a label (an
instance of class java.awt.Label) in it, which can be closed by clicking on the close
icon on top right side and free the system resources.
Anonymous class
Though use of nested class is most versatile, however, if only one window is to be
created in the entire program, then we can use an anonymous class, which can
extend the Java class WindowAdapter (or any other adapter or listener class) for
one time use only. The Listing 10.21B shows the code for such anonymous class and
its use. The results of Listings 10.21A and 10.21B are identical.
Temp.addWindowListener (
new WindowAdapter( )
2. Pair of braces
{
after the
public void windowClosing (WindowEvent Evt)
constructor call
{
defines the body
Temp.dispose ( );
of anonymous
System.exit(0); 3. The
class
} unimplemented
} and other methods
); are now coded
} inside the pair of
4. The right parenthesis for the braces { }, which
}
method addWindowListener define the
Listing 10.21B seems out of place and awkward anonymous class.
but is syntactically correct!
new WindowAdapter( )
{
public void windowClosing (WindowEvent Evt)
{
Temp.dispose ( );
System.exit (0);
}
}
Temp.addWindowListener (
new WindowAdapter( )
{
public void windowClosing (WindowEvent Evt)
{
Temp.dispose ( );
System.exit (0);
}
});
Important thing to remember here is that the last right parenthesis, just before
semicolon is the right member of pair of parentheses for the argument list for the
method addWindowListener.
}
}
static
{ Class defined within a stand-alone
class Class2 static block.
{
}
}
public LocalClasses( )
{
class Class3
{ Class defined within a constructor.
}
public static void main(String[ ] args)
{
class Class4 Class defined within a static method. Same
{ way the classes can be defined within non-
static methods as well.
}
}
} Listing 10.22
12
Local definition means defining with in a stand-alone block, constructor, or a method.
}
}
Listing 10.23
The nested interface (in this case NestedInterface1) may use the modifiers public,
protected, private and static as needed. Static and public nested interface acts like a
stand-alone interface, but the enclosing class defines its name and accessibility. A
class cannot implement the interface it encloses within itself. However, other classes
can implement an interface nested inside another class. For example, a code similar
to the Listing 10.24 is allowed.
Listing 10.24
Also, note that the Class1 could implement the nested interface NestedInterface1
because it was not defined private. Privately defined nested interfaces can only be
implemented with in their member class. For example, a code similar to Listing
10.25 is allowed.
Listing 10.25
Interfaces can nest other interfaces and classes as well. The members of nested
interfaces are also all public. A class that implements an enclosing (or outer
interface is only responsible for implementing the methods in the enclosing
interface. For example, in Listing 10.26, the class MyClass only needs to implement
method1. It is not responsible to implement method2 or method3. On the other hand
the class TheirClass, which extends the abstract class and implements both, the
nested and outer interface, must implement all method1, method2, and method3.
interface NestedInterface2
{
void method2( );
We know that all Java classes implicitly extend the Java class on the top of
inheritance hierarchy java.lang.Object. The Object class has the following protected
and public methods that are automatically are inherited by all Java classes (Table
10.2).
Summary of Methods for Object class
protected clone()
Object Creates and returns a copy of this object.
boolean equals(Object obj)
Indicates whether some other object is "equal to"
this one.
protected finalize()
void Called by the garbage collector on an object when
garbage collection determines that there are no more
references to the object.
final Class getClass()
Returns the runtime class of an object.
int hashCode()
Returns a hash code value for the object.
final void notify()
Wakes up a single thread that is waiting on this object's
monitor.
final void notifyAll()
Wakes up all threads that are waiting on this object's monitor.
String toString()
Returns a string representation of the object.
final void wait()
Causes current thread to wait until another thread invokes the
notify() method or the notifyAll() method for this object.
final void wait(long timeout)
Causes current thread to wait until either another thread
invokes the notify() method or the notifyAll() method for this
object, or a specified amount of time has elapsed.
toString Method
When invoked, the default implementation of the object class method toString
would print out the class name and hexadecimal representation of the hash code of
the object invoking toString appended to a @ sign. For example for Listing 10.27, if
we write a main method in a test class and execute the code such as below:
Two things are clear from the above code snippet. One is that overloaded println
method would automatically invoke the toString method for an object passed to it as
argument! Since Child class in Listing 10.27 does not override the Object class
toString method, the above code snippet simply prints the class name followed by
the hash code for the Object My_Child as 7ced01. It is always desirable for
debugging as well as for some default output purposes that the toString method
provides some useful information about the class. For example in our Customer
class from Listing 4.7, which has a print method, we can also override the toString
method to provide alternate printing functionality for a Customer type object. We
basically add the following toString method to the Customer class in Listing 4.7
(Listing 10.28).
Hash tables could have two types of data members. If objects are immutable, then it
does not matter as to how many identical copies of an immutable object exist (in the
program memory) – only one of them must be added to the hash table. This is
because the object will never change; therefore its retrieval from hash table must
depend upon its state soon after its constructor constructs it. On the other hand if
object of a class is mutable then it must be added to hash table based only on its
memory address or a hash value related to its memory address. This is because the
mutable objects can change after adding to hash table, thus only sure way to
retrieve such an object from the hash table is to search it based on its memory
address.
Java Object class method equals only compares memory addresses and returns true
when two references being compared point to same memory location. For example
the boolean value of variable are_same in code snippet in the main below would be
true.
class MyClass
{
private int data;
public setData(int val)
{
data = val;
}
public int getData( )
{
return Data;
}
}
public class TestMyClass Since MyClass does not
override equals method,
{ the Object class Equals
public static void main(String [] args) method is called.
{
MyClass Temp1 = new MyClass ( );
MyClass Temp2 = Temp1;
boolean are_same = Temp1.equals (Temp2);
}
}
it invokes the Object class equals method, which simply compares the memory
addresses stored in the references Temp1, and Temp2, which in this case happen to
be the same value.
The class MyClass is not immutable, as it does not satisfy the following properties –
all of which are required of an immutable class:
1. The class must be declared final, so another class never extend it.
2. It shall have no methods that can alter the value of its data members after
the constructor has constructed its instance. In other words the immutable
class has no mutators.
3. If a member method returns an Object of the class, then it shall always
return a new Object, not the one that was passed to the member method,
modified by the member method and returned after modification.
Since class MyClass is mutable, there is no point to override the default hashCode
method for it as that returns the memory address where the object is located on the
heap. That hash code is good enough to use, in order to place the object in the hash
table. Therefore the general rule for deciding whether to override both equals and
hashCode methods is that if the class is immutable then they both must be
overridden, otherwise neither of them must be overridden. Java library follows this
rule rather well. For example String in Java is immutable, therefore String class
overrides both equals and hashCode methods. This ascertains that String objects
that evaluate equal in contents, their hashCode methods return the same value. On
the other hand StringBuffer is mutable, and even if contents of two StringBuffer
objects were same, they would still give different hash Code values (Listing 10.29).
00001 public class TestEquals
00002 {
00003 public static void main(String[] args)
00004 {
00005 String Str1 = new String("John");
00006 String Str2 = new String("John");
00007
00008 if(Str1 == Str2)
00009 System.out.println("String " + Str1 +" and String " +
00010 Str2+ " are located at the same memory location.");
00011 else
00012 System.out.println("String " + Str1 +" and String " +
00013 Str2+ " are located at different memory locations.");
00014
00015 if(Str1.equals(Str2))
00016 System.out.println("String " + Str1 +" and String " +
13
Understand that if one assigned values to Str1 and Str2 as follows, then both Str1 and Str2 would
point to same memory location.
String Str1 = “John”;
String Str2 = “John”;
This is because compiler is allowed to place all literal strings at one memory location and make all
direct assigned String references with same content to point to same memory location. In this case
both == operator and equals method would yield the same result.
Then Str1 and Str2 are compared using the equals method (which is overridden in
the String class) (L10.20#15-20). The equals method of String class is called, which
is coded to compare the contents of Str1 and Str2. The result is expected. The call
Str1.equals (Str2) returns true, and the output (F10.42#2) prints that Str1 and Str2
are identical in contents. Finally the hash codes printed for both Str1 and Str2 are
identical as well (F10.42#3-4).
Situation may turn out different for the StringBuffer objects whose class does not
override Object class equals and hashCode methods. We create two StringBuffer
objects SB1 and SB2, both containing string “Mary” (L10.20#25-26). Then we check
the addresses stored in SB1 and SB2 using the == operator (L10.20#28-33). This
result is identical to the one for Strings Str1 &Str2. Use of operator new always
creates the objects at new memory locations on heap. Thus output line (F10.42#5-6)
prints that SB1 and SB2, both containing StringBuffers “Mary” are located at
different memory addresses. The major difference compared to the String example
comes when we use the equals method to compare the objects SB1 and SB2
(L10.20#35-42). While using equals with Str1 and Str2 returned true, the expression
SB1.equals (SB2), evaluates to false, resulting in output (F10.42#7-8), which is same
as the result using == operator. Finally we see that the values returned by method
hashCode are different for SB1 and SB2 (F10.42#9-10), even though both have same
contents (“Mary”). This is because the StringBuffer class also does not override the
method hashCode, thus it calls the Object class hashCode, which only returns the
memory address of the object. Conclusions:
1. The equals method of Object class only compares memory addresses of
objects and not their contents.
It is required that properly overridden equals method has the following five
properties:
1. It is reflexive – meaning that for a reference x, x.equals (x) must
return true.
2. It is symmetric – meaning that for any reference values x and y,
y.equals (x) must return true only if x.equals (y) also returns true.
3. It is transitive – meaning that for reference values x, y, and z; if
x.equals(y) returns true and y.equals(z) returns true,
then x.equals (z) must return true.
4. It is consistent – meaning that for any values of x and y multiple
invocations of x.equals (y) must return true or false, provided that
objects x and y are not modified between the calls to the method
equals.
5. For a null reference value, the x.equals (null) must return false.
Now we show an example of Fraction class (Listing 10.30) that is immutable and has
two data members (both long data types) representing numerator and denominator
of a fraction. We also show codes to override both equals and hashCode methods for
class Fraction.
14
A prime number is the one, which is not factorable into other numbers. First few prime numbers
are 2, 3, 7, 11, 13, 17, 19 etc.
15
PrimitiveData could be int, float, short, char or any other Java primitive type.
In overriding hashCode method, first we wrap two int data members in Integer
Objects and then get their String representation, which in turn gets their own hash
codes by calling String class hashCode method. Each component is multiplied by a
different prime number (P1, and P2). The numbers thus obtained are summed and
the sum returned as a hash code. Figure 10.43 gives the results of only testing equals
and hashCode methods as per the driver program in Listing 10.31.
00001 public class DriverFraction
00002 {
00006 public static void main(String[] argv)
00007 {
00008 //main2()
00009 testEqualsAndHashCode();
00010
00011 }
00012 public static void testEqualsAndHashCode()
00013 {
00014 final Fraction F1 = new Fraction(-1,2);
00015 //Test for reflexivity
00016 System.out.println("Testing for reflexivity.");
00017 System.out.println("Fraction F1 = " + F1);
00018 System.out.println("F1.equals(F1) evaluates to " + F1.equals(F1));
00019 //Test for symmetry
00020 System.out.println("Testing for symmetry.");
00021 final Fraction F2 = new Fraction(200, -400);
00022 System.out.println("Fraction F2 = " + F2);
00023 System.out.println("F1.equals(F2) evaluates to " + F1.equals(F2));
00024 System.out.println("F2.equals(F1) evaluates to " + F2.equals(F1));
00025 //Test for transitivity
00026 System.out.println("Testing for transitivity.");
00027 final Fraction F3 = new Fraction(-800, 1600);
00028 System.out.println("Fraction F3 = " + F3);
00029 System.out.println("F1.equals(F2) evaluates to " + F1.equals(F2));
00030 System.out.println("F2.equals(F3) evaluates to " + F2.equals(F3));
00031 System.out.println("F1.equals(F3) evaluates to " + F1.equals(F3));
00032 System.out.println("Hash code for F1 = " + F1.hashCode());
00033 System.out.println("Hash code for F2 = " + F2.hashCode());
00034 System.out.println("Hash code for F3 = " + F3.hashCode());
00035 final Fraction F4 = new Fraction(-800, 1559);
Method finalize
Although Java permits Object class method finalize to be overridden, it should
almost never be overridden.
Questions
1. What would be printed by the following code? Explain your answer.
class A
{
int i = 1;
For True False questions decide whether they are true or false, and also explain
the reason for your answers.
4. (T/F) A class can be declared abstract and final at the same time.
5. (T/F) A method cannot be declared abstract and final at the same time.
6. (T/F) A method cannot be declared abstract and static at the same time.
7. (T/F) Outer class can be declared static.
8. (T/F) An outer class and a stand-alone interface can be declared private.
9. (T/F) An outer class and stand-alone interface cannot be declared protected.
10. (T/F) A method can be declared private and abstract at the same time.
11. (T/F) A method cannot be declared protected and abstract at the same time.
34. The confused programmer says that since he/she can make the following
constructor call:
In your own words explain to the confused programmer that why the above call
is illegal.
35. A class declared with no modifier (for example with no keyword public in
front of class declaration) can:
[A] Be extended in its own package.
[B] Can be extended from inside any other package as long as it is imported
properly.
[C] All of above.
[D] None of above.
Instance of class
CloseableWindow2 is
now needed because
with out it the inner
class WindowClsoing
cannot be
instantiated.
Instance.new
is required to
call the
constructor for
inner class
Listing 10.17
Note that when an inner class is non-static then an instance of outer class will be
needed, before an instance of inner class can be created. Also, note the syntax of the
constructor call for the inner class:
Even more code would be needed if the Frame type class variable My_Window is
made non-static in the Listing 10.17. Affect of this are shown in the Listing 10.18
below.
import java.awt.*;
import java.awt.event.*;
public class CloseableWindow3
{
private Frame My_Window ; A constructor to instantiate the object
Frame is now needed. Otherwise the inner
public CloseableWindow3( ) class WindowClosing will not know as to
{ which My_Window to dispose.
this.My_Window = new Frame();
}
CloseableWindow3.WindowClosing Object_WindowClosing =
Instance.new WindowClosing();
Instance.My_Window.addWindowListener(Object_WindowClosing);
It is important to note that Listings 10.16, 10.17and 10.18 all accomplish almost
the same results. What is then the advantage of the Listing 10.18, where neither the
object Frame (My_Window), nor the inner class (WindowClosing) is static? Well
now, we can have more than one window in our program if we wanted to. This is
shown in Listing 10.19 for WindowClsoing4, where we create two windows one
with background blue and other with yellow background.
import java.awt.*;
import java.awt.event.*;
public class CloseableWindow4
{
private Frame My_Window ;
public CloseableWindow4()
{
this.My_Window = new Frame();
}
private class WindowClosing extends WindowAdapter
public void windowClosing(WindowEvent event)
{
CloseableWindow4 Temp = new CloseableWindow4();
Temp.My_Window.dispose();
System.exit(0);
}
}
public static void main(String [] args)
{
CloseableWindow4 Instance = new CloseableWindow4();
Instance.My_Window.setBounds(10,10,600,600);
Instance.My_Window.setBackground(Color.blue);
Instance.My_Window.setVisible(true);
CloseableWindow4.WindowClosing Object_WindowClosing =
Instance.new WindowClosing();
Instance.My_Window.addWindowListener(Object_WindowClosing);
display1();
} Method display has the
same code as the main
public static void display1( ) method, except the
{ window is smaller and
CloseableWindow4 Instance = new CloseableWindow4(); yellow in color and its
Instance.My_Window.setBounds(100,100,100,100); origin is located
Instance.My_Window.setBackground(Color.yellow); differently.
Instance.My_Window.setVisible(true);
CloseableWindow4.WindowClosing Object_WindowClosing =
Instance.new WindowClosing(); Listing 10.19
Chapter to be written ☺
CS 3: Java
Chapter 12: Exception Handling in Java
Author: Satish Singhal Ph. D.
Version 1.02
Mathematics defines two types of functions, total functions and partial functions. In
total functions the value of the function is defined for all values of the variables or
arguments provided to the function. In case of partial functions, there are domains
of variable values, where the function behavior becomes indeterminate.
Similar to mathematical concept of total and partial functions, Java has methods,
which can be categorized as total methods and partial methods. The total methods
are such that there is no restriction on the variables passed to the method at run
time, as method would handle all errors related to the data passed to it. This is akin
to a total mathematical function being defined for all values of the variables. A
partial Java method on the other hand “requires” user to refrain from passing
certain variable values as arguments, as the method is not designed to handle such
values. If a forbidden value were passed to a partial Java method then error
condition would result. A simple example of a partial method is a method called
divide (Listing 12.1), which takes two integers num and den as arguments and
returns the result num/den. The pre-condition to be followed in using this method is
that user never passes a zero value for den to the method1.
public class DivideProblem1
{
/*
• pre-condition: The value of den passed to the method shall never be zero.
• Returns the integer result after dividing argument num by argument den.
*/
public static int divide (int num, int den)
{
return num/den;
}
}//Listing 12.1
The method divide in Listing 12.1 has undefined result for den equal to zero and
would require error handling when user violates the pre-condition. Traditional
language like C could pass an extra argument, a pointer to a partial method like
divide to carry the results of the division of num and den. The method could return
a zero if pre-condition is violated. In that case the method would not alter the value
of the pointee of the pointer passed to it. If denominator is non-zero then the method
1
It just so happens that Java would crash the program if a zero value for den were passed.
num = 25;
den = 5;
if(!divide(num,den,result))
printf("The illegal denominator of value = %d has been passed to the method divide",den);
else
printf("\nThe division %d//%d = %d\n",num,den,*result);
}//Listing 12.2
Figure 12.1 shows the results of Listing 12.2.
FIG. 12.1
Due to security considerations, Java does not allow pointers to primitives, and for
the same reason all wrappers to primitives are also immutable. Therefore technique
used in C programming for error handling (where an error code is returned) cannot
be used in Java without elaborate measure, such as designing a method header as
given below.
In a divide method like above, if den is not zero, then method would return a true,
and the value num/den would be appended to (an initially empty) StringBuffer
object result. Using the algorithm similar to the one shown in main method in
Listing 12.2, the caller method can correctly parse the result of the division.
The use of C like technology for error handling is tedious, as it requires the client to
write extra code for error checking. Therefore inventor of Java and other Object
Oriented Languages designed a technology, which allows the methods to return an
error condition to the caller method without using the traditional error code return
mechanism. This technology is called exception handling/error handling. Side bar
12.1 provides few examples of error or exception conditions.
Sidebar 12.1
• In an integer arithmetical division, user provides a zero value
for the denominator.
• In a file input, the wrong file name or non-existent disk drive is
provided.
• When program expects input of a numeric, a string composed
entirely of alphabets is entered.
• When entering a person’s name in the customer database, only
digits are entered.
• Disk drive has a physical crash during the data read/write
process.
• Programmer makes a method call using an object reference,
which is a null pointer.
• The program tries to access an out of bounds array index.
On the other hand exceptions are conditions that are to some degree controllable,
and in some cases correctable by adding an exception handling code in the classes
and/or in the client program. In this chapter we elucidate exception handling by
examples and discuss error handling. Diagram in Figure 12.2 shows Java’s top-level
design of classes for error/exception handling.
FIG. 12.2
At the top of hierarchy (derived from class java.lang.Object) is the class Throwable,
which also implements the interface serializable. Figure 12.2 shows all the
methods/constructors provided and overridden in the class Throwable. The two
subclasses that extend Throwable are java.lang.Error and java.lang.Exception.
By now you already have some experience with messages that appear during your
program execution as a result of Java virtual machine informing you, of error
Listing 12.3
The above program will give expected results if user enters a non-zero denominator.
However, Java crashes the program when a zero denominator is entered and all the
code from the point of division by zero and on is skipped. The message on the
standard output is shown below in Figure 12.3.
FIG. 12.3
Java virtual machine crashes the program and points to the line number where it
found the division by zero error. It tells us that a division by zero was attempted at
the line number 15 in the file SomeExceptions.java in the method main. (Java refers
to methods as threads).
Sidebar 12.2
• Some exception and error handling is in-built in
java. All user has to do is to learn to use it.
• Java accomplishes the error checking and exception
handling by instantiating an object of a Java class,
which closely relates to the error (or exception) and
then throwing that object at the error location.
We shall see shortly, what the mechanism of “throwing” an object encompasses. But
before we learn to throw objects to recover from errors, we would like to learn, as
how to handle thrown exceptions. This is done by putting the error causing code
inside a block after the keyword try (referred to as a try block), and then catching
any exceptions thrown by that code in a block called catch. The syntax of try – catch
blocks is shown as follows (Figure 12.4).
try
{
//One or more program statements that may throw an exception
} Ex should be of type
catch(Exception Ex) Exception or its sub type.
{
//Zero or more statements that execute after thrown object is caught
}
FIG. 12.4
If an exception condition takes place inside the try block, then an exception object is
returned, and control of program is immediately transferred to the first statement
in the catch block and all the statements inside try block, after the exception
throwing statement are skipped. The catch block is also called an “exception
2
C++ has a limited implementation of automatic exception handling.
3
When the code inside the try block throws a “un-checked exception”, the try clause, if needed, may
be followed by a finally clause (missing a catch block). Missing a catch block immediately after a try
block is, however, a non-standard practice. We shall discuss finally clause shortly.
Sidebar 12.3
1. Existence of a lone try or catch block is a compile error.
There shall be no other code between the try catch blocks
(works similar to if/else structure).
2. One or more catch blocks may follow a try block. Java will
match the type of object (Exception) thrown in the try block
with the objects in the arguments of various catch blocks,
and wherever it finds the first best match, it will execute the
code in that catch block.
3. In the try block, once the exception is thrown, the code after
that point is skipped and java proceeds to execute the first
matching catch block.
4. The object thrown by the code in try block must be of type
java.lang.Exception. (Throwing the objects of classes Throwable and of
type Error is syntactically correct, but there is no added value in doing so).
FIG. 12.6
All classes that are of type RuntimeException or Error form the un-checked
exception classes, whereas the remaining classes form the checked exception types.
Listing 12.5 shows as how both checked exceptions, and run time exceptions can
manifest, or be handled. The example in Listing 12.5 is a toy example used just for
illustration purpose.
If(val == 0)
throw new RuntimeException("From method method2");
return 1;
}
The above statement uses the Java reserved word throw followed by the call to the
constructor of Java class java.lang.Exception. This results in returning an object of
type Exception, with the string “From method method1” as being part of the thrown
object. method2 also has a throw statement, which throws an object of type
RuntimeException. Understand that during execution, method1 or method2, could
only do one of the two things: either perform a normal return, which would be
return an integer value of one, or return an exception object following the word
throw.
public static int method1( int val ) throws Exception //throws clause required
Also clearly understand the difference between reserved words throw and throws.
The word throw is used preceding the instantiation or name of the exception object
to be thrown. On the other hand, the word throws is used as the first word to
broadcast the exception(s) that a method would throw. The word throws is never
used inside a method body and word throw is never used next to the method
header after the argument list.
A compile error would occur, if caller method (main method in this case) tries to call
a method that throws a checked exception with out placing such call in a try block
followed by a catch block that can process the thrown exception. Therefore un-
commenting the statement
This call in Listing 12.5 main
method would be a compile error.
int val1 = method1 (0);
in main would be a compile error. However, the method2 throws an object of type
RuntimeException. Call to methods that throw an object of type4 RuntimeException
is exempted from both requirements – that is to broadcast the exception being
thrown (in the method header), and to place the method call statement in a try
block. Therefore the call below would compile, though the program execution would
terminate right after this call is completed.
Int val2 = method2 (0); This call will compile because method2 throws a
run time exception. However, the program
execution would terminate after the method call.
Last eight lines of the program show the correct technique to call method1 where
pair of try catch block is used to and call to method1 is placed in the try block.
Figure 12.7 shows the compiler and JVM messages and outputs for different calls to
methods method1 and method2 in Listing 12.5.
4
Recall that the word type means that the object could be an instance of that particular class or any
of its subclasses. For example an object of “type” RuntimeException would be either an object of
RuntimeException class or of any of its subclasses.
FIG. 12.7B
The call to method2 with out using the try block compiles and runs since method2
throws an unchecked exception. The first line of method2 prints a statement on the
console. However, the program terminates since an exception is thrown and it is not
handled in the way to recover from this error. This is the general characteristic of
all Java programs. When a Throwable object is not caught (or is not catch-able) in
ways that program can recover from such error, then the program terminates.
Finally if we only keep the last eight lines of code in Listing 12.5, where the call to
method1 is placed inside a try block followed by the catch block, we see the output
shown in Figure 12.7C.
FIG. 12.7C
The output first prints the statement from the method1, and then it executes the
catch block, where the toString method for object ex (passed to catch block) is called
and string returned is printed. The toString method of Exception class prints the
qualified class name (java.lang.Exception) and appends the colon and the message
passed to the constructor when the thrown object was instantiated. Notice that the
part of last output line “From method method1” came from the string that was
passed during the following constructor call in method1.
The formal parameter in the catch clause must match the “type” of actual exception
object thrown from the code inside the try block. For example in Listing 12.5,
writing the catch block as below would result in a compile error.
The reason for this compile error is that compiler can determine that
RuntimeException is a subclass of Exception and it is in violation of laws of
inheritance to pass a super class object, when a sub class object is expected.
However a catch block such as below would not be a compile error as when a super
class object is expected by a block or method, a sub class object can always be
passed at the run time.
catch(Throwable ex)
{
System.out.println(ex);
}
Table 12.2 gives some examples of un-checked and checked exceptions commonly
encountered. A verbal description of some of them was given in sidebar 12.1.
Exception throwing Exception class object thrown Type of the
code Object thrown
int val = NumberFormatException1 RuntimeException
Integer.parseInt(“Hello”);
int [ ] arr = new int [5]; ArrayIndexOutOfBoundsException1 RuntimeException
arr[10] = 10;
String Str = null; NullPointerException1 RuntimeException
Str.length ( );
Vector V= new Vector ( ); NoSuchElementException1 RuntimeException
V.firstElement( );
Object I = new Integer(5); ClassCastException1 RuntimeException
Double Dbl = (Double)(I);
BufferedReader BR = null; FileNotFoundException2 Exception
try (checked
{ exception)
BR = new BufferedReader Assume that no drive
(new with letter G exists.
FileReader("G:\\text.txt"));
}
catch(Exception ex)
{
System.out.println (ex);
}
Based on discussion so far, Java exception handling principles dictate that class
designers and clients:
• are required to provide exception handlers for checked
exceptions. The methods throwing checked exception must
broadcast them in the method header.
• are not expected to provide any handlers for the exceptions of
type java.lang.Error, since recovery from them is generally not
possible.
• may provide exception handlers for exceptions of type
java.lang.RuntimeException, if programmer from the design of
program, can conclude that such handler would provide adequate
program recovery. The broadcasting of thrown unchecked
exceptions in the method header is optional. However, it is a good
programming practice to do so.
java.lang.NumberFormatException
java.lang.Object
java.lang.Throwable
java.lang.Exception
NullPointerException java.lang.RuntimeException
java.lang.NullPointerException
java.lang.Object
java.lang.Throwable
java.lang.Exception
SecurityException
java.lang.RuntimeException
java.lang.SecurityException
java.lang.Object
java.lang.Throwable
java.lang.Exception
IOException and
java.io.IOException
FileNotFoundException
java.io.FileNotFoundException
Table 12.4
The algorithm for Listing 12.6 discussed earlier is implemented as follows. User
input for the input file name is taken from the standard input (L12.6#22). Since
readLine method can throw an IOException, a catch block is included (L12.6#86-
91). The user inputted string is passed as an argument to the File class constructor
to create a File object FL (L12.6#23). This File class constructor can throw a
NullPointerException, for which a handler is placed (L12.6#70-75). The File class
constructor throws a NullPointerException, when a null string is passed to it as
argument. Then the File object FL is passed to the constructor of FileReader class to
create a FileReader object FR (L12.6#24). This constructor can throw a
FileNotFoundException, and we add a handler for that as well (L12.6#81-85).
After printing the message from printStackTrace method, we add any other
optional/clarifying message in the catch block. Finally we set the loop control
boolean variable to false, as the normal loop processing did not take place.
2.
FileNotFoundException
thrown/caught
3.
NumberFormatException
thrown.
4.
IllegalArgumentException
thrown
FIG. 12.9
at java.io.File.<init>(Unknown Source)
at ReadDataFile.main(ReadDataFile.java:23)
The first line says that the constructor of class java.io.File threw an exception. (Java
indicates constructors by expression <init>). Second line gives the location of the line
in the class and method, where the exception was thrown.
After providing a valid file name the user is prompted to enter the size for the read
buffer. A NumberFormatException is thrown when a non-numeric string is entered
(bubble #3 Figure 12.9). And an IllegalArgumentException is thrown by the
constructor of class BufferedReader when the buffer size entered is zero or negative
(bubble #4 Figure 12.9). Program prints out the file provided when a valid buffer
size is entered. Notice that in this listing we were not able to test throwing of
SecurityException and IOException as special device and file permission conditions
need to be created to throw those exceptions.
finally clause
There are situations when the exceptions are thrown, user is informed of the error
condition, and if program resumption is not possible then in the way of recovery the
program tries to reclaim resources as soon as possible. This reclamation of
resources may be connected to for example:
• Closing output file, so that the data written so far is saved safely.
• Closing the input file safely.
• Closing connections to databases.
• Close a socket or network connection.
• Disposing the graphical components using the program memory..
etc.
5
A native Java method calls an existing method that may have been written another programming
language, residing on the operating system or platform on which the program is being run.
6
In relational databases, it is desirable to have primary key, but it is not required.
If the two vectors Names and GPA are used independently (as if they have
nothing to do with each other) then there is no problem. For example, the Names
vector can print student names and GPA vector can print a list of GPA and find
average GPA, etc. The problem comes when we try operations like below:
int ind = 5;
String Student_Name = (String)Names.elementAt(ind);
double current_gpa =
Double.parseDouble(GPA.elementAt(ind).toString());
System.out.println(“The GPA of student “ + Student_Name
+ “ is = “ + current_gpa);
The code above tries to print the GPA of student at the location index = 5, in the
Names vector. Even after assuming that we have confirmed by calling the size
method to make sure that ind = 5, is a valid element in vector Names, we are naively
assuming that database stores GPA for all students! For example students who are
attending college for the first time may not have a GPA, and database may not
require a number to be stored in that field. As a result the elementAt method called
second time may throw ArrayIndexOutOfBoundsException. Worse yet, knowing
that Vector stores Objects, there is no certainty that element at location index = 5 is
indeed a Double type element. This can happen if some how the vector GPA became
corrupted in the process of adding elements to it. Figure 12.13 shows, as how one
would separate this code into neat pieces for exception handling and error trapping.
//Assume that Vector Names and GPA are already populated with student names
//and GPA respectively. Code tasks to print the GPA of student at index = 5 in
//Names Vector. If all students have GPA then size of both vector must be same.
if(Names.size ( ) != GPA.size ( ))
throw new RuntimeException (“Vectors storing student names and GPA “
+ “have different sizes.”);
This somewhat contrived example illustrates the strategy for coping from un-
checked exceptions and their use for error trapping. In actual application a better
technique would be to create a Student class, where Name and gpa fields are
populated first, and then use a Vector of Student objects to print record of each
student, rather than trying to use two parallel vectors the way we used here.
Client of the method can catch that exception and process it further to know that a
zero array size was passed to the method. The problem with this is that
ArrayIndexOutOfBoundsException is not very informative of the situation that a
zero size array was passed to the method! Therefore what is desirable is to define a
In order to test the method findMin, we create an array of random length in main
method (Listing12.7B#6). During some invocations, method Math.random would
supply a zero number, and zero length arrays would be created. We also set the
array arr to a null value randomly (Listing12.7B#9-13), in which case we set the
boolean flag OK to false. If OK is not set to false, then we have a non-null array,
which we fill with random numbers and print it soon after (Listing12.7B#15-25).
Call to method findMin could throw either ZeroArraySizeException or
NullPointerException. Since these two exceptions are unrelated, the order in which
they are thrown is unimportant. However, since in method findMin the
NullPointerException is thrown first, we handle it first in a nested try catch block
(Listing12.7B#31-40). (Understand that client may not have the information as to
which exception is thrown first by the method findMin). Then outer try catch block
handles ZeroArraySizeException. Figure 12.4 shows the results from several run of
the main method in Listing 12.7B.
Printing your array.
66 97 65 56 57 96
The smallest element in the array printed above is 56
return min;
}//FIG. 12.15
In alternate code we do not explicitly check for arr being null or having zero size.
We simply attempt to set min equal to arr [0]. If array size is zero then
ArrayIndexOutOfBoundsException would be thrown. In catch block we throw the
new exception ZeroArraySizeException, so that user gets the precise information
about the nature of exception thrown. Functioning of both methods is similar. The
first version is logically easier to understand, whereas the second version is more
compact. In second version both, NullPointerException and
ArrayIndexOutOfBoundsException are thrown implicitly by JVM. First one is
thrown when a null arr is passed and script operator [ ] are applied to the null
reference. Second one is thrown when program tries to access the first element in a
zero length array.
Liskov view point is to use unchecked exceptions if the client can easily enforce the
pre-conditions dictated by the method being called. This may happen if
confirmation techniques are available for easy enforcements of pre-conditions. For
example in our Listing 12.7B, the client (main method) can easily check if the array
passed to the method findMin is a null pointer or a zero size array (in fact the first
version of findMin just does that). Then exception condition would arise only
occasionally thru programming slips. For example in Java it is quite easy to avoid
ArrayIndexOutOfBoundsException as arrays carry their length.
There are situations, however, when techniques to confirm whether the arguments
used for the method would meet pre-condition or not may not exist or may be as
expensive or more expensive to use than using a compile time exceptions. In such
situations use of checked exceptions would be cost effective. For example let us
assume that a piece of software searches for a key in an array using a method,
whose header is given below.
7
Program Development in Java by Barbara Liskov, John Guttag Addison Wesley 2001
FIG. 12.16
It may be daunting for traditional programmers to see that we are actually using the
exception throwing mechanism to print a legitimate message that certain key was
not found in the array (Figure 12.16). While this is unconventional, when using
Func4();
System.out.println("In Method Func3”);
}
FIG. 12.17A
Since none of the methods in Listing 12.9 have a handler for the thrown object
ErrType, it propagates from its thrower Func4 to Func3, to Func2, to Func1, and
finally to the main method where the program would crash. One can see that in re-
throwing an exception, no explicit throw statement is needed. Exceptions
automatically propagate thru the hierarchy of method calls – until they find a
handler or eventually crashing a program if no handler were found. This
propagation hierarchy would terminate, as soon any pf the method in the path of
hierarchy provides a handler. For example we change the code in Func1 as
try{
Func2( );
}
catch(ErrType Ex){ /*code*/ }
System.out.println("In method Func1”);
The re-throw from Func3, to Func2, to Func1 would continue as it did in Figure
12.17A. However, since Func1, now has a handler, the propagation stops there and
FIG. 12.17B
Notice that the program in Listing 12.9A would not have an output because all
output statements are after the call that throws an exception – and exception never
gets caught. However if we alter the code in Func1 to provide a handler (as shown
earlier), the output statement from Func1 would be executed.
try
{
Func1 ( );
}
catch (ErrType Ex){/*code*/}
Now if at some later date the designer of Func4 changes the method design and
decided to throw some exception other than ErrType, then it would break the client
code. This can also happen if design of other layers (Func1, Func2 etc.) changes to
throw some other exception. Therefore the guiding criterion in deciding to re-throw
or handle an exception is to ascertain that changes do not break the client code.
Questions
1. (T/F) A try block can be used with out the use of subsequent catch block.
2. (T/F) A catch block can be used without use of try block preceding it.
3. (T/F) try catch blocks must be used as a pair.
4. A method throwing a checked exception must throw an object, which is of
type:
A] Throwable but not of type RuntimeException
B] RuntimeException
C] Exception
D] Throwable
E] All of above.
5. A method throwing an un-checked or run time exception must throw an
object of type? (Select correct answer from the list given for question #4).
java.lang.IllegalArgumentException
java.lang.NumberFormatException
ArrayIndexOutOfBoundsException java.lang.Object
java.lang.Throwable
java.lang.Exception
java.lang.RuntimeException
java.lang.IndexOutOfBoundsException
java.lang.ArrayIndexOutOfBoundsException
NullPointerException java.lang.Object
java.lang.Throwable
java.lang.Exception
java.lang.RuntimeException
java.lang.NullPointerException
java.util.NoSuchElementException
ClassCastException java.lang.Object
java.lang.Throwable
java.lang.Exception
java.lang.RuntimeException
java.lang.ClassCastException
FileNotFoundException java.lang.Object
java.lang.Throwable
java.lang.Exception
java.io.IOException
java.io.FileNotFoundException
Table A12.1.1
We can broadly divide the GUI components into the following categories:
1. Widgets or components: These are the GUI units such as buttons,
labels, textboxes, scroll lists, menu items etc. The widgets are atomic
in the nature that they cannot contain other widgets1. All widgets
derive from Java class java.awt.Component.
2. Containers: These are the GUI units, which contain either the widgets
or other containers. For example a Frame or JFrame is a container.
All usable containers derive from Java class java.awt.Container.
Because the class Container derives from class Component, we may in
one sense also consider every container as a component as well.
We mentioned in chapter ten that Java provided two graphics package – AWT
(abstract windowing toolkit) in Java 1.1, and swing package in Java 1.2. The AWT
package was quite limited because it used the peer widgets/containers from an
operating system in order to create a Java widget/container. The AWT component
as a result had different look and feel based on the platform running the Java
program. Swing package introduced vast variety of so called lightweight
components, which did not depend upon the operating system and had same look
and feel irrespective of the operating system running a Java program. In chapter
ten we showed one example of creating a simple Swing window, which had the
intelligence to close by clicking on the close (X) button. In this chapter, first we show
some simple yet interesting swing applications, and then discuss layouts in detail.
One brief point about layouts, however, is in order here.
1
Widgets such as buttons, however, can contain pictures and images.
Our derived class MyButton is simple in design in the sense that except two static
Icon type data members, it only has a constructor in it. The constructor (L15.1A#14-
18) first calls the super class constructor (Figure 15.2), and then calls the method
setRolloverIcon (Figure 15.4), which is inherited from the super class
javax.swing.AbstractButton.
public void setRolloverIcon(Icon rolloverIcon)
Sets the rollover icon for the button.
Parameters:
rolloverIcon - the icon used as the "rollover" image
FIG. 15.4
The code on lines (L15.1A#16 - 17) ascertains that when an object of type MyButton
is created, then the button shows up with String “Fancy Button” and the image
contained in object Pic1. Then if user rolls the tracking device or mouse on the
button, the image changes to the one contained in the object Pic2.
Question15.1: Explain that why would you get a compile error if the line #9 in
Listing 15.1A is changed to the one given below?
private Icon Pic1 = new ImageIcon ("Krishna.jpg");
Question 15.2: Rewrite the constructor for class MyButton in a manner that user of
this class can pass the following three objects as constructor arguments and still
achieve the same results as Listing 15.1 would achieve. The three objects are: a
String with the button title, and two Icon type objects containing the original image
and the roll over image.
Question 15.4: Rewrite the explicit constructor for class MyWindow using the
exception classes written in question 15.3.
Question 15.5: Rewrite the client code in Listing 15.1C when client uses the explicit
constructor written in question 15.4 (and MyWindow class including this
constructor).
In order to set the title, the explicit constructor calls the super class constructor. In
Swing windows, which are of type JFrame, the title and menu-bar of the window are
separate from the lower portion into which the content can be written. Therefore
calling the method getContetPane returns the Container type object (Cont) for this
window (L15.1B#38 & 52). The returned object Cont is used for properties such as
changing the background (L15.1B#39 & 53). Finally the size of this window is set to
the width and height passed to the constructor (L15.1B#40 & 58).
2
Recall that program can recover from checked exceptions but generally not from Runtime or
unchecked exceptions.
2. Instantiation
00069 public ButtonsInMyWindow()
00070 {
00071 Button1 = new MyButton();
00072 Button2 = new JButton("Plain Button");
00073 Win = new MyWindow(Title,width,height, Window_Background);
00074 //Win = new MyWindow();
00075 //Win = new MyWindow(null, 800,800, Color.green);
00076 //Win = new MyWindow("Test Window", -800,800, Color.green);
00077 //Win = new MyWindow("Test Window", 800,-800, Color.green);
00078 //Win = new MyWindow("Test Window", 800,800, null);
00079 Win.addWindowListener(new CloseWindow());
00080 Font FText1 = new Font("SansSerif",Font.BOLD|Font.ITALIC,60);
00081 Button1.setFont(FText1);
00082 Button2.setFont(FText1);
00083 Button1.setForeground(Color.red);
00084 Button2.setForeground(Color.blue);
00085 Button1.setBackground(Color.blue);
00086 Button2.setBackground(Color.yellow);
00087 Container Cont = Win.getContentPane();
00088 Cont.setLayout(new FlowLayout());
89 ButtonHandler Handler = new ButtonHandler();
90 3. Registration
00090 Button1.addActionListener(Handler);
Data members
Button1 and Button2 respectively are objects of type MyButton and JButton
(Listing 15.1C#12 & 16). Four static variables Window_Background, Title, height,
and width define the Color, String for window title, height and width in pixel for the
window that user wishes to create (Listing 15.1C#20, 24, 28, &32). Finally a
reference Win of type MyWindow is declared (Listing 15.1C#36).
Nested Classes
Since we need to provide intelligence to the button objects, we define a nested class
ButtonHandler (Listing 15.1C#54-64) that implements the interface
java.awt.event.ActionListener. This interface only has one method public void
actionPerformed (ActionEvent e), which is invoked when a registered button is
pressed. It is important to understand the code inside the event handler
actionPerformed (Listing 15.1C#59-63). When the button registered with action
listener ButtonHandler is pressed, a JOptionPane message dialog is popped on user
screen that displays the String “You Pressed” and the title of the button. The code
portion: e.getActionCommand executes the corresponding method whose
description is given in Figure 15.5.
public String getActionCommand()
Returns the command string associated with this action. This string allows a
"modal" component to specify one of several commands, depending on its state. For
example, a single button might toggle between "show details" and "hide details".
The source object and the event would be the same in each case, but the command
The nested class CloseWindow (Listing 15.1C# 40-50) extends the class
java.awt.event.WindowAdapter and overrides the method windowClosing whose
details are given in Figure 15.6.
Constructor
In Class ButtonsInMyWindow (Listing 15.1C# 69-95), the constructor does almost
all the work. First the constructor instantiates the Button1 by calling the default
constructor for the MyButton class (Listing 15.1C#71). Then the Button2 that is of
type JButton is instantiated (Listing 15.1C#72). The explicit constructor for the
MyWindow class is called to instantiate a JFrame type object (Listing 15.1C#73).
The parameters passed to the constructor in line 73 customize the window to be
FIG. 15.10C
FIG. 15.10D
Layout Managers
We briefly talked about one Java layout manager called FlowLayout. Layout
managers define the pattern in which either the widgets or containers can be placed
on a Java Container. Figure 15.11 shows a general classification of layout managers
available in java.awt package.
FlowLayout
As discussed earlier, in flow layout we add the widgets and containers to the
container being painted much the same way in which words are added to a line and
lines to a page in a word processor, i. e. starting from left to right and top to bottom.
Table 15.3 shows the summary of fields, constructor and methods for the class
called MyFlowlayout that gives a demonstration of the typical example of the use of
FlowLayout manager.
Table 15.3
The class MyFlowlayout has seven data members, four of which (Title, height,
width, and Window_Background) are required for the object Win, which would be
the container for the array of JButtons called Buttons. The integer constant FIVE
gives the number of JButtons that would be displayed on the container Win. The
only constructor for the class MyFlowlayout instantiates the button and window
objects and gives the intelligence to JButton objects as well as adds them to the GUI
to be displayed. The method setSwingLookAndFeel sets the look and feel of the GUI
to be displayed to conform to default Swing standards. The inner class
ButtonHandler remains same as Listing 15.1.
The Listing 15.3 shows the source code for the class MyFlowlayout.
00001 import java.awt.event.*;
00002 import java.awt.*;
00003 import javax.swing.*;
00007 public class MyFlowlayout
00008 {
00012 private static final int FIVE = 5;
00016 private JButton [ ] Buttons;
00020 private static Color Window_Background = Color.cyan;
00024 private static String Title = "My Window with Plain buttons";
00028 private static int height = 800;
00032 private static int width = 800;
00036 private MyWindow Win;
00042 private static class ButtonHandler implements ActionListener
00043 {
00047 public void actionPerformed( ActionEvent e )
00048 {
Inside the constructor (L15.3#59-83), first we call the explicit constructor for class
MyWindow to instantiate the object Win (L15.3#61). In Java 1.4 and above the
method setDefaultCloseOperation can be called on a JFrame type object to close it
with out needing to register it with a WindowListener type object. This is done for
the object Win on line 62. Figure 15.12 describes the details of the method
setDefaultCloseOperation.
public void setDefaultCloseOperation(int operation)
Sets the operation that will happen by default when the user initiates a
"close" on this frame. You must specify one of the following choices:
FIG. 15.16A
A border drawn in Button 1 indicates that as a default, in flow layout, the left-most
component is in focus. The focused button may be activated either by pressing it by
a mouse or by pressing the space-bar key on the keyboard. Figures 15.16B, and C
show the layout when layout is right aligned or center aligned. This requires
commenting in the code line 67 and 68 respectively.
FIG. 15.16B
FIG. 15.16C
When line 69, using the layout where the constructor of FlowLayout class takes no
argument is commented in, the result is similar to the Figure 15.16C, indicating that
argument-less constructor defaults to center alignment of components.
FIG. 15.17A
As displayed, this window is not too different from the Figure 15.16A. However if
one drags the right edge of this window with a mouse and reduces the width then
buttons rearrange themselves, first in the pattern shown by Figure 15.17B and
finally all aligned in one vertical column (Figure 15.17C).
FIG. 15.17B
Border Layout
In border layout the components are placed east, west, north, south along the four
edges and at the center of the GUI display. Figure 15.18 shows the schematic picture
of border layout.
FIG. 15.18
Listing 15.4 shows an example of using border layout.
00001 import java.awt.event.*;
00002 import java.awt.*;
00003 import javax.swing.*;
00007 public class MyBorderlayout
00008 {
00012 private static final int FIVE = 5;
00016 private JButton [ ] Buttons;
00020 private static Color Window_Background = Color.cyan;
00024 private static String Title = "My Window with Plain buttons";
00028 private static int height = 800;
00032 private static int width = 800;
00036 private MyWindow Win;
00042 private static class ButtonHandler implements ActionListener
00043 {
00047 public void actionPerformed( ActionEvent e )
00048 {
00049 JOptionPane.showMessageDialog( null,
00050 "You pressed: " + e.getActionCommand());
Figure 15.19 shows the output from the main method of Listing 15.4 in the as
displayed form and packed form.
FIG. 15.19B
As indicated earlier, when the Swing Look and Feel is used the display at minimum
width and height packs all the components in the frame that is visible, with out
allowing the disappearance of any of the components. If the line 72 in Listing 15.4,
which sets the layout, is commented out, even then the output from main method of
Listing 15.4 remains unchanged. This is because the border layout is the default
Grid Layout
In grid layout, the components are arranged in a grid, which is controlled, by the
number of rows and columns defined by the user. Figure 15.20 shows the
constructors for the class GridLayout.
public GridLayout()
Creates a grid layout with a default of one column per component, in a single
row.
-------------------------------------------------------------------------------------------------
public GridLayout(int rows, int cols)
Creates a grid layout with the specified number of rows and columns. All
components in the layout are given equal size.
One, but not both, of rows and cols can be zero, which means that any
number of objects can be placed in a row or in a column.
Parameters:
rows - the rows, with the value zero meaning any number of rows.
cols - the columns, with the value zero meaning any number of columns.
-------------------------------------------------------------------------------------------------
public GridLayout(int rows, int cols, int hgap, int vgap)
Creates a grid layout with the specified number of rows and columns. All
components in the layout are given equal size.
In addition, the horizontal and vertical gaps are set to the specified values.
Horizontal gaps are placed at the left and right edges, and between each
of the columns. Vertical gaps are placed at the top and bottom edges, and
between each of the rows.
One, but not both, of rows and cols can be zero, which means that any
number of objects can be placed in a row or in a column.
All GridLayout constructors defer to this one.
Parameters:
rows - the rows, with the value zero meaning any number of rows
cols - the columns, with the value zero meaning any number of columns
hgap - the horizontal gap
vgap - the vertical gap
Throws:
IllegalArgumentException - if the value of both rows and cols is set to zero
FIG. 15.20
The argument-less constructor for class GridLayout places all components in one
row, in which case each component becomes a column in the display. The second
What happens if the number of rows and columns specified in the second
constructor in Figure 15.20 calculates to the number of components spaces less than
the actual number of components added? In that case the number of rows set are
equal to the first constructor argument, whereas the number of columns is increased
to the necessary number that all added components are accommodated in the
display. For example if the constructor call on line 67 is changed to the one below,
then the display shown in the Figure 15.21C results.
Cont.setLayout (new GridLayout(2,1));
FIG. Xxx
accelerator keys. These are the keyboard actions, which perform the same task as
the mouse clicked tool bar, or menu items would. For example once the text is
highlighted in the word document, one may copy it by using the keys Control + C, in
place of performing the copy action using the tool bar or edit submenu.
Typically one provides this single task multi-enablement as follows: The tool bar
button, the menu item would be registered with the same ActionListener type
object, whose actionPerformed method would enable the two widgets to perform the
same function. However, we also wish that if user selected no text to copy then both
tool bar and menu copy options are disabled in unison! On the other hand if user
did select text to copy to system clipboard, then both aforementioned widgets must
enable in unison as well. Imagine what can happen if this synchronous behavior of
tool bar button and corresponding menu item was not present? The copy toolbar
button may be enabled, while the copy menu item may not be. Suffice to say that it
will cause confusion in using the GUI. The typical use of actionPerformed method in
an implemented ActionListener interface is straightforward in ascertaining that
when an event object fires, then all widgets registered with it behave in unison.
However, enabling and disabling of widgets in unison is not so straightforward. One
would actually need to keep a list of widgets, which register with a particular
ActionListener object, which requires extra programming effort. The situations,
where several widgets in a GUI must fire and get enabled and disabled in unison,
the use of Action object facilitates the task greatly.
The steps similar to the Figure XXX can be taken to synchronize behavior from all
widgets registered with the same action object (Copy_Obj in this case).
1. Define subclass of AbstractAction to implement the
actionPerformed ()
Step four in Figure xxx shows that one can control the synchronous enablement or
disablement of user interface widgets from a single place, which in this case is the
Action object Copy_Obj. The step three in Figure xxx becomes possible because the
constructors of following widgets can take an Action object as argument thus setting
the property of the widget as supplied by the Action object passed to it (Figure
XXXX). The description of JButton constructor is also given.
JButton(Action a)
JToggleButton(Action a)
JCheckBox(Action a)
JMenuItem(Action a)
public JButton(Action a)
Creates a button where properties are taken from the Action
supplied.
Parameters:
a - the Action used to specify the new button
FIG. XXX
In addition to the constructors of widgets taking an Action object as argument, they
also have method setAction, which can take an Action object as argument. The list
of these methods and detail of one of them are given (Figure XXXX).
JComboBox.setAction (Action a)
JTextField.setAction (Action a)
JButton. setAction (Action a)
JToggleButton. setAction (Action a)
JmenuItem. setAction (Action a)
AbstractAction(String name)
Defines an Action object with the specified description string and a default icon.
Object[] getKeys()
Returns an array of Objects which are keys for which
values have been set for this AbstractAction, or null if no keys
have values set.
PropertyChangeListener[] getPropertyChangeListeners()
Returns an array of all the PropertyChangeListeners
added to this AbstractAction with
addPropertyChangeListener().
Object getValue(String key)
Gets the Object associated with the specified key.
boolean isEnabled()
Returns true if the action is enabled.
Table XXX
The constructors of class AbstractAction show that any widget whose constructor
takes an Action object (hence an AbstractAction object) as argument can have its
label set to the desired string. Alternately an icon and a string can also be passed as
arguments.
Applet
pp Class API Documentation
Numerous Methods
Bare minimum ones are only two!
1. void init( )
Called by the browser or applet viewer
to inform this applet that it has been loaded
into the system.
2. Inherited from super class Container
void paint(Graphics g)
Hello World Java Applet
import java.awt.*;
i
import
t java.applet.*;
j l t*
public class HelloWorldApplet extends Applet{
public void init( ){
setBackground(new Color(250,0,100)); }
public void paint(Graphics g) {
gg.setFont(new
( Font("Ariel",
( , Font.BOLD,, 48));
));
g.setColor(Color.blue);
gg.drawString(
drawString("Hello
Hello to World From El Camino!
Camino!",0,150);
0 150);
}}
How Does it look?
Dissecting the Code
imports
•Browser
Browser java virtual machine is not
allowed to run any code that may have an
assembly language instruction
instruction.
•This is because by running the assembly
code the server can get hold of random
chunks of client’s memory – a great
security hazard.
hazard
High level Security Issues
•Before Applet is run, the browser loads a
sec rit manager.
security manager
•If Applet code tries to read a file or write to
a file
fil on client
li machine,
hi the h security
i manager
will shut it down.
•The signed applets can ask client permission
to over-ride the security manager.
•Signed applet must give Server’s contact
information and risk level! With out that
browser will not let it run.
No main( ) method in the Applets
•One can design java virtual machine
to run
r n any
an method first
first.
•In this case the method init ( ) is
called
ll d first!
fi
Lifetime of a java Applet
•init( ) method is called first!
•Then browser calls an applet method called start( )).
•If user moves to another web page then the method stop( ) is
called to free non
non-memory
memory resources that applet may have been
using.
•For example
p if Applet
pp was doing g an animation, and user moves
to another web page, then stop ( ) method will stop the
animation and resources will be freed.
•When user returns to the page, the start ( ) method is called
and applet starts again.
•destroy(
d t ( ) method
th d iis called
ll d tto d
destroy
t th
the applet,
l t when
h all
ll
browser windows are closed!
Why our code did not have those
methods?
•start, stop and destroy methods are called internally by the
virtual machine,
machine so we do not need to include them
them.
•But to show their functioning we can include them
intentionally and show as to how they work.
work
•This is done in the next example.
BasicEventApplet
• In addition to init( ) and paint( ), the following methods are
added intentionally:
1. A constructor
2. start( )
3. stop( )
4 destroy( )
4.
Sequence of Events
• As soon as Applet is started, the constructor is called first.
• Then applet is initialized by calling the init( ) method.
method
• Then applet is started by calling the start( ) method.
• Th paint(
Then i ( ) method
h d paints
i the
h applet.
l
• If other widows cover and uncover the applet, the paint
method is called every time to paint the applet back.
back
Sequence of Events - 2
• If user moves to another web page then stop( ) method is
called to free non-memory resources.
• When user comes back to the applet web page again, the
applet is started again.
• This behavior may differ based on browser, but appletviewer
shows this sequence clearly.
Applets with parameters
• Applets can take parameters embedded in HTML code and
display them or use them in the applet display.
• Shown in the applet based on java file ParameterApplet.java
HTML code to include
parameters
• <APPLET
• CODE="ParameterApplet.class"
CODE "P t A l t l " WIDTH=450
WIDTH 450
HEIGHT=300>
• <PARAM NAME=
NAME="name"
name VALUE=
VALUE="Satish
Satish Prakash
Singhal">
NAME
attribute
• <PARAM NAME="yourHeight" VALUE="5.5">
• </APPLET> U param
Use VALUE
tag attribute
How Applet gets the parameters?
Uses its getParameter( ) method.
String getParameter(String name)
R t
Returns th
the string
t i value
l off the
th named
d parameter
t iin th
the
HTML tag.
For example the call
getParameter("yourHeight")
Will return the
h yourHeight
H i h value
l included
i l d d in
i the
h HTML
code.
CS 3: Java
Chapter 19: Connecting To Databases
Author: Satish Singhal Ph. D.
Version 1.0
One can connect to databases from a Java program through variety of interfaces.
The interface may be a desktop application, a web site, a cell or regular phone, or a
voice activated device. The database may be located locally on the client machine, or
located on a distant machine. In all cases, the computer (or program) requesting a
connection to database is called a client1 and the computer (or program) honoring
the request is called a server. This forms one type of client-server architecture. If
client and server are on the same machine, then there is no communication protocol
needed for the two to connect and communicate. The client-server relationship in
that case is almost similar2 to a person being able to open a browser by clicking on
the hyperlink embedded in their e-mail message. However, if the database were
located on a distant and/or on a different machine the communication would involve
some protocol. For example in a local area network in a company or university, the
computers may be connected by Ethernet protocol. The computers on Internet are
connected by TCP/IP networking protocol. This chapter is devoted, only to the
situation, where a Java program does not have to worry about as to what kind of
communication protocol would be there between the client and server. Later on
when we discuss networking Java application, we would lift this barrier.
1
This is true even if the client program and database server program are located on the same
machine.
2
It is actually a bit more than that, however this simplification is reasonable.
Of four types of databases, the RDBMS are in widest use in enterprise applications.
To remove any ambiguity, let us clarify as to what we mean by a table? A table is a
collection of data, which has rows and columns. For example a typical address book
(Figure 19.1) may have rows where each row indicates the address record for a
person and with in each row, there would be fields or columns storing one type of
information.
Column
3
Word view has a special meaning in database technology. Its discussion is not in the scope of our
textbook.
4
Granted that term “not too large” is not well defined.
5
There are other string data types in Oracle, such as NCHAR and LONG, which are not considered
here.
Now the Zip code field appears in both tables. However the two tables can now be
related via their common field. Since in Zip code table, no two records would ever
have same value of the Zip code (since no two sates in US have the same zip code),
the zip code field in this table is given a special name called “primary key”. On the
other hand in the first table, we may have addresses of more than one person living
in the same zip code. The relationship between two tables is then called one-to-many
relationship. When a primary key in a related table appears as a column in its
relative table, it is given a special name “Foreign key” in that table. Thus Zip code
field in the table with addresses is the foreign key. Though it is not necessary that all
tables have primary keys, it is undesirable to build a database table with out one.
The existence of primary keys helps build database indices and views to speed up
the search process, in addition to maintaining data integrity and reducing
redundancy. Therefore we added a column in the first table called ID #, which
would be different for each person in our personal address book, thus acting its
primary key. Decomposing the data tables in one or more, selecting proper primary
and foreign keys – are all part of good database design process.
FIG. 19.3
Using the syntax of Figure 19.3, the following statement will create the table called
US_ZIP_CODES in the database.
6
I sincerely acknowledge Professor Harold Rogler at Santa Monica College, from whose notes this
Figure is taken from.
Table 19.3 gives the decisions made about the personal address table and its
columns.
Some times we may need to alter the tables after they have been created. The
ALTER statement is used for that. For example we may need to add two more
The following ALTER statements will add the additional columns to the table
PERSONAL_ADDRESS_BOOK_US.
FIG. 19.4
The decision whether to choose certain field as non-null depends on if not recording
the value of that field in database will make the record meaningless. For example an
address entry with out person’s name, city and zip code is meaningless and we
might as well wait until those data about person become available. We can afford
not to have street address, and birth date in the beginning as those data can be
added later. Therefore a null value for them, in the interim, is affordable.
The DROP statement deletes the table from the database. The syntax of DROP
statement is simple:
After using the words INSERT INTO one provides the list of columns into which
data are to be entered. The column names are separated by comma. Then after the
word VALUES one provides a comma-separated list of values in the same order in
which column names were provided. The number of columns and values in the
INSERT statement must be equal. If the data table has a primary key, then a record
cannot be inserted unless the value of primary key is specified. This, as you would
recall, that a primary key for a record cannot be null. The data types for values
must match the data types for columns – though some exceptions to this rule may
exist.
Since the Table US_ZIP_CODES has a field that acts as a foreign key to the table
PERSONAL_ADDRESS_BOOK_US, we must populate the former first. An
INSERT statement such as below would insert the Zip code and state values.
SELECT statements
Since the biggest application of databases is in making queries on the data stored in
them, SELECT statement is one of the most used SQL statements. Simplest use of
SELECT statement is in getting all the records stored in a table. For example the
statement below may produce an output similar to the Figure 19.5.
FIG. 19.5
The use of * after the word SELECT tells the database to get all the records from
the table US_ZIP_CODES. The header of second column is truncated. Very often
the queries are done subject to some constraints. For example we may only be
interested in getting the list of Zip codes stored in the table for California or CA.
The keyword WHERE is used to qualify the query further.
The above query would only produce the first line of output from the Figure 19.5.
Wild cards can be added to the queries.
For example a query such as below will produce result shown in Figure 19.6.
FIG. 19.6
SELECT statement can use keywords ORDER BY to sort the data based on certain
column of some other criteria. We postpone showing other uses of SELECT till we
discuss them through some concrete Java program examples.
UPDATE statement
UPDATE statement is used to alter the value of a field, other than primary key, of a
record in the data table. If the field to be altered is a foreign key, then the new value
must exist in the related table before an update is done. The Figure 19.7 shows the
syntax of UPDATE statement.
The new value for the column. This can be a literal, another
[WHERE condition];
column name, an expression involving literals, strings, and
column names.
Optional WHERE
statement would make
assignments only when
condition is true for a
row!
Notice that after the word SET the column names and their expression list is comma
separated.
Let us imagine that John Doe shown in Figure 19.6 moved to Florida with new
address being ‘1923 Swamp Lane’ ‘Water Falls’, ‘FL’, ‘32003’. Then since Zip code
field in the address book table is a foreign key, first we must ascertain that this new
zip code in Florida exists in the related table for US Zip codes. If not then we insert
UPDATE PERSONAL_ADDRESS_BOOK_US
SET ADDRESS = '1923 Swamp Lane', CITY = 'Water Falls',
ZIP_CODE = '32003'
WHERE ID_NUM = '0001';
In above statement the WHERE clause defines the location of the record to be
updated by specifying the primary key (ID_NUM) for the record. As alluded earlier,
depending upon the WHERE condition, fields for more than one records can be
altered in one UPDATE statement.
DELETE statement
The DELETE statement can remove a record from the data table. The syntax for
DELETE is given below.
Understand that if where clause is skipped then ALL rows from the table with
TableName are deleted. An easier way to delete all rows from a table is to use the
TRUNCATE statement. For example syntax like below will delete all rows from
table called TableName.
SQL operators
We have already seen one SQL operator equal (=) in use. The SQL operators can be
words as well as mathematical symbols. Table 19.6 gives a list of commonly used
SQL operators.
Operator symbol/word Meaning Example
= Equal WHERE ID_NUM = 0001
> Greater than WHERE AGE> 20
< Less than WHERE AGE><25
>= Greater than or equal WHERE AGE >= 36
<= Less than or equal WHERE AGE <= 99
<> Not equal WHERE AGE <> 55
LIKE Pattern match WHERE NAME LIKE ‘%hn’
IN Matches any of given choices WHERE AGE IN (19, 20, 20)
Table 19.6
FIG. 19.7
Therefore in the process of connecting to a database, a Java program first loads the
driver for the database and then communicates to DB through it. Two Java
packages java.sql and javax.sql provide necessary classes for facilitating the overall
communication with databases. A more popular name for these packages is JDBC
or Java database connectivity. Let us talk a bit more about database drivers. For
various flavors of windows Microsoft introduced a system of database drivers
collectively called ODBC (open database connectivity). One can find these drivers
by using the following procedure in Windows 9X:
7
The database such as Microsoft Access provide graphical interface with some functionality as well.
FIG. 19.8
ODBC drivers are written in C programming language. A Java program can in fact
make calls to ODBC driver directly as Java allows native method calls. This
however is complicated, as doing so would require differing codes to load different
drivers (one piece of code to load driver for Access, and another SQL server, or text
file, or Excel spread sheet). Also C has pointers, which are inherently unsafe, thus
compromising Java’s security paradigm. Sun found a solution to this problem, by
including a JDBC to ODBC bridge in its JDBC API. The JDBC:ODBC bridge can
load and communicate with any of the ODBC drivers with out having to worry
about as to which database is being called from your program. Therefore if we use
JDBC:ODBC bridge, then the database driver portion of Figure 19.7 can be
visualized in more detail as shown by Figure 19.9.
8
On Windows 2000, XP, and NT one may need to click on “Administrative Tools” in order to get to
icon ODBC Data Sources.
Sun Microsystems maintains a web site where one can get list of available drivers
for various databases at the web address:
http://servlet.java.sun.com/products/jdbc/drivers/index.html
Since the above address may change in time, the generic web address java.sun.com
can be used to search for current database drivers. Knowing some details of
database drivers to use, following steps are taken to connect to the database:
9
Type 1 drivers use JDBC:ODBC bridge API.
new JdbcOdbcDriver( );
import sun.jdbc.odbc.*;
Net affect of using the above import and calling the constructor of JdbcOdbcDriver
class is to extract the necessary information from JdbcOdbc.dll and add it to your
program.
There is an alternate approach available, where you do not have to import the
package sun.jdbc.odbc. This approach uses the class named Class in java.lang
package. This class has a static method called forName, which takes a string
containing fully qualified name of a class, makes a constructor call for that class and
returns a Class object for it. You can actually call the static method shown below
(Listing 19.1) from the main method, and output will print java.lang.String.
try
{
Class.forName (“sun.jdbc.odbc. JdbcOdbcDriver”);
}
catch(ClassNotFoundException Cnfex)
{
//code to handle ClassNotFoundException
}
The third step in the procedure is to get URL string, user name and password
strings for the database we are interested in communicating with. The last two
strings are set by the DBA for the user.
FIG. 19.10
The driver being used could determine database identifier name, however it
depends upon how the driver and DB administration software maps the database
file(s) to their physical directory. There are two situations we may face.
1. Database is created through the process, which simultaneously registers it
with the driver.
2. Database exists but it has not been registered with the driver or DB
administration tools.
We show examples for both cases (for Windows 9x) and how the database identifier
is generated. Let us assume that you wish to create a Microsoft Access database
called MyAddressBook, which shall be located on physical drive C. Figures 19.11
show, the process step-by-step.
1. Click on startÆ Settings Æ Control Panel.
2. Double click on ODBC Data Sources10 (32 bit) so that applet shown by
Figure 19.11 A shows up.
On Windows XP, NT and 2000, the ODBC source icon can be reached as follows: Click on start Æ
10
FIG. 19.11B
6. In this dialog box fill out (as shown above), the data source name and its
brief description. Then click on create. The data source name and
description is for identifying the database.
1. Fill the
database
file name.
FIG. 19.11C
Here fill out the database file name (bubble #1). Choose the physical directory in
which database will be located. And finally click on OK button. The success of
database creation will be indicated by the confirmation dialog popup message
(Figure 19.11D).
FIG. 19.11D
If we choose database name to be MyAddressBook.mdb and its physical location
on drive C, then clicking on OK in Figure 19.11C will give the message shown in
Figure 19.11D.
8. Close out all dialog boxes by clicking ok in each case.
The database identifier (the last part of database URL string) is then the Data
source name (DSN) that we filled out in Figure 19.11B. For example the
identifier for the database created above is: “Personal Address Book”.
The above process creates a database and registers it with the ODBC driver
simultaneously. If the database already exists but it has not been registered with
FIG. 19.11E
Repeat steps six for the pre-existing database, and then click on select button
(Figure 19.11E). This makes sense because the database already exists, so we do
not need to create it. Rather we just need to select it to finish the registration
process. This leads to the popup window similar to the one shown in Figure
19.11C. This time however navigate to the physical location on the drive where
database is located and choose it so that its name shows up in the left pane. Then
select it and click ok. For example had you created the database
MyAddressBook independently through Microsoft Access and then try to
register it, then selecting it for registration will lead to the Figure 19.11F below.
FIG. 19.11F
FIG. 19.12
Thus the URL string for the database created or registered as above will be:
“jdbc:odbc: Personal Address Book”. Notice that URL string does not need to know
the physical drive and file extension of the database as the ODBC driver (after
registration) has both of those registered with it already.
A part of the database URL string will change if you are connecting to the database
across a network. For exact semantics of figuring out sub protocol and database
identifier, you would need to consult the literature that comes with the database.
For example let us say you were connecting to a database on Internet, which has the
following details:
Connection method: jdbc:rmi (Remote method invocation)
Database web URL: 192.168.170.27:1099
Sub protocol: jdbc Portion before colon gives the IP
Database identifier: cloudscape:db address and after the colon gives the
Then the database URL in this case is: port number.
The most commonly used version is the third one which takes database URL, user
name and password as arguments. The details of the third version taken from Java
API are shown in Figure 19.13.
public static Connection getConnection(String url, String user, String password)
throws SQLException
Attempts to establish a connection to the given database URL. The DriverManager
attempts to select an appropriate driver from the set of registered JDBC drivers.
Parameters:
url - a database url of the form jdbc:subprotocol:subname
user - the database user on whose behalf the connection is being made
password - the user's password
Returns:
a connection to the URL
Throws:
SQLException - if a database access error occurs
FIG. 19.13
Notice that method getConnection throws an SQLException, which is a checked
exception. Therefore any call made to getConnection must be inside the mandatory
try block followed by a catch block to handle the exception. Therefore the syntax of
the call to getConnection method would look like as follows:
The version of getConnection method that takes a single string as argument can be
used by folding database URL string, user name, and password – all in one using the
following syntax:
try
{
Connection Con = DriverManager.getConnection (
“database URL string;UID=user name string; PWD=password string”);
}
catch(SQLException Sqex)
{
//code to handle SQLException
}
The getConnection method parses the string passed to it as argument for database
URL, user name and password and either returns a corresponding Connection
object or throws SQLException. Once a Connection object is obtained, the
Statement object can be created for further data processing.
In order to use the above technology effectively, we wish to design a class called
MyConnection in which client usable methods will all be static. We would like this
class to have the intelligence, that it would return to us a Connection object for the
given database URL, user name and password. And in the process it will also take
the input for the type of database driver, other than JDBC:ODBC bridge that we
may wish to use. The class would also have methods to close the database connection
and provide a list of all the drivers loaded. This class can be used to open
connections to as many databases as user wishes to open at the same time. Table
19.8 gives the summary of the design of class MyConnection. A high-level diagram
showing class fields, constructor and methods is given by Figure 19.14.
Listing 19.2A shows the source code implementing the design shown by Table 19.8
and Figure 19.14.
//Listing 19.2A
///////////////////////////////////////////////////////
00001 /*
00002 * DataBaseTest1.java
00003 *
00004 * Created on October 16, 2004, 7:14 AM
00005 */
00006 import java.sql.*;
00012 public class DataBaseTest1
00013 {
00014
00016 private DataBaseTest1() {}
00017
11
In a more advanced version, we may loop user through to get the valid input for the null string
values passed to the method. However that may not work in all situations.
The code line 104 in Listing 19.2A calls the method forName taking the driver path
string as argument and loads the driver. Checked exception
ClassNotFoundException is handled and client is informed if the exception is
thrown.
The last step in the process is to get a Connection object and set the class member
Con to point to it. Private instance method makeConnection is called for this
purpose (L19.2A #77).
There are several ways to make connection to the database. The method
makeConnection (L19.2A #124-142) shows all of them. The code lines for alternate
ways are commented out (L19.2A #130 & 132-133). One version of getConnection
method of DriverManager class takes the three strings – database URL, user name,
and password – as arguments and returns a Connection object (L19.2A #131).
getConnection is an overloaded method whose summary was discussed in Table
19.7. If getConnection throws an SQLException, then it is handled and user is
informed of such exception having been thrown (L19.2A #137-142). If
SQLException is not thrown then connection to database is successful and user is
given a message accordingly (L19.2A #134-135).
Finally the method getMyConnection returns the class level Connection member
Con as an object to interact with the database (L19.2A #78).
Method getDatabaseMetaData
Before we discuss more details, we must define what is metadata? In simplest terms
the metadata are data about data. More precise terms, the metadata are data about
information bearing objects. Database is an object that may have many properties.
One simple property about database that we discussed was the data types it may
support. The client using a database from a Java program may be interested in
finding out all possible data about the database they are using. Java interface
java.sql.DatabaseMetaData has methods that can provide vast amount of
information about a database object. The Connection class has a method
getMetaData which returns an object of type DatabaseMetaData. This returned
object can be used to survey or print various properties of the database the user is
connected to. One simple example of this is that a database may have reserved
words other than the one specified by SQL92 (which is the standard SQL). The
method getSQLKeywords for the object of type DatabaseMetaData can provide one
a comma separated list of these non-standard keywords. We shall see a short
example of that soon. In order to provide the DatabaseMetaData object for a
database pertaining to certain Connection object we simply call the method
getMetaData as per syntax given on line # 216 in Listing 19.2A, where the method
call returns an object of type DatabaseMetaData. A simple example of using this
DatabaseMetaData object would be a call such as below:
Method okToUseBatchOperation(L19.2#235-258)
When we discussed SQL, we showed example of execution of one SQL statement at
a time. Understand that each time you execute just one statement you have to make
a trip to the database back and forth. When large amount of data are to be added to
the database this could be slow and wasteful. Depending upon the type of driver
available a batch operation may be allowed. What that means is that user can add
all the SQL statements in a batch (details later) and then execute all of them at once.
However, before embarking on a batch operation such as this, the database driver
must allow this operation. User can find out about such situation by calling the
method supportsBatchUpdates for the DatabaseMetaData object for the database.
Method okToUseBatchOperation facilitates this for the client. The method takes the
Connection object as argument. Then it calls the static class method
getDatabaseMetaData to get the object of type DatabaseMetaData for this
Connection object. The DBMD object thus returned (L19.2#243) is then used to get
a Boolean value by calling its member method supportsBatchUpdates. If this
method returns true then the batch SQL operations are supported otherwise they
are not. The method returns the value of local variable OK accordingly. Illustration
of use of this method is made later, when we attempt batch SQL updates.
FIG. 19.15A
If a driver other than JDBC:ODBC bridge is needed then user would enter the
name for that in the dialog box and click OK. Otherwise user would click cancel.
The connection to database is then attempted, and if successful then the
confirmation dialog shown in Figure 19.15B is shown.
FIG. 19.15B
The dialog also informs of the database URL to which the connection is successfully
made. Now one can execute DDL and DML SQL statements with the database to
which the connection is obtained. To do this systematically, however, requires
developing another class called MyStatement, which we discuss next.
FIG. 19.16
12
One should be aware that there is also a class called Statement in the package java.beans. If both,
the class Statement and interface Statement are to be used, and then one must use their full qualified
names.
FIG. FYZ1
In Figure FYZ1 the portion containing buttons on the top is a panel, where pressing
different buttons accomplishes relevant purpose of data entry or display. The
middle panel has the data entry/display text fields and their labels. The lower
portion is a non-editable text area, where the messages are printed for the user from
database or from the program. An improved design may also include the text fields
for entering the user name and password and may show a progress bar to indicate
the task progress. To implement above look and feel, we design the classes with
following scheme. We design a class called ControlPanel, which shows the top part
of GUI with buttons. The responsibilities of this class are discussed in the Table
TYZ1 below.
13
It goes without saying that the best look and feel for a GUI requires a design of its own. Graphical
designer and user should jointly come up with the best GUI design and then communicate that to the
software engineer.
javax.swing.JPanel
ControlPanel
ScrollingPanel Class
As discussed earlier, the responsibility of this class is to provide the middle part of
the form that has the text entry fields and their corresponding labels. Understand
that this class does not have the responsibility to provide intelligence to the data
entry fields. That responsibility, coupled with intelligence for buttons lies with
ControlPanel class.
Chapter 20 : Multithreading1
Author: Satish Singhal Ph. D.
Version 1.0
When a single program can switch between different (lightweight) processes, it is
said to be a multithreaded program. Each lightweight process running in the
program is called a thread. This definition requires that we understand the concept
of “process” clearly. When an operating system (OS) executes a program, it creates
a process dedicated to it. If you would like to see all such processes running on a
Windows XP computer, then you can press Control + Alt + delete keys, and under
processes tab you would see a picture similar to the Figure 20.1.
Figure 20. 1
The process chart will include the OS (native) processes as well as the ones created
by the applications. Process for an application would create its own stack and heap
memory areas, as well as other components. Threads, which more precisely must be
called “threads of control”, do not create a separate heap. Rather all threads share
1
This chapter discusses multithreading based on Java 1.4. Java 1.5 has additional support for
multithreading in the package java.util.concurrent. At the time of this writing Java 1.5 has been
released only as a Beta version.
Figure 20.2
The above figure shows us a process, as it would be executed by the operating
system. The part of the process which is enclosed in the dotted line box is called a
thread. Each thread has its own stack, stack pointer, and program counter.
However all threads would share the same heap, and may share the resources in the
miscellaneous category. Because more than one thread would share the same heap,
care is required when writing multithreaded applications so that state of heap is not
corrupted by one thread. Program counter simply keeps track of the line number in
the binary code being executed for a certain thread.
Why would one need threads in an application? Imagine that your program is
waiting for user to input some data, or for a server to open a connection. This “wait
time” can be put to better use by attending to some other tasks in the program. An
excellent example of this is when you open a web browser. All the images and other
components in the web page open up simultaneously, controlled by many threads in
the browser process. In this sense it would appear that threads are doing
multitasking. However, threads are lightweight processes as they only give us an
illusion of multitasking. Two threads can be doing some program task
simultaneously or one thread may be inactive, while other is doing something.
You would see that even though the end of main has reached, the Window shown by
the program does not shut down. The reason is that window is showing in its own
“thread of control” called a swing thread. Therefore you may surmise each Java
program displaying a swing component to be a multithreaded program. However, at
times we may wish to create other threads of control in a Java program. Now we
describe how to accomplish that.
The minimal code that is needed in both above thread-able classes is to override the
base class method called run in the MomThread class, and implement the same
name method in the DadThread class. Needless to say that interface Runnable only
has one method called run, which must be implemented by the concrete class
implementing this interface. The class Thread also implements the interface
Runnable. Table 20.1 gives a bird’s eye view of the Thread class architecture.
Method/entity Data types or Methods signatures
type
public data static int MAX_PRIORITY , MIN_PRIORITY ,
members NORM_PRIORITY;
Thread()
Thread(Runnable target)
Thread(Runnable target, String name)
Thread(String name)
Constructors Thread(ThreadGroup group, Runnable target)
Thread(ThreadGroup group, Runnable target, String name)
Thread(ThreadGroup group, Runnable target, String name,
long stackSize)
Thread(ThreadGroup group, String name)
int activeCount()
Thread currentThread()
void dumpStack()
int enumerate(Thread[ ] tarray)
Static methods boolean holdsLock(Object obj)
boolean interrupted()
void sleep(long millis)
void sleep(long millis, int nanos)
void yield()
On the other hand if a class was made thread-able by implementing the interface
Runnable, its object is to be passed to the constructor of class Thread as below.
Though all thread-able classes3 have a method called run, this method is NEVER
called directly to run a thread. Rather a method name start (from super-class
Thread) is called to execute the code contained in the run method. Therefore the
syntax for executing a thread is as follows:
3
We are calling the classes that can be used as threads as thread-able. However, since all threads
implement the interface Runnable, it is common also to call the Threads as Runnable. On the other
hand the term runnable is also used for threads, only when thread is available to execute its run
method. Therefore we introduce this new term thread-able, which indicates that the Java class either
inherited from Thread or implemented the Runnable interface.
The reason that run method is not called directly to start a thread execution is
because in that case a thread object no longer acts as a thread of control. Calling
run method directly makes it a sequential and non-threaded call. First we show an
example where we have two (counting the main, actually three threads) almost
independent threads in one program, which means that they are not sharing the
same program data or objects (Listing 20.2). Purpose of this Listing is to show the
syntactic elements of using Java threads.
4
A hyper-threaded CPU acts like two logically CPU in one physical CPU. Therefore it will act almost
like two CPU in one. Details of hyperthreading technology can be searched at www.intel.com
private static void test4() *********Starting the main *********Starting the main
{ thread!!!! thread!!!!
Thread Mom1 = new MomThread(); Running (not starting) the Mom Running (not starting) the Mom
System.out.println( thread. thread.
"Running (not starting) the Mom “ + Message 1 From: Mom Message 1 From: Mom
“ thread."); Message 2 From: Mom Message 2 From: Mom
Mom1.run(); Message 3 From: Mom Message 3 From: Mom
System.out.println("The priority of Message 4 From: Mom Message 4 From: Mom
Mom1 = " + Mom1.getPriority()); The priority of Mom1 = 5 The priority of Mom1 = 5
Runnable Dad = new DadThread(); Running (not starting) the Dad Running (not starting) the Dad
Thread Dad1 = new Thread(Dad); thread. thread.
System.out.println ( Message 1 From: Dad Message 1 From: Dad
JVM will run a high priority thread as long as it is “runnable”. Once it becomes
non-runnable, then it would run a lower priority thread. A thread is runnable as
long as it is not blocked in some way. We discuss what makes a thread non-runnable
soon when we discuss various mechanisms that can manifest in the life of a thread.
In test1, both Mom and Dad threads have same priority (of five) because they are
created by main method, which also has a priority of five. The Mom thread is
started first. In computer 1, all four loop iterations from the Mom thread are
finished first, and then the run method of Dad thread is executed. Notice that in all
cases except for the test4, signified by the output “**********Ending the main
thread!!!!” the main method ends while other two threads keep running. In
computer 2, the second logical CPU picks up the execution of Dad thread and the
output from two threads becomes intermixed, as both threads are executed in
parallel.
In test2 we set the priority for Mom thread at ten and that for the Dad thread at
two. However, we start the Dad thread first. As indicated from the result for the
computer1, starting low priority Dad thread first had no affect. The JRE picks up
the execution of high priority Mom thread first and finishes it, and then finishes the
execution of low priority Dad thread. In test2 the results on computer 2 show drastic
variations in results patterns. In run#1 Dad thread starts execution first, even
though it is a low priority thread. In run#3 Mom thread execution starts first. In all
runs, the output and execution of both threads is intermixed. A bit later we would
In test3, the priorities of Mom and Dad threads are same as they were in test2.
However, this time we start the high priority Mom thread first. The output on
computer 1 is identical to test2. JRE starts the high priority Mom thread first and
then finishes the low priority Dad thread. For computer 2 the output from Mom
thread always starts first, and then the output from both threads gets intermixed,
showing some parallel processing.
In test4, we do not call start method to start the thread execution. Rather we call the
run method directly for both threads. Doing so results in a non-threaded sequential
execution of all program code lines and results for both computers are identical.
Thread Scheduling
When JVM needs to switch between threads of control it must use a scheduling
algorithm to do so. There are two types of scheduling algorithms in vogue. These
are:
• Pre-emptive Scheduling, and
• Cooperative Scheduling
Older Java Runtime environment (JRE) provided by Sun used only so called
“Green Threads5”. Use of green threads allowed multithreading at the application
level, where JRE and user program managed the thread scheduling. However, to
operating system JRE is just one process. Therefore if machine has multiple CPU’s,
the green thread implementation could not take advantage of running your Java
application on multiprocessors simultaneously (thus achieving true multitasking
and parallel processing). In that case multithreading would speed up only those
Java applications, where one or more threads were blocked for long time or were
waiting for user input.
Sun realized this limitation, and made improvement in later JVM implementations,
where a multithreaded Java application could actually use thread scheduler
available on the operating system. Such threads are called native threads (or kernel
threads). For example, Sun’s Solaris operating system allows multiple CPU’s. One
can run a multithreaded Java application on Solaris with improved speed by using
its multiple CPU’s. For a Java program to use the native threads for an OS requires
a binding between “user or application threads” and operating system “native
threads”. Figure 20.3 shows schematics of such binding.
Or
native
threads
FIG. 20.3
In above Figure, the tasks one, two and three contain one or more threads in various
user programs running on the computer. The lightweight process resulting from
threads binds to kernel threads, which are threads at the operating system level.
Then these kernel threads bind to various CPU’s on the computer. One can debate
5
Green threads use so called fixed priority scheduling, where a threads are executed based on their
priority.
It is clear now that pre-emptive scheduling has the advantage of not hogging CPU
entirely (the way cooperative scheduling does). One may then wish to adapt pre-
emptive scheduling for the threads in their Java application, which would allow
time slicing various thread executions. Before we discuss thread scheduling further,
we shall learn some more details about life cycle of threads and events that can take
place in their life.
Figure 20.4
A thread can have following states: Thread can become runnable
1. New thread again by elapse of sleep time,
2. Runnable or yielded by being notified that wait is
3. Not Runnable (non-runnable) over, or when I/O is over.
4. Dead
The thread is in new state just after the constructor call has been made to create it.
The events in thread’s life are changes in its state that are brought about by calling
one of its methods or sending a message to it. For example:
1. A new thread becomes runnable by calling its start method.
2. A thread becomes dead when it’s run method exits. In older Java
implementation a stop method could be called to kill a thread. However, the
use of stop was considered unsafe; therefore stop has been deprecated now.
In current technology a thread must plan its own death by gracefully exiting
from its run method.
A thread can go back and forth between runnable and non-runnable states. The
escape routes from non-runnable to runnable states depend upon the process by
which the thread got into non-runnable state in the first place. For example:
1. If a thread became non-runnable because it was put to sleep by calling sleep
method, then time specified by sleep method must elapse for it to become
runnable again.
2. If a thread was made non-runnable by calling its wait method, then it could
become runnable after another object notifies it that wait is over and wait
condition has been satisfied. This notification is sent by using methods notify
or notifyAll. Understand that methods wait, notify, and notifyAll are final
methods from Object class ready for use.
3. If thread becomes non-runnable because it was blocked for I/O, then it
becomes runnable when I/O block is over.
Thread.currentThread().sleep(millis);
Above modification would make each thread sleep for 5000 milliseconds at the end
of one loop iteration. Table 20.3 shows the results for the test methods test1, test2,
and test3 for the STSP machine. The time slicing and parallel processing that was
missing earlier is now induced.
Test method (See code in Table 20.2) Typical output from STSP machine
test1 *********Starting the main thread!!!!
Starting the Mom thread.
Starting the Dad thread.
**********Ending the main thread!!!!
Message 1 From: Mom
Mom thread going to sleep.
Message 1 From: Dad
Dad thread going to sleep.
Under normal examination, the above method works fine as it ascertains that
withdrawal is not done if balance is not equal or higher than amount being
withdrawn. Now imagine the situation that two threads – one initiated by the
customer to withdraw money, and other by the bank to deduct monthly fee are
initiated at the same time. Assume that at that time the balance is $25. The thread
that withdraws the money wishes to withdraw $20 from it, and the thread that needs
to charge a $20 monthly fee also needs to deduct the same amount. Assume that
program is running on a STSP computer, and the following happens. The customer
money withdrawal thread performs the following check:
if (25>=20)
At that instant the pre-test condition is true, thus customer thread enters the block
under the scope of if condition. However, assume that before customer thread can
actually set the balance down to $5 , the monthly fee thread tests the pre-condition
and still finds it true and gets the permission to execute the code inside the if block.
In this case the timing of both threads is arranged such that both of them would get
to deduct $20 from the balance, thus leaving the balance of -15, which would violate
the invariant of the bank account class. (You would recall from earlier chapters, the
invariant for bank account class is that balance can never become negative). This
condition in software, where the state of an object or other class variables is
With respect to our discussion of withdraw method, what is needed to prevent this
invariant violating situation and racing is to arrange the action of threads using the
bank account object that while one thread is using the method withdraw, the object
is “locked” to all other threads, thus allowing the withdraw method to run to
completion. Java allows this locking by using the keyword synchronized in the
header of a method. Thus the method withdraw must be modified as follows:
The classes Customer and AccountManager both extend the Thread class, and have
BankAccount as the private datum. The constructor for both takes a BankAccount
object as argument, and initializes the class datum to it. The run method of both
classes calls the withdraw method on its BankAccount object, and in each case tries
to withdraw $20 from the balance, and then print the balance after the call to
withdraw method.
To shape the program output better, we make slight modifications to the run
methods of both Customer, and AccountManager classes as shown in Listing 20.4.
public class Customer extends Thread
{
//Rest of code is identical to Listing 20.3B. Modified run method is shown below
public void run()
{
if(Account.withdraw(20))
System.out.println("From Customer: " + Account);
else
System.out.println("Withdrawal failed");
}
}
Only one thread can call the synchronized method on an object at a time, and all
others are blocked in the interim. However, there are no such limitations placed on
the non-synchronized methods of an object. If an object has more than one
6
Purists however insist that locks and monitors are different things.
Static methods can be declared synchronized even though they only deal with local
variables and static class members. For example there is a design pattern called
singleton. The characteristic of a class that adheres to singleton pattern is that in
one program execution only one of its instances can exist. For example there was
only one Elvis Presley, therefore class Elvis must be written in such a way that never
two or more instances of Elvis be created in a program. Listing 20.5 shows a way of
doing that.
public class Elvis
{
private static Elvis Instance;
private Elvis()
{
//constructor code
}
public static Elvis getElvis()
{
if (Instance == null)
Instance = new Elvis();
return Instance;
}
}
//Listing 20.5
Now imagine the following scenario: the first thread calling getElvis, testing the if
condition would find Instance to be null, as all class level object references are
initialized so. Therefore this thread will get inside the if block to execute the code to
create only one Elvis instance that should be. However similar to BankAccount case,
if timing of two threads calling the getElvis method is arranged such that before
first thread can execute the code line
Instance = new Elvis ();
another thread also calls getElvis and tests if condition inside it and finds it to be
true and gets the permission to execute the code in the scope of if block. Then
impossible would take place. We would have two Elvis, instead of one-and-only-one
Elvis. Making the method getElvis synchronized would solve this problem. Thus the
correct signature of method getElvis must be:
How does JRE locks the call to synchronized getElvis method as there is no object to
lock? When the class-loader loads the class Elvis during the call to getElvis, it would
create a java.lang.Class object describing the class Elvis on the fly. The thread
calling the synchronized getElvis would get the monitor for that Class object which
was created by class-loader. Only one synchronized static method can be called for a
class by a thread at a time. In this sense the behavior of synchronized static and
instance methods is identical. Monitor used to manage synchronized execution of
static methods is different from the one used for instance methods. Therefore it is
perfectly possible for two threads to execute a synchronized static method and
instance method at the same time.
7
We would admit that it would be hard to imagine that any one would write such bad code.
However, in defensive programming one must think of all possibilities.
8
It has been suggested that synchronized methods may be slower by a factor of 100 compared to
their non-synchronized version.
9
For more details read “Double-checked locking: Clever, but broken” in Java World February 2001
or search www.google.com with query “double- checked locking”.
while ( ! the_condition_I_am_waiting_for )
wait( );
synchronized (The_Object){
while ( ! the_condition_I_am_waiting_for )
The_Object .wait( );
}
If synchronization is being done for a class level monitor to synchronize the access to
the static members, then The_Object is the Class object for the class. getClass is an
instance method inherited from java.lang.Object super class that returns the Class
object for a class. For example if we need to call the wait method inside the
synchronized block in Listing 20.6D, we can do it as follows: (Listing 20.6E).
In order to liberate the thread frozen inside the wait loop, two things must happen.
1. Another thread must make the pre-test condition (balance < amount) to
evaluate to false. In our case it means that there must be a thread that
executes a method to transfer money from the savings to checking account or
deposit money into it.
2. The thread that was waiting must be “notified” that its wait is over, and it
could get the monitor back to execute rest of the withdraw method on the
object from which it was frozen out earlier. This notification can be made by
calling one of the methods notify and notifyAll– both inherited from class
java.lang.Object (Table 20.5).
FIG. 20.7
The Listing 20.9A shows the source code for the class BankAccount.
00007 public class BankAccount
00008 {
00013 private String Str1 = ", new balance is ";
00017 private double balance;
00021 public BankAccount()
00022 {
00023 this(0.0);
00024 }
00030 public BankAccount(double amt)
00031 {
00032 balance = amt;
00033 }
00034
00039 public synchronized void deposit(double amount)
00040 {
00041 if(amount<=0)
00042 {
00043 notifyAll();
00044 return;
00045 }
00046 System.out.print("From " + Thread.currentThread().getName()+
Extends BankAccountOperations
Fig. 20.8A
Fig. 20.8B
Fig. 20.8C
The class DepositThread is structurally alike the class WithdrawThread. Super-
class BankAccountOperations defines the protected data members account, amount,
DELAY, and REPITITIONS, common to all thread sub-classes. Table 20.6 gives the
summary of data members for super-class BankAccountOperations.
Customer class
The Customer class is designed so that a BankAccount customer can make
withdrawals, deposits, and transfers through a menu driven interface. When
withdrawal is being made, an overdraft protection is applied automatically. Figure
20.9 shows the high level diagram for Customer class.
Figure 20.9
The class Customer has one data member account, which is of type BankAccount.
The constructor takes a BankAccount type object and initializes account equal to it.
The menu method provides a menu driven interface to carry out various banking
activities. Listing 20.9F gives the source code for the class Customer.
00006 import java.io.*;
00015 public class Customer
00016 {
00021 private BankAccount account;
00023 public Customer(BankAccount act)
00024 {
00025 account = act;
00026 }
00027
00032 public void menu()
00033 {
00034 boolean ok = true;
00035 do
00036 {
00037 System.out.println( "From " + Thread.currentThread().getName()+
00038 ": [W]ithrdaw, [T]ranfer, [D]eposit , [P]rint balance or [E]xit?");
00039 BufferedReader BR = new BufferedReader(
00040 new InputStreamReader(System.in));
00041 String Input = "";
00042 try
00043 {
00044 Input = BR.readLine();
00045 if(Input.startsWith("W")||Input.startsWith("w"))
00046 {
00047 System.out.print("From " + Thread.currentThread().getName()+
AccountManager class
The class AccountManager performs a single activity of deducting monthly fee.
Figure 20.10 shows the high level diagram for this class.
Figure 20.10
The class data members Account is the BankAccount on which the
AccountManager needs to operate. The fee data member is the static data which has
the monthly fee to be deducted at the end of the month. The constructor takes the
BankAccount object and sets the class level Account equal to it. The method
deductMonthly fee creates TransferThread and WithdrawThread objects to
accomplish the deduction of monthly fee and transfer money from savings if needed.
Listing 20.9G shows the source code for the AccountManager class.
00011 public class AccountManager
00012 {
00013 private BankAccount Account;
00014 private static double fee = 20;
00016 public AccountManager(BankAccount Act)
00017 {
00018 Account = Act;
00019 }
00020
00021 public void deductMonthlyFee()
00022 {
00023 System.out.println("From " +
Thread.currentThread().getName() + ": Deducting monthly fee. If the balance is below "
00025 + fee + " then a transfer would be made from savings account.");
00026 WithdrawThread WT = new WithdrawThread(Account,fee);
00027 double val = Account.getBalance();
00028 double amt_trn = fee - val +1;
00029 TransferThread TT = new TransferThread(Account,amt_trn,1);
00030 WT.start();
00031 TT.start();
You would appreciate now that synchronization is a powerful tool. By using the
thread synchronization, we were able to automate the overdraft protection in our
bank account simulations. While without synchronization, some modern software
Synchronization deadlocks
Excessive synchronization may cause deadlocks. What are deadlocks? Deadlocks
are blocked processes that can never be unblocked. One reason for this condition is
that threads in a deadlock set wait for a process that only another thread from the
set could execute. Unless the software is designed to recover from deadlocks, it will
hang the program or system using it. You would recall that in the
transferFromSavings method of our BankAccount class, we were only able to do one
way transfers i. e. from savings to checking. Imagine that you would like to write
just one transfer method, which can take the following three arguments:
1. From_Account – The account from which the money is to debited.
2. To_Account – The account into which the money is to be credited.
3. amount – Amount to be transferred.
The header of such generic transfer method can be written as follows:
You would like to ascertain that while method transfer is in execution, both
From_Account, as well as To_Account objects are locked by the same thread, so
that state of both accounts is not altered by another thread. In that case we may
wish to write the body of transfer method as follows (Listing 20.10A).
public void transfer (BankAccount From_Account, double amount,
BankAccount To_Account)
{
synchronized(From_Account)
{
synchronized(To_Account)
{
// Make sure that there are enough funds in From_Account
// Debit the From_Account by amount
// Credit the To_Account by amount
}
}
}
//Listing 20.10A
Now imagine that two threads are trying to use the method transfer at the same
time. (Notice that method transfer is not synchronized, so two threads can call it at
the same time). We create two BankAccount objects as follows:
It could happen that one thread is calling the method transfer with arguments in the
following order:
transfer (Savings, amount, Checking),
while the other thread is calling it with the following argument list:
transfer (Checking, amount, Savings).
The sequence of events could be such that first thread would acquire the lock to
object Savings. However before it can acquire the lock to Checking (the second lock
needed in the method transfer), it is entirely possible that second thread may
acquire the lock to object Checking. (This because for second thread Checking
becomes the From_Account whose lock it must acquire first). When this happens
then two threads are deadlocked. The first thread has the lock on object Savings
and it waits for the lock on Checking, and the second thread does the reverse. Both
threads are waiting for each other to release the lock but neither does it. Of course
in this case the solution is simple: do not use synchronization blocks. Rather make
the method transfer as a whole synchronized. It would also appear that many
potential deadlocks would be prevented if you would write methods in a manner
that does not require locking more than one object at a time. The probability of
deadlocks increase in direct proportion to the number of objects one needs to lock.
If one has to use multiple locks then one needs to define an order in which the
threads would acquire the locks to the objects. Listing 20.10B shows as to how one
can define a lock order to avoid deadlocks.
1 public void transfer (BankAccount From_Account, double amount,
2 BankAccount To_Account) throws InterruptedException//because of withdraw method
3 {
4 BankAccount First_Lock = null;
5 BankAccount Second_Lock =null;
6
7 if(amount<=0)//negative or zero amount is not transferred
8 {
9 notifyAll();
10 return;
11 }
12 else if(From_Account.getAccountNumber() == To_Account.getAccountNumber())
13 {
14 // Cannot transfer to the same account
15 notifyAll();
16 return;
17 }
18 else if(From_Account.getAccountNumber() < To_Account.getAccountNumber())
19 {
20 First_Lock = From_Account;
21 Second_Lock = To_Account;
22 }
23
Now imagine that two thread that calls transfer method makes a call such as:
transfer (Savings, amount, Checking); //by first thread
and
transfer (Checking, amount, Savings); //by second thread
Then following two possibilities exist.
1. If savings account number is smaller than the checking account number then
first thread will acquire lock to Savings first and then to Checking. Notice that in
this scenario the else block (L20.10B#24-28) would be true for the second thread.
It will also try to acquire the locks in the same order i. e. Savings and then
Checking. However, the deadlock would be avoided because either lock to
Savings would be available at that time or it would not be.
2. The second possibility is exact mirror image of the first one. If Savings account
number is larger than the Checking account number then the lock order is
Checking and then Savings.
class ArrayWithLockOrder
{
private static long num_locks = 0;
private long lock_order;
private int[] arr;
public ArrayWithLockOrder(int[] a)
{
arr = a;
synchronized(ArrayWithLockOrder.class) {
num_locks++; //Increment the number of locks.
lock_order = num_locks; //Set the unique lock_order for
} //this object instance.
}
public long lockOrder()
{
return lock_order;
}
public int[] array()
{
return arr;
}
}
Java networking is a technology that enables one to write programs that would
allow one to connect to various computers on the Internet, on a local area network
(LAN), or on an intranet1. Computers connected to the Internet for the purpose of
serving clients are called servers and they may perform one or more of the following
services:
• Publishing content on web pages and on web sites,
• Provide web service such as banking, entertainment, and knowledge base,
• Provide data, software, and other kind of files,
• Provide communication assistance such as e-mail, text chat, voice chat,
telephony, and video conferencing,
• Provide electronic shops and e-commerce channels.
Java libraries are so well designed for the Internet and for networking between the
computers and devices that it is now said “Java is the language for the
Internet”. Networking is the name given to the process by which computers or
other devices communicate with each other. In order for the computers to
communicate with each other, we can connect them directly. This technique is called
point to point connection. This can work if number of computers that need to
communicate with each other is small. When large numbers of computers need to
communicate with each other then they are connected to a network. Figure 21.1
shows a schematic picture of a generic network.
1
Intranet is a network of computers that uses the same principles that Internet does. However unlike
Internet the intranet is a private network. Intranets are built and used by corporations and entities
for their own use.
By now you can appreciate that Internet facilitates the communication between
computers which may have vastly different hardware and operating system (OS).
For example when a client computer requests a web page from a server, irrespective
of the brands and OS of client and server the request is fulfilled. Therefore, the
designer of Internet had to come up with a scheme that would allow communication
between any two machines, as long as they fulfilled some basic requirements. The
OSI Model
OSI model divides the communication process in seven layers. The layered structure
in OSI model is analogous to the modular structure adapted in designing modern
software. Once the function of each module is defined, the implementation can be
done in many different ways. Same way, once the function and service provided by
each layer is defined; the hardware and software implementation can be done in
many different ways. Dividing the task of communication in layers also facilitates
management of complexity of the network. Figure 21.2 shows the various layers in
the OSI model that participate in computer2 networking. This figure shows seven
layers, however in some applications the number of layers can be as low as five or
four.
Internet
applications
combine
these 3
layers in
one and call
them
application!
FIG. 21.2
Data from the source computer flows downward from the application layer through
each layer until it reaches to the physical layer or physical link between two
computers. Then on the receiver computer data travels upwards from physical layer
2
We are using the word computer in this chapter in a more generic sense. The fact is that any two
devices can be made to network with each other.
Our Figure 21.2 does not give numbers to the OSI layers; however it is customary to
number them from bottom to top in ascending order, thus physical layer being
number one and application layer being number seven. (This is why many times you
would hear networking professional referring to some layer number, when they
have problem with that particular layer in their network). The Internet applications
combine the layers five, six and seven into one layer and call this collection as the
application layer (thus reducing number of layers to five). It is hard for people to
remember the names of all the layers. Therefore many devices are floating around
to memorize them. For example “Please Do Not Teach Students Poor Acronyms”,
where the first alphabet of each word is also the first alphabet of each layer (P =
Physical, D = Datalink, N = Network, T = Transport, S = Session, P = Presentation,
A = Application).
We now briefly describe the service provided by each layer in OSI model. Table 21.1
gives the laundry list of service each layer must perform and example(s) wherever
we can give one.
Layer Layer Service performed Example(s) of
Number Name service
7 Application Gets the data from the source or Web page request,
sends data to the destination. e-mail, files
transfer requests.
6 Presentation Prepares data in the format that it Conversion from
can be transported on the network Unicode to ASCII
and can be understood by the or ASCII to binary
receiver.
5 Session Sets up an active connection Shopping on an e-
between source and destination, commerce site
maintains it, and when session is
over tears it.
4 Transport Manages the flow of data between If part of a
the source and destination and message is lost, it
control the quality of data can be resent.
communication. Handles the
addressing of the messages.
First of all let us describe as to how the IP works. The source computer would send
data to destination that would be broken up in “packets”. The data packets received
at the destination computer are assembled back into the original data form. The
way in which packetization is done and the address headers are added to them is
shown by the Figure 21.4.
Figure 21.5 shows a trace of route an IP packet would travel from Southern
California from my computer to the web site of Guardian newspaper
(www.guardian.co.uk) in England.
When one needs to ascertain that ALL packets reach their destination, more robust
protocol is needed. It is similar to the fact that when you need to make sure that
your letter must reach the destination, you would pay post office extra money and
send it certified or registered. TCP is the implementation of transport layer which
has aforementioned robustness. TCP ascertains that all packets sent by source are
received by destination. It sends a packet and waits for an acknowledgement from
destination that packet was received. Lost packets are re-sent. TCP keeps a copy of
a sent packet till it receives the acknowledgement from destination that packet was
received.
3
Some packets are inevitably lost in the transmission due to so called transmission losses.
Sockets
Using sockets is actually much easier than defining them. In this sense trying to
define a socket is like blind men grabbing different parts of an elephant and
describing elephant according to what they grabbed on to. The person grabbing the
tail said that elephant is like a rope, whereas the person grabbing the leg said that
elephant is like a pole. Let us hope that we can do better then those unfortunate
blind men. Sockets are to communication between client and server what I/O system
is to the program that wishes to communicate with a file and file itself. When a
client and a server must communicate a process must exist on each computer to do
so. If we would use TCP/IP, then this communication process would piggy-back the
process on client and server. Creation of this communication process or interface
generically embodies sockets. For example the steps in creating and using a socket
could be:
• Creation – Open a socket.
• Reading & Writing – Receive data from and send data to socket.
• Destruction – Close socket.
Both in Java and in Berkeley BSD flavor of UNIX (originator of sockets) as well as
in other operating systems, API’s are available to send and receive data through
4
To understand the impact of client server architecture we have to go back to the era of main frame
computing where all the processing was done by the server and client was just a dumb terminal
which unlike today’s desktop of client computer, had no real processing power or software.
5
Databases usually follow a three tier architecture which apart from client and server software’s
uses an intermediate software layer called middleware.
The Host Name is the string providing the name of the host with whom a Socket
communication is intended. The host name can be a numerical IP address or a
domain name. For example the host name (domain name) www.photo.net would
automatically be translated by the domain name server, to the IP address:
216.127.244.133
The string in Socket class constructor above could either be the domain name or
numerical IP address for the host. The port number is the integer bound to the
program on host which would facilitate the communication with respect to the
application being sought (See Figure 21.3). The above constructor call can throw the
following three exceptions, of which first two are checked type. Therefore the
constructor call must be embedded in proper try catch blocks:
Socket class has many other constructors, whose details are given by the API for
that class. If exceptions are not thrown then constructor would create a Socket
object which can be used to read and write those files on the server which exist and
for which the read/write permissions are available, or perform other activities
permitted by the program on server side. Sidebar 21.1 gives more information about
IP addresses and domain names.
The above documents define 15 HTTP methods. Table 21.4 gives a summary of
some HTTP methods. Understand however, that web server administrator may
disallow any methods to the client that are deemed unsafe or security hazards. On
the other hand, the authenticated users may be allowed to use them based on the
degree deemed necessary by the server administrator.
Method Name (All Description
upper case)
GET Used during web browsing to get documents
POST To submit data back to the server when filling out web forms
OPTIONS Used to query web server about its capabilities provided to the
client.
TRACE Used to trace the path of the client request through fire walls,
and proxy servers.
HEAD Used to get the header information for a resource
PROPFIND
PROPPATCH
MKCOL
DELETE Provides a way to delete the document from the server
PUT Stores the content body at the location specified in the request
COPY
MOVE
LOCK
UNLOCK
SEARCH
Table 21.4
HTTP methods are used in the request that client makes of the server. The general
syntax of the request is as follows:
6
What is important in real estate? Location, location, location. What is important in writing HTTP
based applications? Understand HTTP, understand HTTP, understand HTTP.
7
RFC stands for request for comments. In early days of Internet development the IETF created
specification documents and asked the community to make comments on it. The final form of the
documents retained original name which was given a RFC title and a number.
Using the GET method, the generalized syntax above would boil down to:
GET Path to the resource requested / Resource file name HTTP / Protocol #
\ 2 line feeds
When using socket programming the path to the resources requested is the web
address of the server and is not needed in the string making the GET request. Thus
all you need is the resource file name. Protocol number can be 1.0 or 1.1 etc.,
depending upon the implemented HTTP by the web server. Based on how the GET
request is sent, additional line feeds may be needed. As an example if I needed the
file index.html from a web server whose name and port number has already been
passed to the Socket constructor, then my GET request string to get the file
index.html would look like below:
When using URL’s (rather than socket programming)8, path to the resource
requested would include the web address and other path details to the requested
resource.
After the GET request is made, the server may do two things:
• It may honor the request and provide the resource requested. If something
goes wrong in fulfilling the request, it may also provide an error code.
• It may decline the request.
Understand that in HTTP, the process is over after the sever has fulfilled or
declined the request. Even if the Socket object on client side is still alive, it would
have to make another request and server would have no memory of any previous
requests made by the same client socket. In this sense it is said that HTTP is a
stateless protocol as it does not maintain any information from the previous session
with the same client. (Some servers may put cookies in your web browser to retain
some of the information from previous sessions. Cookies are small text files).
8
URL = Uniform Resource Locater
The Socket class has two methods getOutputStream which returns an object of type
OutputStream and getInputStream which returns object InputStream. Figure 21.6
reproduces the Java API description of these instance methods.
If this socket has an associated channel then the resulting output stream delegates all of
its operations to the channel. If the channel is in non-blocking mode then the output
stream's write operations will throw an IllegalBlockingModeException.
Returns:
an output stream for writing bytes to this socket.
Throws:
IOException - if an I/O error occurs when creating the output stream or if the
socket is not connected.
///////////////////////////////////
public InputStream getInputStream() throws
IOException
Returns an input stream for this socket.
If this socket has an associated channel then the resulting input stream delegates all of its
operations to the channel. If the channel is in non-blocking mode then the input stream's
Under abnormal conditions the underlying connection may be broken by the remote host
or the network software (for example a connection reset in the case of TCP connections).
When a broken connection is detected by the network software the following applies to
the returned input stream :-
• The network software may discard bytes that are buffered by the socket.
Bytes that aren't discarded by the network software can be read using
read.
• If there are no bytes buffered on the socket, or all buffered bytes have
been consumed by read, then all subsequent calls to read will throw an
IOException.
• If there are no bytes buffered on the socket, and the socket has not been
closed using close, then available will return 0.
Returns:
an input stream for reading bytes from this socket.
Throws:
IOException - if an I/O error occurs when creating the input stream, the
socket is closed, the socket is not connected, or the socket input has been
shutdown using shutdownInput()
FIG. 21.6
The OutputStream object returned by the method getOutputStream can be
converted into a PrintWriter object for our Socket (Sock), which can then send our
GET request to the server as simply as the PrintWriter can write to a file. This is a
two step process. First step requires that we pass the OutputStream object returned
by getOutputStream method to the constructor of class OutputStreamWriter, and
then pass the object thus constructed to the constructor of class PrintWriter. Figure
21.7A shows the schematics of this process.
www.photo.net xyz
9
URI means uniform resource indicator.
Reason for that is because no resource names xyz exists on the server. Status code
400 would be used if client made a request that is not understood by the server. One
example of this is when there is an error in the IP address; For example the
command line arguments:
www.phto.net index.html
10
Port scanners are the programs that scan Internet for unguarded sockets and Internet connections
that can be exploited for un-authorized entry to the system. Port scanners do have legitimate uses as
well.
FIG. 21.9
For each client request, server must perform activities enclosed in the blue bordered
oval. To limit the scope of this exercise we confine ourselves to the types of files that
server can send to the followings: html, jpg, gif, and plain text. In previous example
when we developed client side application using socket, we did not have to worry
about the details of what server did when it received a request. Now we explain
those details. When server gets a valid client request, it creates a “sever side socket”
and a new port to serve this client. This frees the original port to serve next client.
This new port and its associated socket fulfill the client request, after which the
former two are torn down. Since HTTP is a stateless protocol, this process repeats
again, even if the same client sends a new request right after fulfillment of its
previous one. Java provides a different socket class, called ServerSocket to create a
socket on the sever side. This server side socket is created by making the constructor
call of the following type:
In above call, port is the port number integer on which sever will listen to the client
requests. For this application, in order to choose a non-standard port number, we
choose it to be a number above 102311 (must be below 65536). This constructor
throws an IOException (which is a checked exception), requiring that the
11
On UNIX server one cannot choose a port number less than 1024 without the authorization from
super user.
If there is a security manager, its checkListen method is called with the port
argument as its argument to ensure the operation is allowed. This could result in a
SecurityException.
Parameters:
port - the port number, or 0 to use any free port.
Throws:
IOException - if an I/O error occurs when opening the socket.
SecurityException - if a security manager exists and its checkListen method
doesn't allow the operation.
See Also:
SocketImpl, SocketImplFactory.createSocketImpl(),
setSocketFactory(java.net.SocketImplFactory),
SecurityManager.checkListen(int)
FIG. 21.10
Once the constructor call above provides the ServerSocket object, we can create a
Socket object to serve the client by calling the accept instance method of the
ServerSocket class as follows:
The accept method listens for a connection to be made to fulfill the impending client
request and finally creates a new Socket object (Serve_Client in this case)
materializing the connection with the client. Figure 21.11 reproduces the Java API
description of accept method.
public Socket accept()throws IOException
Listens for a connection to be made to this socket and accepts it. The method
blocks until a connection is made.
Returns:
the new Socket
Throws:
IOException - if an I/O error occurs when waiting for a connection.
SecurityException - if a security manager exists and its checkListen method
doesn't allow the operation.
SocketTimeoutException - if a timeout was previously set with setSoTimeout
and the timeout has been reached.
IllegalBlockingModeException - if this socket has an associated channel, the
channel is in non-blocking mode, and there is no connection ready to be accepted
See Also:
SecurityManager.checkAccept(java.lang.String, int)
FIG. 21.11
The beauty of using ‘accept’ method is that it blocks the execution of its own code,
until an actual request is received from the client. In this sense it works almost like a
GUI listener. The method ‘accept’ can throw many exceptions; however it only
broadcasts the IOException in its header. The reason for that is that
Since each client request must run in its own thread, we write a class called
HttpRequest, and each object of this class would be used to serve one client. The
structure of HttpRequest class is shown by the Figure 21.12.
FIG. 21.12
This class has a constructor that takes a Socket object as an argument. This
argument would be provided by the return value from the accept method of the
ServerSocket object, when an actual client request is received. Since each object of
HttpRequest must run in its own thread, this class implements Runnable interface
and provides the implementation of run method. Method contentType,
processRequest, and sendBytes are helper methods. Run method calls the
Depends
upon
FIG. 21.13
Lines going from icons into the class HttpRequest show class members which are
also shown in Figure 21.12. Red arrows (connecting icons) show as to which member
depends on which other member. Sock is used by the constructor and
processRequest, so both of them depend upon Sock. CRLF is used only by
processRequest. processRequest is called by run. In turn processRequest calls
methods contentType and sendBytes. Relationships between various members of
class HttpRequest is now becoming clear. ‘run’ method will be called when a thread
of class HttpRequest would start. To process client request, the run method calls
processRequest which needs to make a determination as to what kind of content is
requested by the client. It does that by reading client request and parsing it for the
type of file client asked for. (For example if client asked for an html file, that file
extension would be included in the client request string). Method contentType takes
the client requested file name and returns its type as a String. Table 21.6 gives the
concluding summary of class HttpRequest.
Field Summary For class HttpRequest
(package private) CRLF
static java.lang.String A carriage return and line feed string used by method
processRequest.
http://URL/FileName
Therefore we just need to drop the slash from the second token in the request string
in order to retrieve file name or path to filename. Therefore after tokenizing the
‘requestLine’ (L21.2#72), an empty call is made to method ‘nextToken’ to discard
string ‘GET’ (L21.2#73). Next call to ‘nextToken’, gives us the file name string with
slash appended in front (L21.2#74). We confirm that and extract the file name by
dropping the slash in front by calling the substring method of String class, and
dropping the first character in the String (L21.2#76-77). Notice that this technique
requires that requested file be in the same directory in which the class file with
12
Understand that URL is not part of requested resource.
If ‘fileExists’ is true, then statusLine is set to string "HTTP/1.0 200 OK" + CRLF
(L21.2#98). The ‘contentTypeLine’ string is set to reflect the type of content file has.
Portion of this string is constructed by the return value from the method
contentType, which takes the file name string as argument and returns a string
indicating its content type (L21.2#99). If the file does not exist then the else block is
executed (L21.2#101-106), which sets the values of strings to be published to the user
to give the error code 404 indicating that file was not found on the server. Instance
method writeBytes of class DataOutputStream is used to write the strings
‘statusLine’ and ‘contentTypeLine’ to the client (L21.2#109 & 112). We only need to
write the file to client if the file exists. Therefore, under the scope of if statement
testing the value of boolean variable ‘fileExists’, we call the method ‘sendBytes’ that
takes ‘fis’, and ‘Data_OS’ as arguments (L21.2#118-122) and writes the file to the
client. If ‘fileExists’ evaluate to false then the else block is executed (L21.2#123-126),
which informs the user that file is not found.
Method sendBytes
Method sendBytes takes the FileInputStream object bonded to the file on the server
that must be written to that client to which the second argument OutputStream is
connected (see Figure 21.14). The method simply reads the file on the server byte-
by-byte and then writes it to the client. However, for efficiency purpose, we do not
write to the client byte-by-byte. Rather we build a buffer of 1024 bytes. This buffer
is first filled with bytes from the input file, and then it is emptied as it is written to
the client. One version of read method of FileInputStream takes a byte array as
argument and fills the array with the data from the file being read (L21.2#168). If
end of the file is reached then the method returns an integer -1 value. Therefore the
file reading loop exits as soon as the end of file being read is reached. If end of file is
not reached then the read method returns the number of bytes pumped into the
buffer. The code in the scope of while loop uses the overloaded instance method
However, as soon as the client request is received, the above line is executed and a
Request object is created. Since Request is a Runnable, we pass it as an argument to
the Thread class constructor to create a Thread of control to fulfill the current client
request (L21.3#38). Then we call the start method of Thread TH, in order to execute
the run method, which from previous description, we know calls the processRequest
method to fulfill client request. The loop process continues unless an exception is
thrown or server is shut down.
Test Results
We test our web server locally, so that client and server both reside in the same
computer. In this situation the IP address of the server is:
http://localhost:portNumber
Assuming that we wish to get a file from the server called index.htm then complete
client request string using a web browser would be (in this case),
http://localhost:2468/index.htm
While server is running, we can launch any of our browsers and type the above
address in it to display the file index.htm. Make sure that you run the application
from command line, as some times the default directory that an IDE like Netbeans
would look for is different from the folder where main class is located. In this case it
just so happens that in file index.htm I placed html format of my Multithreading
lecture, and web browser simply displays that. Read sidebar 21.2 for comments on
servers written purely in Java.
Sidecar 21.2: Server Software Engineering and Java
Although most industrial strength servers, such as Apache (the most successful
server) are written in C, recent release of a purely Java based server called Jigsaw
by the w3 organization (www.w3.org) has proven that good quality web servers can
be written using Java. W3 organization cites following examples of using a pure
Java server:
• A multithreaded server that is portable
With the advent of Internet and HTTP protocol, servers around the world became
able to publish static web content for clients connecting from disparate geographical
locations. There was, however a problem with static web pages. For example a
weather reporting web site could not (with out difficulty) build a web page of
changing weather conditions every few hours and host it as an HTML file for the
client. Similarly the web site that updates stock quotes also could not update
changing prices by means of static HTML pages as often as the investors need it to
make buying and selling decisions. (People had to depend upon TV, radio, and stock
quote ticker devices for that). What was needed was a technology that can rebuild
the web pages as the client request or as the data to be displayed changed. Java
applets could in fact present information dynamically. Therefore early on there was
a tremendous enthusiasm for them (including their use in a technology called “push
technology”, which died rather quickly). Java applets however, are client side
technology and not as reliable as the server taking the control of updating the
information. What was needed was a layer of software between the client and HTTP
server, which can run programs on the server to generate web pages on the fly in
the light of fast changing data and customer request for it. This was first
accomplished by CGI (common gateway interface), in which a directory on the
server, cgi/bin became repository of programs to run, when a client request needed
the dynamic information. The program would get the information, generate an html
page on the fly and serve it to the customer. One example of this is as follows: Let us
assume that client is flying from Dallas to New York and needs to know current
weather conditions at the destination. The client would make a request to the
weather web site, the web site will run a cgi program to get the current weather
data, build an html page and display to the client.
The problem with cgi was that if 15 clients are asking for the same information at
the same time, the server had to fork a new process of the cgi program and serve the
clients. This became expensive in terms of server resources. (Imagine the overhead
of running 15 copies of the same program at the same time). Business to consumer
(B-to-C) web sites presented another new challenge. By now you know that HTTP is
a stateless protocol. HTTP does not remember anything about the client from the
previous session because serving each web page starts a new session. On an e-
commerce web site client may visit a web page, look at the products on it, put items
on their shopping cart and then move to next web page to do more shopping. How
Servlets and JSP are two faces of the same technology. Servlets either implement
interface javax.servlet, or extend a class that already does that. JSP pages have
HTML and Java code embedded in them, which are compiled into a servlet. Java
packages javax.servlet and javax.servlet.http contain necessary classes to write
servlets. The inheritance hierarchy of abstract class HttpServlet that is extended to
write servlet classes is shown by the Figure 23.1.
1
It is extremely saddening and maddening that all these robust e-commerce technologies (JSP and
ASP.Net) arrived after dot com crash, which slowed the growth of e-commerce to a crawl. In the
meantime the e-commerce vision promoted to customers turned bleak. This is perhaps a starkest
example of how over-hyped technologies do incalculable harm to prospects of building new
businesses and distribution channels.
Table 23.1 gives a summary of methods inherited by the class HttpServlet from its
super-classes (excluding the Object class).
Method Summary For class HttpServlet
protected doDelete(HttpServletRequest req, HttpServletResponse resp)
void Called by the server (via the service method) to allow a servlet to
handle a DELETE request.
protected doGet(HttpServletRequest req, HttpServletResponse resp)
void Called by the server (via the service method) to allow a servlet to
handle a GET request.
protected doHead(HttpServletRequest req, HttpServletResponse resp)
void Receives an HTTP HEAD request from the protected service method
and handles the request.
Table 23.1
For class MyServlet to do anything useful, it must override, at least one of the
following super-class methods:
• doGet, if the servlet supports HTTP GET requests
• doPost, for HTTP POST requests
• doPut, for HTTP PUT requests
• doDelete, for HTTP DELETE requests
• init and destroy, to manage resources that are held for the life of the servlet
• getServletInfo, which the servlet uses to provide information about itself.
You would recall that GET, POST, PUT, OPTIONS, TRACE, HEAD, and
DELETE are HTTP methods, whose brief summary we discussed in the chapter on
Networking. Therefore the HttpServlet class includes methods to handle all these
methods that may be embedded in the client request. Each such method is of type
doxxx, for example doGet, doPost etc.
Similar to applets, sockets, and threads, servlets also have a typical life cycle.
However, before we discuss that, we need to understand another concept called
“servlet container”. The servlet container is to servlet, what a browser is to a Java
applet. You would recall from chapter on Java applets that browser called the init
method to initialize the applet, start method to start it, stop method to stop it from
FIG 23.2
2
Older name for a servlet container is servlet engine.
3
See www.apache.org. At the time of this writing the specific link to the Tomcat page is:
http://jakarta.apache.org/tomcat/index.html
1. Throws a ServletException
2. Does not return within a time period defined by the Web server”
The second phase of a servlet’s life is service in which it can accept requests and
render responses to them (Figure 23.2). It does so through objects of two other
classes: HttpServletRequest and HttpServletResponse. This is the reason why you
see that ALL doxxx methods in Table 23.1 take these two object types as arguments.
doxxx methods however are called by the method service which is an overloaded
method (Table 23.1). Java API describes the public version of service method as
follows:
“service is called by the servlet container to allow the servlet to respond to a request.
This method is only called after the servlet's init() method has completed successfully.
The status code of the response always should be set for a servlet that throws or sends an
error. Servlets typically run inside multithreaded servlet containers that can handle
multiple requests concurrently. Developers must be aware to synchronize access to any
shared resources such as files, network connections, and as well as the servlet's class and
instance variables.”
Just like the Java applets are destroyed after browser is closed to dispose resources
used by them, servlets are also destroyed when it is removed from the container.
Container does that by calling the destroy method (Table 23.1). None of the
following methods: ‘init’, ‘service’, or ‘destroy’ need be called directly by the servlet
writer as the container does that automatically. Nor is there a need to override these
methods in the class extending HttpServlet.
http://java.sun.com/j2ee/1.4/download.html#nb
If in future this link is dead then you may go to general site java.sun.com and look
for Netbeans bundled with JSAS. (In fact Netbeans 4.1 would have Java System
Server application 8 or higher integrated into it). The download page would have
installation notes and release guide. It would be best to print this guide after the
We now proceed assuming that you successfully installed the Netbeans and JSAS.
First we show as how to build a servlet example. The following description applies to
Netbeans 3.6.
1. Start Netbeans IDE.
2. If you have any previous file systems mounted then un-mount them. Your file
systems tab should be clear (Figure 23.4A).
No files mounted.
FIG. 23.4A
3. For the illustration purpose we create a folder on our C directory called
J2EE.
4. Mount this file system in Netbeans. Right click on Filesystems and then on
mount/Local Directory (Figure 23.4B).
FIG. 23.4B
5. Then navigate to the folder J2EE and click on finish. (Do not open this
folder). Once it is mounted, it would look like Figure 23.4C.
FIG. 23.4D
7. Once you have done that the Filesystems node will change as shown in Figure
23.4E.
2. Node used to
write servlets
FIG. 23.4E
8. Netbeans creates an additional node which can be used to write servlets.
Right click on the node pointed by the bubble #2 in Figure 23.4E and then
click on New and then on Servlet (Figure 23.4F).
FIG. 23.4F
9. After last step a popup menu similar to the Figure 23.4G will open up.
Location of the
servlet java and class
files
FIG. 23.4H
11. Notice that the path in the location text field has changed automatically. This
text field gives you path to the folder where your servlet Hello.java would be
created. In the popup box in Figure 23.4H click on finish. (Clicking on next
would give you other options, which we are not ready to investigate yet).
Netbeans creates the servlet class Hello.java and fills in its method headers
and some code automatically. If you would now expand the node
C:\J2EE :/WEB-INF/classes fully, it would look like the Figure 23.4J
package net.gandhi.servlets;
import java.io.*;
import java.net.*;
import javax.servlet.*;
import javax.servlet.http.*;
/**
*
* @author authorised user
* @version
*/
public class Hello extends HttpServlet {
out.println("</body>");
out.println("</html>");
*/
out.close();
}
Servlets produce web pages by embedding HTML tags and content displayed by
them as strings passed as argument to the method println. In method
processRequest the PrintWriter object out is created by calling the getWriter
method of HttpServletResponse object response. This class inherits this method
from its super-class ServletResponse. The Java API description of getWriter
method is given in Figure 23.5.
public java.io.PrintWriter getWriter( ) throws java.io.IOException
Returns a PrintWriter object that can send character text to the client. The
PrintWriter uses the character encoding returned by getCharacterEncoding(). If the
response's character encoding has not been specified as described in
getCharacterEncoding (i.e., the method just returns the default value ISO-8859-1),
getWriter updates it to ISO-8859-1.
Calling flush() on the PrintWriter commits the response.
Either this method or getOutputStream() may be called to write the body, not both.
Returns:
a PrintWriter object that can return character data to the client
Throws:
UnsupportedEncodingException - if the character encoding returned by
getCharacterEncoding cannot be used
java.lang.IllegalStateException - if the getOutputStream method has already been
called for this response object
java.io.IOException - if an input or output exception occurred
See Also:
In Listing 23.1 if we uncomment the portion pointed to by bubble #1, we get the
basic headers in place to print an HTML page. Whatever we wish to display on our
web page must now be placed inside the tags <body> and </body>. Let us assume
that we wished to say hello to the user from our domain and print the day, date, and
time. The line saying hello would be composed as follows:
The above line gets printed on the web page served by our servlet called Hello just
the way a regular HTML page would.
In order to print day, date and time, would need to create an instance of class
java.util.Date and pass that to the method println. This is done by the following code
line.
Notice
the URL
FIG. 23.6
Notice the URL used by the browser. The IP address used is localhost:1168. This
shows port number to be 1168. However, JSAS may be shown to be running on a
different port in the Runtime tab in Netbeans environment. If you copy the above
web address into any other browser on your system, you would get similar results.
4
http://www.w3.org/TR/html401/interact/forms.html
</body>
</html>
<!—Listing 23.2A Æ
The HTML page created by the browser from Listing 23.2A is shown in Figure
23.7A.
FIG. 23.7B
Understand that since we wish to group all radio buttons together; they will all have
the same value (radio1) for the name attribute. In order to create check boxes, the
type attribute is given a value ‘checkbox’. Since user can check mark more than one
When the above HTML line is added at the location shown by the box#2 in Listing
23.2A, then the web page interpreted by the browser is shown by Figure 23.7C.
FIG. 23.7C
Finally we show the syntax for creating a button that user can click to submit the
data they typed or chose on the web form. To create a submit button for the input
tag the type is submit. The syntax is as follows:
When the above HTML tag is placed at the location shown by the box#3 in Listing
23.2A then the browser interprets the whole code as shown in Figure 23.7D.
FIG. 23.7D
Similarly one can add the status checked to all the check boxes that must be pre-
selected. The latest version of HTML also allows one to add tool tip text to all input
components. This is done simply by adding the attribute title and the tool tip string
as the value of this attribute. For example we may wish that when user places the
mouse over check box Kimchi, then tool tip shows the message: “ Click here if your
favorite food is Kimchi”, then the HTML tag to create Kimchi check box changes as
follows:
Figure 23.7E shows the tool tip created by adding the title attribute.
FIG. 23.7E
Listing 23.2B shows the HTML file Gandhi_index.html that we create to submit the
form data entered by the user to the modified servlet Hello.
<html>
<head><title>Home Page of Gandhi Software</title></head>
<body>
<input type =radio name='radio1' value='Pink' checked title='Click if your favorite color is pink'>
<Font color='black'>Pink </font>
<input type =radio name='radio1' value='Magenta' title='Click if your favorite color is Magenta' >
<Font color='magenta'>Magenta </font>
<input type =radio name='radio1' value='Blue' title='Click if your favorite color is blue'>
<Font color='blue'>Blue </font>
<input type =radio name='radio1' value='Green' title='Click if your favorite color is green' >
<Font color='green'>Green </font>
<input type =radio name='radio1' value='Cyan' title='Click if your favorite color is cyan' >
<Font color='black'>Cyan </fonr>
<input type =radio name='radio1' value='White' title='Click if your favorite color is white'>
<Font color='black' >White </font>
<input type =radio name='radio1' value='Orange' title='Click if your favorite color is orange' >
<Font color='orange' >Orange </font>
<input type =radio name='radio1' value='Yellow' title='Click if your favorite color is yellow'>
<Font color='black' >Yellow </font>
<input type =radio name='radio1' value='Burgundy' title='Click if your favorite color is burgundy'>
<Font color='black'>Burgundy</font><BR><BR><BR>
<B><U>Please checkmark all your favorite foods and or drinks from the list given below:
</U></B><BR><BR>
<input type =checkbox name = 'check1' value='kimchi' title='Click if your favorite food is Kimchi'>
Kimchi
<input type =checkbox name = 'check2' value='Felafel' title='Click if your favorite food is Felafel'>
Felafel
<input type =checkbox name = 'check3' value='Cheeseburger'
title='Click if your favorite food is Cheese Burger'>Cheese Burger
<input type =checkbox name = 'check4' value='Curry' title='Click if your favorite food is Curry'>
Curry
<input type =checkbox name = 'check5' value='PolishHam'
title='Click if your favorite food is Polish Ham' checked>Polish Ham
<input type =checkbox name = 'check6' value='Vodka' title='Click if your favorite drink is Vodka'>
Vodka
<input type =checkbox name = 'check7' value='Chowmin'
title='Click if your favorite food is Cowmin'>Chowmin<BR><BR>
Protocol
Web address Path to servlet and servlet
name
Port number
FIG. 23.8
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
The HTTP method we use in Listing 23.2B is GET. Later on we show the use of
method POST. Following the form tag we have two input tags to create two text
input boxes for the user to enter their first and last names. Then the lines
highlighted in yellow shows the code for placing all the radio buttons that are
grouped together. Then the lines highlighted in cyan show the code for placing
check boxes. Finally the line before the closing form tag shows the source code for
placing a submit button. When the user presses the submit query button the form
data would be sent to the URL listed in the action attribute using the method GET.
Figure 23.9 shows the form created by the Listing 23.2B in the web browser. The
look and feel would be slightly different in the Internet Explorer and Mozilla
Firefox browsers.
http://66.27.200.112:1168/j2ee/Hello?firstname=Satish&lastname=Singhal&radio1=
Cyan&check2=Felafel&check4=Curry&check5=PolishHam
When GET method is used to submit a form, then the browser sends all form
parameter to the web server by appending them to the URL it sends. In above URL
string all the form parameters entered by the user are appended after the question
mark ?. For example:
firstname=Satish and lastname=Singhal etc. For each parameter the browser send
the name of the parameter and its value entered by the user. Each set is separated
Obviously depending upon the choice made by the user, some members of array
Choice would be null and we would not need to print those. We can use a control
structure such as below to discern as to which one are those:
if (Choice[index] != null)
Print Choice [index] //index being the array index.
In order for the servlet hello to parse user inputted parameters from the web form
submitted to it, we just modify the method processRequest in Listing 23.1 as given
below (Listing 23.2B).
00039 protected void processRequest(HttpServletRequest request,
HttpServletResponse response)
00040 throws ServletException, IOException
00041 {
00042 response.setContentType("text/html");
00043 PrintWriter out = response.getWriter();
00044 out.println("<html>");
00045 out.println("<head>");
00046 out.println("<title>Servlet</title>");
00047 out.println("</head>");
00048 out.println("<body>");
00049
00050 out.println ("Hello " );
00051 String Name = request.getParameter("firstname");
00052
00053 if(Name !=null)
00054 out.println ("to " + Name +" ");
00055
Figure 23.11 shows the web page furnished to the user by the modified servlet Hello,
when the following entries are made in the form shown in Figure 23.9.
• First name : Satish
• Last name: Singhal
• Favorite color: blue
• Favorite foods: Felafel, curry, and Polish Ham.
FIG. 23.9
The URL that web page of Listing 23.2A submits to servlet is given below.
http://66.27.200.112:1168/j2ee/Hello?firstname=Satish&lastname=Singhal&radio1=
Blue&check2=Felafel&check4=Curry&check5=PolishHam
Notice that because we used the GET method to submit the form to the servlet, all
form data are appended to the URL after the question mark (?) in it. As we
mentioned earlier, there is a 255 character limit on HTTP URL’s. Therefore the use
of GET method to submit form data is not advisable if data in form would cross this
limit. In addition the URL displaying the form data is not a secure practice. In fact
it is possible to heck the form data when it is appended to the URL. For example if
we just add the string “&check6=WhoCares” to the end of URL shown above and
paste it in the web browser window and press enter, the web page produced (Figure
23.10) shows that displayed web page includes our hacked entry.
FIG. 23.10
To overcome both these limitations we use HTTP method POST to submit the form
data. Using POST is deceptively simple. In fact you would not need to alter your
servlet code at all. All you need to do is, in Listing 23.2A, to replace word GET by
word POST in the line which has the form tag. For example the form tag would now
be changed as below.
Rest of the code in Listing 23.2A and in servlet remains unchanged. Now when the
button Submit Query is pressed by the user the URL submitted to the servlet does
not include the parameter sent by the form, yet the functioning of servlet is
unaltered compared to when we used the GET method. One may ask as to what is
the advantage of using GET if POST (which has no problem with URL size and is
secure) works so well? The reason for using GET is that since it includes the
parameters in the URL string, such URL’s can be book marked by the user. This
provides one to do an instant search on the search engine such as Google.
JSP pages
We expressed that servlets and JSP are two faces of the same technology. Now we
would be able to illustrate that. We begin to see this equivalence, first studying the
similarity between the life cycle of a servlet and of a JSP page. Figure 23.11 shows
the events in the lifecycle of a JSP page. The various phases in its life cycle are as
follows:
FIG. 23.11
1. Translation: The JSP page is translated into a servlet before being loaded.
This translation included parsing the JSP page for servlet code and then
compiling the servlet. This is the reason that when first times a JSP page is
called by the browser when you test the page, there is a slight delay. The
servlet thus generated implements the interface
javax.servlet.jsp.HttpJspPage. This interface has the following methods,
which in turn are available to the servlet compiled from JSP page (Table
23.2).
Method Summary for HttpJspPage
void _jspService(javax.servlet.http.HttpServletRequest request,
javax.servlet.http.HttpServletResponse response)
The _jspService()method corresponds to the body of the JSP page.
Methods inherited from interface javax.servlet.jsp.JspPage
jspDestroy, jspInit
Methods inherited from interface javax.servlet.Servlet
destroy, getServletConfig, getServletInfo, init, service
Table 23.2
javax.servlet.http.HttpServletResponse response)
throws javax.servlet.ServletException,
java.io.IOException
The _jspService()method corresponds to the body of the JSP page. This
method is defined automatically by the JSP container and should never be
defined by the JSP page author.
If a superclass is specified using the extends attribute, that superclass may choose
to perform some actions in its service() method before or after calling the
_jspService() method. See using the extends attribute in the JSP_Engine chapter
of the JSP specification.
Parameters:
request - Provides client request information to the JSP.
response - Assists the JSP in sending a response to the client.
Throws:
javax.servlet.ServletException - Thrown if an error occurred during the
processing of the JSP and that the container should take appropriate action
to clean up the request.
java.io.IOException - Thrown if an error occurred while writing the
response for this page.
FIG. 23.12
As long as servlet is loaded the method _jspService continues to handle client
requests.
5. Destruction: When the servlet is no longer needed, it is destroyed by the
engine by calling the method jspDestroy.
One can see that the life cycle of a JSP page created servlet is similar to the regular
servlet, except the different methods are called in the different phases of its life. Next
we describe as how to create a JSP project in Netbeans.
FIG. 23.13
Popup box presents all possible templates. Choose the template JSP (Figure 23.13).
Then click on next.
4. The next popup box (Figure 23.14) would prompt you to enter the name of
your JSP page.
1. <%@page %>
t
2. JSP comment
FIG. 23.15
JSP allows you to write regular HTML the way you write it to build static web
pages. However, it allows you to add JSP code, which would be compiled into a
servlet behind the scene. All5 JSP code is placed between a pair of angular brackets
<% and %> or
You could have JSP code and HTML mixed together inside a .jsp file in the way in
which your design requires it. At runtime the servlet engine takes all the code
bounded in pairs of <% %> brackets and compiles it into a servlet to produce the
web page to be displayed by the jsp file. The elements <% and %> are considered
JSP operators6 and no space is allowed between them.
JSP tags
In order that JSP and HTML can co-exist in the same file JSP specification
introduced some special JSP tags. Two of them are already used in the Figure 23.13.
The bubble #2 shows the simple JSP comment. Any text (single or multi-line)
bounded in the pair of brackets given below
5
At times you may have a modifier attached to the first % sign. For example <%= expression %>
type. There are other modifiers as well.
6
Some of you may be somewhat unsettled to see us calling JSP tags as operators. Even though these
JSP tags are not classifiable as traditional unary and binary operators, their syntactic characteristics
are similar to operators such as == , or != , where no space is allowed between the characters forming
the operators. We believe that from syntactic point of view, finding a commonality with the multi-
character Java operators, makes it easier to remember the syntax of JSP tags. Thus we call them
operators, even though they do not fit the traditional definition of operators.
7
Java beans are some special precompiled classes, which can supply some information or data at the
runtime. Bean classes are written under some restrictions. We shall discuss Java beans in a later
chapter.
If there is a space between the angular bracket and percent sign then entire line is
treated like a regular HTML line and it is no longer a JSP code. That means that the
package java.util is not imported if code is written as follows:
Notice that in the import directive when multiple packages are imported, they are
separated by comma and not by semicolon! Also the end of import directive does not
have semicolon in the end. For example the below is a JSP compile error.
Comma separated package names or fully qualified class names may be placed
between single or double quotes. However, missing quotes altogether would be a
compile error. One can have as many import directive lines as needed.
Then we were able to use the out object to display HTML on the web page using its
println method. JSP is actually provided with same object called out as one gets
from getWriter method of HttpServletResponse (response in above code). The
provided out object in JSP can be used exactly the way it is used in servlet. In fact
very soon we show an example of use of out object in JSP. More commonly,
however, in JSP the following strategy is followed in displaying strings and data on
the web page.
In JSP and HTML the same output would be made with code line:
Since in above case the expression is the string value of Date object created by
the call to constructor, in JSP this expression would be outputted by enclosing it
inside the operators <%= and %>, leading to the following syntax:
Expression outputted in
<%= new java.util.Date () %> <BR> JSP page.
Remembering our rule about the syntax for operators, no space is allowed
between the characters forming the operator <%= .
8
Expressions are values of class or local variables return values from methods, string representation
of objects, and result of some mathematical operations, or any combinations of above.
The above code fragment would print ‘5’ on the web page. The reason that this
is OK is because in compiled servlet, val is a class level variable whose value is
set to 5 when servlet is initialized and loaded to the container. Therefore val is
available for outputting and the physical location of statement outputting val is
irrelevant. Same logic holds true about the declaration of member methods.
However to condition this output to the restriction that output be made only if val is
equal to 52, this must be under the scope of a pretest performed by the if selection
structure. In JSP it is done as follows (Figure 23.16):
<%
// code Under the scope of if
if(val == 52){ %> selection structure
Val = <%= val%> <BR>
<%}else{ %>
Under the scope of else
Val is not 52<BR>
selection structure.
<%}%>
This would indicate that all code in the scriptlet tags <% and %> is taken to be
continuous, even though physically it may be scattered all over the JSP page9.
9
Some programmers detest this inter dispersing of HTML and Java code and derisively they call it
spaghetti code. That is why if too many control structures, iteration structures, and
conditionals are to be used in a JSP page, one is better off writing a servlet to perform the same
function (if HTML to be outputted is small). On the other hand if your web page mostly has HTML,
and you just need to run Java code equivalent to a small servlet, then you are better off using a JSP
page. One can come upon a judicious mix of using servlets and JSP pages in their web applications.
Table 23.3
You would recall that we needed the object request and call its getParameter
method to parse the data inputted by the user in a web form. Since this object is
automatically available to use, we can just go ahead and use it. First we would like
to create a JSP page that would perform the same function as the servlet called
Hello (Listing 23.1 but using the processRequest method shown in Listing 23.2B)
shown earlier did. The Table 23.4 shows the equivalence between the code contained
in processRequest method (Listing 23.2B) and the way we would write it in a JSP
page.
Servlet code in method processRequest Code on JSP page that would be inserted
into _jspService method
out.println ("Hello " ); Hello
String Name = <%! String Name = null; %>
request.getParameter("firstname"); <%
Name =
if(Name !=null) request.getParameter("firstname");
out.println ("to " + Name +" ");
if(Name !=null)%>
to <%=Name%>
request.getParameter("check3"),request request.getParameter("check3"),request
.getParameter("check4"), .getParameter("check4"),
request.getParameter("check5"), request.getParameter("check5"),
request.getParameter("check6"), request.getParameter("check6"),
request.getParameter("check7")}; request.getParameter("check7")};
out.println("<U>List of your %>
favorite food(s)/drink(s):</U><BR>"); <U>List of your favorite
if( Str[0]!=null) food(s)/drink(s):</U><BR>
out.println(Str[0] + "<BR>"); <%
if( Str[1]!=null) if( Str[0]!=null)%>
out.println(Str[1]+"<BR>"); <%=Str[0] + "<BR>"%>
if( Str[2]!=null) <% if( Str[1]!=null)%>
out.println(Str[2]+"<BR>"); <%=Str[1]+"<BR>"%>
if( Str[3]!=null) <%if( Str[2]!=null)%>
out.println(Str[3]+"<BR>"); <%=Str[2]+"<BR>"%>
if( Str[4]!=null) <%if( Str[3]!=null)%>
out.println(Str[4]+"<BR>"); <%=Str[3]+"<BR>"%>
if( Str[5]!=null) <%if( Str[4]!=null)%>
out.println(Str[5]+"<BR>"); <%=Str[4]+"<BR>"%>
if( Str[6]!=null) <% if( Str[5]!=null)%>
out.println(Str[6]+"<BR>"); <%=Str[5]+"<BR>"%>
out.println ("<U>Date and time <%if( Str[6]!=null)%>
are: </U>" + new java.util.Date() + <%=Str[6]+"<BR>"%>
"<BR>"); <U>Date and time are: </U>
<%= new java.util.Date()%>
<BR>
Table 23.4