0% found this document useful (0 votes)
4 views460 pages

Practical Java Programming Guide

This document is a comprehensive guide to programming in Java, authored by Stuart Fripp, covering various topics from basic concepts to advanced features. It includes sections on Java's structure, data types, control flow, object-oriented programming, exception handling, and more, aimed at providing a practical understanding of the language. The course emphasizes hands-on learning and encourages users to work through examples and exercises to solidify their knowledge of Java.
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
4 views460 pages

Practical Java Programming Guide

This document is a comprehensive guide to programming in Java, authored by Stuart Fripp, covering various topics from basic concepts to advanced features. It includes sections on Java's structure, data types, control flow, object-oriented programming, exception handling, and more, aimed at providing a practical understanding of the language. The course emphasizes hands-on learning and encourages users to work through examples and exercises to solidify their knowledge of Java.
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd

PROGRAMMING IN JAVA

Developed and written by: STUART FRIPP


VZAP’s PRACTICAL COURSE IN JAVA

Table of Contents

Introduction ................................................................................................................ 6
Introduction To Java................................................................................................... 7
Getting your environment setup ............................................................................... 11
A Java Program ........................................................................................................ 16
Structure of a Java Program ..................................................................................... 23
Java’s Keywords....................................................................................................... 25
Primitive data types .................................................................................................. 26
Comments ................................................................................................................. 32
Variables ................................................................................................................... 45
Declaring Variables .................................................................................................. 46
Constants .................................................................................................................. 47
Operators In Java ...................................................................................................... 48
Arithmetic Operators ................................................................................................ 48
Relational and Equality Operators ........................................................................... 50
Increment and Decrement Operators ....................................................................... 51
Logical Operators ..................................................................................................... 52
Bitwise Operators ..................................................................................................... 54
Assignment Operators .............................................................................................. 58
Operator Order of Precedence .................................................................................. 59
Block Scope .............................................................................................................. 60
Strings in Java .......................................................................................................... 61
String Tokenising ..................................................................................................... 68
Output formatting ..................................................................................................... 72
Control Flow............................................................................................................. 77
Decision (Conditional) Statements........................................................................... 79
The ‘if’ Statement .................................................................................................. 79
The ? Operator ......................................................................................................... 84
‘switch’ Statement ................................................................................................ 85
Loops ........................................................................................................................ 88
Jump Statements ....................................................................................................... 95
Arrays in Java ........................................................................................................... 96
Casting .................................................................................................................... 102
Java Packages ......................................................................................................... 104
Classes and Objects ................................................................................................ 110
Variable-arity methods and varargs ....................................................................... 121
Inheritance .............................................................................................................. 124
Interfaces ................................................................................................................ 138
Nested and Inner Classes........................................................................................ 146
Anonymous Classes ............................................................................................... 147

PAGE 2
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

Wrapper classes and Autoboxing ........................................................................... 149


Exception Handling ................................................................................................ 159
Threads in Java ....................................................................................................... 171
Thread Priority ....................................................................................................... 176
Unrelated Threads .................................................................................................. 177
Related but Unsynchronized Threads .................................................................... 178
Mutually-Exclusive and Communicating Mutually-Exclusive Threads. .............. 179
Daemon Threads..................................................................................................... 186
Garbage Collection ................................................................................................. 187
Enumerations .......................................................................................................... 189
Annotations ............................................................................................................ 196
Creating Custom annotations ................................................................................. 199
Generics .................................................................................................................. 205
The Collections Framework ................................................................................... 215
Arrays.......................................................................................................... 215
Vector.......................................................................................................... 216
Stack ............................................................................................................ 222
Hashtable .................................................................................................. 224
Properties ................................................................................................ 228
BitSet.......................................................................................................... 231
Collections Interface .............................................................................. 238
AbstractCollection ............................................................................. 241
Set Interface.................................................................................................. 242
AbstractSet.............................................................................................. 242
HashSet<E> ................................................................................................ 242
TreeSet ....................................................................................................... 246
List Interface ............................................................................................... 248
LinkedList ................................................................................................ 249
ArrayLists ................................................................................................. 253
Maps ............................................................................................................... 255
AbstractMap.............................................................................................. 258
HashMap ....................................................................................................... 259
TreeMap ....................................................................................................... 261
WeakHashMap.............................................................................................. 262
Sorting and Shuffling ..................................................................................... 263
Event handling ........................................................................................................ 268
Multicasting ............................................................................................................ 288
Consuming.............................................................................................................. 290
Applets.................................................................................................................... 292

PAGE 3
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

Java I/O Streams and Files ..................................................................................... 301


Java Input ........................................................................................................... 304
Java Output ......................................................................................................... 319
The File class. ................................................................................................. 324
Scanner class ...................................................................................................... 328
Random File Access and appending .................................................................. 333
Serialization ............................................................................................................ 336
The JFC and Swing ................................................................................................ 351
Testing and Debugging Java Code ......................................................................... 400
Assertions ....................................................................................................... 402
JUnit testing .................................................................................................... 404
Debugging using JDB .................................................................................... 417
Conclusion .............................................................................................................. 432
Java Language Keyword Definitions ..................................................................... 433
Glossary of terms.................................................................................................... 440

PAGE 4
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

Learning

Responsibility for learning and growth rests ultimately with the individual. We can
reshape the environment to remove obstacles. We can stimulate and challenge. But
in the final analysis, the individual must foster his/her own development. (Anon).

This manual belongs to:

Copyright Notice:

This document may not be copied, reproduced, reduced or translated, in whole or


part, without the written consent of its author, Stuart Fripp or Directors at Van Zyl
and Pritchard (Pty) Ltd. All rights reserved.

Java is a trademark of Sun Microsystems Inc.

UNIX is a registered trademark licensed through X/Open Company Limited.


Windows is a registered trademark of Microsoft Corporation.
Windows/95, Windows 2000, Windows XP, Windows Vista, Windows/NT
Windows 7, Windows 8 and Windows 10 are trademarks of Microsoft Corporation.

PAGE 5
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

INTRODUCTION
This course is an introductory course in the JAVA language. Even though there
will be a fair amount of theory which is imperative to the understanding of the
language, the course leans towards the practical. The reason for this approach is so
that the delegate, having completed the course, will have a good basic grounding in
the language. In the course material there are a number of examples and exercises.
The delegate is encouraged to work through all the examples and attempt all the
exercises to gain the full benefit of the course.

Stuart Fripp

All sides of our nature press for satisfaction, and if left unsatisfied, will
manifest themselves so in ideas.
- F. H. Bradley, Essays on truth and reality.

PAGE 6
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

INTRODUCTION TO JAVA
Java is a general purpose, yet powerful object-oriented programming (OOP)
language. Patrick Naughton and James Gosling of Sun Microsystems started
designing Java in 1991. It was released to the public, for free, in 1995. Despite its
young age, Java has grown into an extremely popular programming language. Java
grew from a number of other languages, especially C and C++. For instance Java’s
syntax and variable scoping model is similar to C and C++. Java’s dynamic
memory management, multithreading and runtime extensibility is similar to that of
Smalltalk. Even though Java bears similarities to these and other languages it was
built from the base up with OOP in mind. The developer of C++, Bjarne Stroustrup
in his book The design and Evolution of C++, actually wrote “Within C++, there is
a much smaller and cleaner language struggling to get out.” Many believe that it is
Java.

The motivation to create Java was to produce a language that would be used for
control in the consumer electronics industry. It was imperative that the language
was portable, efficient, small and object-oriented. The first application Java was
used in was to control a small hand held computer known as *7 (star seven). *7’s
function was to control household electrical appliances. The MMI (man-machine
interface) was a colour touch-sensitive LCD screen through which the various user
options could be entered. The second project in which Java was used was in the
design of TV boxes that were supposed to deliver interactive video-on-demand.
Both these products did not enter into the consumer industry, but what they did for
Java was to develop it into a mature and reliable programming language.

Java’s trump card is its portability. Java applications will run on multiple hardware
and operating systems. Compiling Java source code into an object code known as
bytecode, and then using the Java interpreter, known as the Java virtual machine
(JVM) the application is executed. This JVM needs to be implemented only once
on each machine that wishes to execute Java programs. Thus Java code written on a
Windows machine will run on a Macintosh, Solaris, IBM mainframes, mobile
phones, tablets, personal digital assists (PDA) or any other machine running the
JVM. This portability even extends into the graphical users interface (GUI). Java
code is “Write Once, Run Everywhere”.

So the environment in Java looks as follows;

PAGE 7
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

Java Program

Java API’s

Java Virtual Machine


(JVM)
Computer System

As indicated in the above diagram “Java program” is the program you write and
which sits on top of the Java platform. This platform consists of the Java API
(Application Programming Interface), which are precompiled libraries of code.
These are being continually updated as is the JVM (Java Virtual Machine). Your
code gets translated by the JVM and then executed on your computer.

Java’s maturity, reliability, smallness and capacity to be architecturally neutral has


transformed the World Wide Web (WWW) and the way the Web is programmed.
No longer are web pages static and uninteresting. Java enabled browsers (browsers
containing the JVM) are capable of running programs that contain sound, video and
animation making web pages exciting and interesting. The Internet helped catapult
Java to the forefront of programming, and Java, in turn, had a profound effect on
the Internet.

Because Java makes use of bytecode and the JVM, one is assured of safe and
secure code. Each bytecode needs to be interpreted by the JVM before executing it.
As a program is unable to have direct access to system resources or calls to external
functions, a system environment is not open to malicious interference. This makes
Java one of the most secure programming languages available today.

Important programs created in Java are;


• Stand-alone application programs that run within the JVM
• Applets, which are typically smaller than stand-alone programs are embedded
into an HTML (Hypertext Markup Language) document and run inside a web
browser. Java not only simplified web programming in general by creating this
new type of networked program it also changed the way the online world
thought about content.
• Servlets, which is a small program that executes on the server. Just as applets
dynamically extend the functionality of a web browser, servlets run in a web
server and executed on demand in the server. They dynamically generate
content that is then served to clients. Servlets are being used to replace CGI

PAGE 8
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

(Common Gateway Interface) scripts as they offer several advantages, including


increased performance.

Java is a simple, very robust (as it is checked at both compile time and run time),
secure, portable, multithreaded, architecture-neutral, interpreted, high performance,
distributed, object-oriented programming language.

I trust that you will enjoy this course in Java.

PAGE 9
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

For Gill, Sarah and Robert.

Curious learning not only makes unpleasant things less unpleasant, but also
makes pleasant things more pleasant.
-Bertrand Russell, In Praise of Idleness.

PAGE 10
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

GETTING YOUR ENVIRONMENT SET UP


For our course you do not need any Integrated Development Environment (IDE). I
have put one in the ‘software pack’ that accompanies this course. It is called JGrasp
however. The reason for this is that it is far more beneficial to you that you learn
from the command line as opposed to using and IDE, which shields you from core
detail that really matter. It is imperative that you have a thorough, in depth
understanding of Java to be the best Java developer you can. Taking this approach
certainly helps get you there. Once you do have comprehensive handle on Java,
then move to an IDE that will automate processes for you.

1. You need a text editor. Any will do. For instance:


1. Windows: Notepad++, Atom, WordPad etc.
2. Linux: Vim, vi, Nano, Atom, Emacs
3. macOS: SublimeText, TextEdit, TextWrangler
2. Download Oracle’s Java Development Kit (JDK). Head to the main download
page [Link]
and get the latest stable release (JDK SE 9.0.1 was released on 17-10-2017) for
the operating system you are using. You may download previous versions
should you prefer to. If you do, make sure that it is at least JDK1.7 or greater
and is the non-beta version. Before performing any download, you need to
accept the ‘Oracle Binary Code License Agreement for Java SE’.
Just as aside, if you are running macOS make sure that you read which version
to download, depending upon the macOS you are running. Sometimes you may
get error messages when running applications in macOS because an application
requires the legacy Java 6 provided by Apple.
3. As the JDK may not contain any API documentation, you will need to download
this too. So, download the documentation that is associated with the JDK you
downloaded by going to [Link]
[Link] and select the version. You must get the documentation. You will
need it.
4. Once you have downloaded the JDK, click on the installer and go through the
steps. For this explanation, I will assume you have not installed any related tool
before, and your system is clean from Java and other Java development tools.

Setting up in Windows
1. There is one thing I do when installing Java on my machine, and that is I change
the default directory. Using JDK8 as an example, instead of installing the JDK
to C:\Program Files\Java\jdk1.8.0_102, I choose something that looks
like the following; C:\Java\jdk1.8.0_102. I do the same when the installer

PAGE 11
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

prompts me to install the JRE (Java Runtime Environment) and provide the
following path C:\Java\jdk1.8.0_102.
2. When complete, open a new command line (cmd) and type java -version.
This is illustrated below. If all went well you should see something like that
illustrated below. If not then there is another process we need to go through,
which involves setting up the path. If your console looks similar then for interest
sake, type where java command to find out which executable is loaded on
the path. This is also illustrated below.

3. Java may have not set up its path correctly if you did not see the above. So to
correct this you need to set up your path. Open your Advance System Settings
1. In the search box type: ‘View Advanced System Settings’
2. Open it
3. Select ‘Advanced’ tab
4. Press button ‘Environment Variables’
5. Select Path under ‘System variables’.
If you do not have one then add a new system variable calling it Path. Add the
C:\Java\jdk1.8.0_102\bin to the end of your path variables as illustrated on
the next page. Incidentally Oracle sets up shortcut links to the JDK which reside
in a hidden directory C:\ProgramData\Oracle\Java\javapath. You can edit
these as the path points to this directory, or make a new entry at the end of the
path like we have just done. Press OK, and then OK again to exit. Open a new
command prompt screen and do what you did in 6 above.

PAGE 12
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

4. Almost there - you need to set two more environment variables. This is an
important step as they may be used tools that are based on Java or require Java
to work.
1. JAVA_HOME variable: Add a new system variable as described in 7, but
this time give it the name JAVA_HOME and the path is actually the path our
JDK installation, in my case C:\Java\jdk1.8.0_102\ . This is shown
below;

2. CLASSPATH variable: Add a new system variable as described in 7, but


this time give it the name CLASSPATH and the path is actually the path to
your classes and any .jar files you create. Enter the following for the
meantime: .;..; This is shown below;

PAGE 13
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

Your Windows environment should now be successfully setup.

Setting up in Linux:
If you are using Ubuntu or LinuxMint then use apt-get to install. If you are using
Fedora or CentOS then use yum to install. I use LinuxMint, so will illustrate using
apt-get.

1. The very first thing to do after installing Linux is to update the system. If you
are working on ‘VirtualBox VM’ you will also need to install VirtualBox Guest
Additions.
sudo apt-get update
sudo apt-get install virtualbox-guest-dkms virtualbox-guest-x11

2. Your distro may have installed OpenJDK by default. You should remove
OpenJDK first and then install Oracle’s JDK.
sudo apt-get purge openjdk-*
sudo add-apt-repository ppa:webupd8team/java
sudo apt-get update

3. Install the JDK, in this example we will use JDK8


sudo apt-get install oracle-java8-installer

4. To set the JAVA_HOME and CLASSPATH environment variable. Enter the text
shown below. Edit the startup file ~/.bashrc or ~/.bash_profile or
~/.profile. For all the users globally, then you can add it to /etc/profile
file. In Linux, files beginning with dot (.) are hidden by default. To display
hidden files, use command ls -a or ls -al.
export JAVA_HOME=/usr/lib/jvm/java-8-oracle
export CLASSPATH= .:..:

5. To set the path permanently, set the path in your startup file. Enter the text
shown below. Edit the startup file ~/.bashrc or ~/.bash_profile or
~/.profile. For all the users globally, then you can add it to /etc/profile
file.
export PATH=$PATH:$JAVA_HOME/bin

6. To refresh the bash shell, issue a source command or re-start the bash shell.

PAGE 14
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

$ source ~/.bashrc

or
$ source ~/.bash_profile

or
$ source /etc/profile

Your Linux environment should now be successfully setup.

PAGE 15
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

A JAVA PROGRAM
To whet your appetite let us write our first Java program. Type the following
program exactly as it is. Do this by using any text editing program.
class FirstProg{
public static void main(String[] args){
[Link]("One Cup of Java and Cake Please.");
}
}

Once you have finished entering the code, save the file as [Link].
Make sure you save the file in a directory. For instance,
c:\users\username\java\ where username is your student code. Otherwise,
any other directory will suffice. For our example I will use the directory
c:\java\stuprogs. Your entered code should look as follows;

Throughout the course we are going to make use of Oracle’s (who acquired Sun
Microsystems) JDK. This Java Development Kit (JDK) is command line driven. As
you progress through the course you will learn the various features of this
environment.

Once you have saved the program you need to compile it. In other words you need
to convert your program code into bytecode. Do this by launching a DOS window,
or command line console, and make sure your command prompt points to the
directory in which you saved your [Link] file. Your screen should look
something like the screen below;

PAGE 16
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

To compile your code, type in at the command line: javac [Link]


If you typed in your code correctly your screen should look something like the
following;

If, for some reason, you made a typing error or syntax error then you will see a list
of error messages. For example, you may see something along the following lines;

PAGE 17
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

To rectify your error you need to return to your editor, locate the error, correct it
and save your updated code. Having done this you then need to recompile your
code. You need to repeat this process until the compiler generates no errors. To see
all the files in your working directory type: dir at the command prompt. Your
directory should contain the circled files.

If these two files are present and there are no compiler errors, it is time to run your
first Java program. To do this type in: java FirstProg at the command prompt.
Do not type in an extension. If all is well you will see “One Cup of Java and
Cake Please.” on your screen. This is shown on the screen below.

PAGE 18
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

CONGRATULATIONS!! You have just written, compiled and run your first Java
program.

For the fun of it, let us now write our first Java Applet. To do this, type in the code
exactly as you see it below using any text editor.
import [Link];
import [Link];
import [Link];

public class FirstApp extends Applet{


public void paint(Graphics graf){
[Link]([Link]);
[Link]("One Cup of Java and Cake Please.",20,20);
}
}

PAGE 19
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

Make sure that you save this file as [Link] in the directory you used
earlier. (You could use another directory if you wish). Compile this file. This is
done in exactly the same way as you did your first program. Once you have
finished compiling your code and there are no errors you should see a
[Link] and [Link] file sitting in the directory of choice. To
run an applet is slightly different to running a program. One needs to create an
HTML file. So within your text editor you are using, type out the following HTML;
<applet code=[Link] width=300 height=100>
</applet>

Save this in a file called [Link] in the directory in which you saved your
[Link] and [Link] files. (We could have embedded the HTML
code in the [Link] file). If you do not understand this at present, do not
worry. All will be revealed throughout the course.

Viewing this applet can be done in two ways


1. Using the appletviewer tool supplied in the SDK.
2. Using a Java enabled browser.

Let us first view this applet using the appletviewer. As a Java developer, this is
the preferred way for running Java applets. Ensure that you are in the directory in
which the [Link] and [Link] files reside. At the command
prompt type: appletviewer [Link]

PAGE 20
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

All being well you should see the applet appear on your screen.

Viewing your applet in a browser will most probably not work. The Java browser
plug-in relies on NPAPI, Netscape Plugin Application Programming Interface.
NPAPI is an application programming interface that allows plugins (more
specifically, browser extensions) to be developed for web browsers. Many web
browser vendors are deprecating this functionality due to NPAPI’s age and security
issues. As of April 2014, Google Chrome does not allow the use of any NPAPI
plugins. Mozilla Firefox also banned NPAPI plugins at the end of 2016. This
means that Java applets can no longer be used in either browser. In January 2016,
Oracle announced that Java runtime environments based on JDK 9 will discontinue
the browser plug-in and so your browser may not have Java enabled. Try and see if
your applet will execute by launching your browser and pointing it to the
[Link] file. If your browser is indeed ‘Java savvy’ you should see
something like the example shown below.

CONGRATULATIONS!!! You have just successfully run your first Java Applet.

Throughout this exercise you may have made a few errors and not copied down the
code exactly. What you must remember is that Java is case sensitive. For instance

PAGE 21
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

[Link] is not the same as [Link]. javac


[Link] is not the same as javac [Link]. Should you have
typed in the second lower-case statement you would have received an error
message. So BEWARE of this, it will catch you out many times.

PAGE 22
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

STRUCTURE OF A JAVA PROGRAM


Let us look at the first program we have just written. An important thing to
remember about Java is that it is an Object Oriented programming language. In the
program [Link] we see the keyword class. This keyword is used to
define a new class we are creating. This new class we called FirstProg. We
shall be discussing classes in greater detail throughout the course. We could have
called this class anything we wished.

Once we have declared the class name, the next step is to declare all methods and
variables that will be a member of this class. The class block is defined by a { brace
which opens the class block and the } brace which determines the end of the class
block. In our program these two braces are the left-most { and } brace combination.
There are different theories of where these braces should appear. As more of them
appear in the code, so I indent the code. This allows me to see which opening, {
brace corresponds to which closing, } brace. If you have been observant, you will
have noticed that the name of the .JAVA file corresponded exactly (even to the
capital letters) with the name of this public class. In Java, everything resides in
a class. These class names must begin with a letter. Thereafter it can be any
combination of letters and digits. The convention to class naming is to make the
first letter in the class name a capital letter. This will then prevent you from making
errors when accessing class methods or variables. Beware however of trying to use
Java’s reserved words for a class, method or identifier name.

Within the FirstProg class we see a method defined. This method name is main().
Every single Java program will have this method. It is our entry-point into the
program and the first method the JVM executes upon program invocation. For
C/C++ programmers, this method performs a similar function to the main function
in a C/C++ program. Preceding the method name is the keyword public. This is
known as an access modifier and indicates that the main method is accessible from
outside the FirstProg class. static will be discussed later. The keyword void
indicates that nothing will be returned from the main method. Remember this is an
introduction and should become clearer as we progress through the course.

Inside the ( ) braces we see the word String. This is a class name and we have
declared an array object args to be of type String. These are known as the
method parameters. It is the information passed into the main method when the
method is invoked. All statements within the main method are embedded between
two new { } braces. In our example there is only one statement,
[Link]("One Cup of Java and Cake Please.");

PAGE 23
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

In Java, as in C/C++ every statement must end in a semi-colon. Notice how the
println() method is being called. The general syntax for calling a method in Java
is;
[Link](parameters);

In our example we are using the [Link] object and then calling the println
method, passing it a parameter of type String. From this you should see that if you
invoke a method within a class you need to make use of the dot operator. This is
the same as invoking element members within a structure in a C program.

In any Java program you will always see the following method;
public static void main(String args[ ]){
:
:
}

This should give you a little more understanding of how a Java program is
constructed. This is an extremely simple program, but every Java program is based
on the above format. Let us now move on to studying the language in detail.

PAGE 24
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

JAVA’S KEYWORDS
The limits of my language mean the limits of my world.
-Ludwig Wittgenstein, Tractatus Logico-Philosophicus.

Below are the keywords defined by JAVA (as of JDK 8).

abstract default goto package this

assert (JDK1.4) do if private throw

boolean double implements protected throws

break else import public transient

byte enum (JDK1.5) instanceof return true

case extends int short try

catch false interface static void

char final long strictfp (JDK1.2) volatile

class finally native super while

const float new switch

continue for null synchronized

As discussed earlier Java is case sensitive and this applies to its keywords as well.
They are all lower-case. Those persons who know C/C++ will recognise a number
of these keywords.

A number of these keywords fall under the category of primitive data types.

PAGE 25
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

PRIMITIVE DATA TYPES


In Java there are eight primitive data types. These data types are, unlike the rest of
Java, non-object data types. Let us now discuss each of these eight types.

1. boolean
In C and C++ an expression would return an integer value of 0 (zero) or 1. In
Java this is not the case. An expression or method may return either true or
false. This is an area in which C/C++ programmers may make numerous
errors. As its name implies a boolean type may only be in one of two states, a
true state or a false state. Should you declare a variable to be of type
boolean and not explicitly assign it one of these two states, then the variable
will be assigned the default condition of false.

2. byte
A byte consists of eight bits and in Java it is a signed, two’s complement
quantity. Java does not have an unsigned byte. As a byte can only hold 8 bits,
the range of possible values that it may represent ranges from –128 to 127 (28).
What does a signed, two’s complement quantity mean? It is the way the
computer stores a value. For instance, the left most bit (known as the MSB, or
Most Significant Bit) determines whether the number being stored is a negative
or positive number. Should this bit be a 0 (zero) then the value in the remaining
bits is positive. However, if the number is 1 (one) then the number is negative.

MSB LSB
D7 D6 D5 D4 D3 D2 D1 D0
0 0 1 0 1 1 0 1

This value represents positive decimal 45. The representation of negative


decimal 45 is;

MSB LSB
D7 D6 D5 D4 D3 D2 D1 D0
1 0 1 0 1 1 0 1

Notice how the MSB bit has been set. There is a problem, however in storing
this negative number in a computer. It is not in the fact that the number itself is
difficult to store, but when it comes to using this negative number in arithmetic
operations. To do effective calculations on this number as it stands within a
microprocessor makes the circuit implementation within the hardware chip
extremely complex. So to resolve this problem, you store negative values in a

PAGE 26
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

form known as two’s complement. To generate a two’s complement we get the


binary value and convert it to one’s complement. This is achieved by toggling
all the bits except the sign bit. For example;

MSB LSB
D7 D6 D5 D4 D3 D2 D1 D0
1 0 1 0 1 1 0 1 -45

MSB LSB
D7 D6 D5 D4 D3 D2 D1 D0
1 1 0 1 0 0 1 0 -45 in ~1’s

Where ~ means complement. This ~ symbol is in fact the representation for the
complement operator in Java. Once a one’s complement has been generated, all
that is required to generate a two’s complement is to add a 1 to the one’s
complement. For example;

MSB LSB
D7 D6 D5 D4 D3 D2 D1 D0
1 1 0 1 0 0 1 0 -45 in ~1’s
0 0 0 0 0 0 0 1 Adding 1

1 1 0 1 0 0 1 1 -45 in ~2’s

So a positive number remains the same whereas the negative number is stored as
a two’s complement of the number with the MSB indicating the sign. The
implications for calculating are huge. In order for one number to be subtracted
from the other all that needs to happen is that the one number is converted into
two’s complement and then added. For example 5010 – 4510 = 510 = 000001012.
Let us see.

MSB LSB
D7 D6 D5 D4 D3 D2 D1 D0
0 0 1 1 0 0 1 0 50 +
1 1 0 1 0 0 1 1 (-45)

1 0 0 0 0 0 1 0 1 =5

The extra bit that gets carried over is ignored in this case. Under other
conditions it needs to be taken into account. So, as you can see the reason why
the byte value in Java makes use of two’s complement is for efficient data
calculation.

PAGE 27
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

In Java, byte numbers can be typecast. This must be remembered, especially


when doing arithmetic with bytes. In Java, arithmetic is always executed with
at least 32 bits of precision. This means that if we are going to perform
arithmetic operations on byte values these values will be cast into 32 bits, a
calculation executed and the answer returned will be 32 bits wide. This means
that the following code will generate an error;
byte a = 50, b = 45;
byte c = a + b;

To ensure that the correct result will be returned after the byte calculation, you
need to typecast. This informs the compiler that after the calculation the result
must be stored in a byte. The code to do this would look as follows;
byte a = 50, b = 45;
byte c = (byte)(a + b);

Typecasting has its problems. The reason for this is that the potential for loss of
precision is great. In real terms the MSB’s are dropped during typecasting.

As a rule of thumb: You need to typecast a numeric type whenever you assign
a more capacious type to a less capacious type.

3. int
An int is the fundamental data type for declaring integer variables. Like byte, it
is a signed two’s complement value. It is larger than a byte in that an int is 32
bits wide. This implies that any value from -231 to (231-1) may be represented in
an integer variable.

There are three int literals you may assign to an int. These are;
• Decimal:
int a = 50, b = 45;
int c = a + b;

• Octal:
int i = 023;
Note: to represent an octal number, the number MUST be preceded by
a 0 (zero).
• Hexadecimal:
int i = 0x4c;
int j = 0xFA;
int k = 0x2f;
int l = 0x2D;

PAGE 28
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

Note: to represent a hexadecimal number, the number must be


preceded by 0x (zero x) or 0X (zero X). The alpha values may be upper
or lower case.

When typecasting from a bigger integer type to a smaller type, for example from
an int to a byte, the higher order bits are just dropped. Remember this fact. If
you declare a variable and do not explicitly assign it a value, then it defaults to
being 0 (zero).

4. long
Like an int, long is a signed two’s complement number. However it is 64 bits
wide. It is thus capable of storing a value of between -263 to (263-1). Everything
that applies to int also applies to long. The only difference is in the declaring
of the long value. A long literal requires the suffix “l” or “L” to append the
integer value, for example;
long i = 23450l;
long j = 0x23feAL;

Beware of using “l” (‘el’), as this could be confused with a 1(one).


long i = 259l; //is this an ‘el’ or one?

5. short
Like a byte, int and long a short is a signed two’s complement number. It is
however 16 bits wide. It is therefore capable of storing a value of between –215
to (215-1). All that applies to byte, int and long applies to short except for
the “l” and “L”. Its default value is 0 (zero).

6. float
So far all the primitive data types discussed are capable of storing whole
numbers only. float however allows for the storage of a floating-point value of
between the ranges –3.4E38 to 3.4E38 in a 32 bit field, with about five to six
digits of accuracy. You must indicate a floating-point literal by explicitly
appending an “f” or “F” to the number. For example;
float pi = 3.14159f;
float E = 2.718281F;
float E = 2.7182818284590452354F;

If you do not append the number with “f” or “F” you will generate an error. The
following code produces an error;
float pi = 3.14159; //No No

floats are initialized to 0.0 if not explicitly assigned a value.

PAGE 29
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

7. double
A double stores a floating-point value. It differs from a float in that it is
capable of storing a number of –1.7E308 to +1.7E308 in 64 bits. To indicate a
floating point double literal you may append a number with “d” or “D”, but this
is not necessary. Any floating-point number defaults to double. This is why a
float requires an “f” or “F”. The following declarations all imply a double;
1e1 = 10
1E2 = 100
2.
.5
3.1415
3.1415d
6.19e14D (619 with 12 zero’s)

double and float adhere to the IEEE 754 arithmetic standard.

You may be wondering whether a number will ever be too big to be stored in a
double.
• Well the volume of the observable universe is about;
 4 * pi  3
(15billionlightyears ) = 10 cm
85 3

 3 

• The average density of a proton, taking the whole observable universe into
account is about 10-7cm-3.
• The number of protons in the observable universe has been calculated to be
in the region of 1078.

Will we need to store a value greater than 1.7E308?

8. char
A char is fundamentally different from all the other primitive data types in that
it is unsigned. It is 16 bits wide. In C a char is 8 bits wide. This implies that
Java char’s are different from an ASCII character. In fact Java’s char conforms
to the Unicode character set. This is an international character set that includes
all European and Asian characters. This ensures that Java is a truly universal
programming language. Java is however still capable of interpreting the ASCII
character set as the first 256 characters of the Unicode character set conform to
the ASCII character set.

In Java there are a number of character literals. These are the same as those
found in C, and appear in single quotes.

PAGE 30
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

Java has a number of character escape sequences. Again these are the same as
C’s character escape sequences. Java recognizes them as common non-printable
characters and are shown below;

\n → Linefeed. \r → Carriage Return.


\f → Form Feed. \\ → Backslash.
\t → Horizontal Tab. \” → Double Quote.
\b → Backspace. \’ → Single Quote.

Whenever Java encounters a backslash in single quotes, it then knows that the
character following has a special meaning. You are also able to represent an
Octal number as a character literal using this method. It takes the form \nnn,
where n is an octal digit. For example; \324 , \0.

To represent a Unicode character in Java the form is \uxxxx, where u indicates


that the number is based on the Unicode character set and xxxx is four
hexadecimal digits. For instance the escape sequence \n has a Unicode value of
\u000a. The \b escape sequence is represented as \u0008 in Unicode.

Finally, even though a char is a 16 bit quantity, if you are wanting to perform
16 bit arithmetic then make use of a short and not a char data type.

To find out more information on the Unicode character set visit the web site;
[Link]

To summarize; the primitive data types in Java are not objects. No matter the
platform the Java bytecode is going to run on, these data types will always be
the following;
boolean = true or false
byte = 8 bits
short = 16 bits
int = 32 bits
long = 64 bits
float = 32 bits
double = 64 bits
char = 16 bits

PAGE 31
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

COMMENTS
Comments are “explanations” about the program. In other words it provides
“internal documentation”. All the comments placed in your source code are ignored
by the compiler. Java programs are free format. This means that comments and
white space are not considered meaningful to the compiler. Before parsing, the
code is stripped of these. Comments in Java begin with the following character
sequences;
(a) /* and end with */
(b) //
(c) /** and end with */

Comments can be arranged basically in three different ways;


a) Block format.
b) Line format.
c) Short format.

a) Block comments can extend over many lines. This form of commenting is
usually used to describe class definitions, methods etc. For example;
/********************************************
The following code will evaluate
the rate of croaking of a bull frog to the
temperature of its surrounding water.
*********************************************/

// *****************************************
// The following code will evaluate
// the rate of croaking of a bull frog to the
// temperature of its surrounding water.
// *****************************************

b) One-line comments are usually used prior to a line of source code the comment
will describe. For example;
/* Initialize the variables for use as indices for frog array */
int row = 0, colmn = 0;

// Initialize the variables for use as indices for frog array


int row = 0, colmn = 0;

Short comments usually appear on the same line as the code, describing that line of
code. For example;
temp = frog_water(); /*Get the temperature of water from A/D sensor */

temp = frog_water(); // Get the temperature of water from A/D sensor

PAGE 32
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

You should have noticed that I have used the two types of comments the /* and */
and the //. These forms of comments are the same as the C and C++ form of
commenting. The /* and */ allows for multi-line comments, whereas the // has to
be placed on each line that requires commenting. The above examples indicate this.

One important thing to remember is that comments should assist the reader of the
source code to interpret OPERATIONAL usage. They should not describe the
language. For example the following comment really is silly;
/* Allocate space for three variables */
int a, b, c;

Beware: When using the /* and */ form of commenting, do not leave it


unterminated. The compiler will assume the whole program to be a comment from
the character sequence /* onwards. The compiler will not even issue an error.
These errors are hard to find when debugging, so ensure that you terminate your
comments correctly.

Comments cannot be nested. In other words you cannot have a comment within a
comment. For example a /* and */ within a /* and */ comment block. These will
cause misleading compiler-time errors, or even incorrect program operation. It is
for this reason you should not ‘comment-out-code’ using comment symbols.

Whenever you change your code, update your comments. Do not assume that your
comments are always correct. Ensure that any code change is reflected in your
comments.

Java has a special form of comment. This is the /** and */ comment block. Notice
the double asterisk. This form of comment has to be outside a method. For
example;
/** The frog API code
@version 1.0 Last updated: 21 Dec 2017
@author: Stuart Fripp
*/

In the JDK there is a tool called javadoc. Running your .java file that has these
comments through this tool will result in these comments being extracted and
copied to an HTML file. It is, in real terms an automatic document generator. So by
adding these comment blocks to your code and then running it through this utility
results in you generating up-to-date, professional looking documentation (assuming
that you keep your comments up-to-date). To ensure the most thorough
documentation you should add this form of commenting to the following areas of
your code;

PAGE 33
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

• package
• public class
• public interface
• public or protected methods
• public or protected variable or constant.
As we progress through the course you will learn what each of these are. I have
placed them here for reference. Below is a verbose description on how to go about
using javadoc in your source code. If you are very new to Java you may not
understand it all. Once you do have a better understanding of Java and its
environment, come back here and re-read the text and start implementing javadoc
in your code.

A documentation comment can span several lines, and contain special javadoc and
HTML tags for formatting the generated documentation. A single documentation
comment may be placed immediately preceding the following constructs.
• Class definitions and Interface declarations.
• Member method definitions, including constructors.
• Member variable definitions.

Such a comment will be treated as a regular comment, if placed elsewhere.


Information contained in the documentation comment and the construct declaration
are used by the javadoc utility to generate documentation akin to the API
documentation for the JDK, and as such can be read using a Web browser. In order
for the javadoc tool to be able to generate the documentation, each interface and
class must be placed in their own compilation unit, i.e. a separate source file.

Here is another example of a documentation comment;


/**
* This class generates a <i>generic stack</i>. The stack
* is implemented using an array.
* @author Fred Bassett
* @version 1.0
*/
public class Stack
{ ...class definition }

Inside a document comment, white space at the beginning of each line, followed by
an optional sequence of asterisks ('*'), are all ignored by the javadoc utility. The
first sentence in the comment is used as a summary for the construct in the
generated documentation. The javadoc facility recognises the end of the first
sentence as a period ('.') followed by white space. Text in the comment, including
the summary sentence, can be formatted, and hyperlinks to other documents can be

PAGE 34
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

specified using HTML tags. The first line that begins with the character @ ends the
general description, and starts the section containing special javadoc tags.

Using tags
Following the description inside the documentation comment, groups of special
javadoc tags can be used to provide additional information that can be extracted
by the javadoc utility. All javadoc tags have the following general syntax;
@<tag-name> <text>

A javadoc tag starts at a new line in the comment, and ends at the next javadoc
tag or at the end of the comment. Tags with the same name must be grouped
together inside the comment. Some tags also have pre-assigned formatting for the
first argument of the tag (for example the @exception, @throws, and @param).
Details for javadoc tags for documenting different constructs are given below.

The text in the comment can be formatted using HTML tags. For example, the HTML
tag pairs <b></b>, <i></i>, and <code></code> can be used without conflicting
with the document structure generated by the javadoc utility. However, HTML tags
like <h1> and <h2> should be avoided. Paragraphs can be created using the
<p></p> element pairs in the comment.

Tag Name Used With Tag description


@author Class, Interface. Specifies the author of the class or interface.
@deprecated Class, Interface, method and Specifies that the declaration has been deprecated.
member variable.
@exception Method. Specifies the exception thrown by the method.
{@link} Class, Interface, method and Creates an in line hyperlink.
member variable.
@param Method. Specifies the formal parameters of the method.
@return Method. Specifies the value returned by the method.
@see Class, Interface, method and Creates a hyperlink.
member variable.
@since Class, Interface, method and States the version of the code in which the
member variable. declaration was first introduced.
@throws Method. Specifies an exception thrown by the method.
Same as the @exception tag.
@version Class, Interface. States the version of the class or interface.

PAGE 35
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

javadoc Tags for Classes, Interfaces and Members


The following tags may be used in documentation comments for classes, interfaces,
methods and member variables.
@see
{@link}
@deprecated
@since

1. Specifying hyperlinks to Classes and Interfaces


@see <class-name or interface-name> <label>
@see <full class-name or interface-name> <label>
@see <full package-name> <label>
{@link <class-name or interface-name> <label>}
{@link <full class-name or interface-name> <label>}
{@link <full package-name> <label>}

A hyperlink to the specified class or interface is created in the generated


document. If the option label is specified, it is used as the link's visible link.
The class or interface is in the current package, if the full class or interface
name is not specified.
@see Stack
@see [Link] Stack
@see [Link]

see also this {@link [Link] Stack} class.


For information on extra utilities, try
{@link [Link] here}.
See {@link [Link] Collections}.

2. Specify hyperlink to members


@see #<member-name> <label>
@see <full class-name>#<member-name> <label>
@see <full class-name>#<method-signature> <label>
{@link #<member-name> <label> }
{@link <full class-name>#<member-name> <label> }
{@link <full class-name>#<method-signature> <label> }

The @see and {@link} tags create a hyperlink to the specified member in
the generated document. Whereas the link created by the @see tag is placed
in a “See Also” section, the {@link} generates an in line link in the text
where this tag appears. If the optional label is specified, it is used as the link's
visible label. The member is the current class or interface if no class is
specified.
@see #topOfStack
@see #peek()
@see [Link]#topOfStack
@see [Link]#peek() here
@see [Link]#push(Object) push

PAGE 36
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

Use the {@link [Link]#push(Object) push method}.


For more information, click
{@link [Link]#peek()here}.

3. Specify hyperlinks to other documentation


@see <a href=”URL#value”>label</a>

In the documentation, a See Also entry is added as the specified hyperlink.

@see <a href=”[Link]#peek”>Usage Restrictions</a>

4. Marking features as deprecated


@deprecated <explanation>

This tag allows entities to be marked as deprecated, meaning that their


continued usage is discouraged. The Java compiler reads these tags and
issues a warning if a deprecated feature is used by a program. The javadoc
utility generates a deprecated entry in the documentation, together with the
explanation. All members in a class or interface are marked deprecated if the
class or interface is marked deprecated.

@deprecated As of Version 1.1 replaced by this {@link #push() push}


method.

5. Dating features
@since <version>

This tag allows a specific version for a feature to be recorded in the


documentation. The intended usage of this tag is to indicate when the feature
was added.
@since version 1.1

Documenting Classes and Interfaces


The following tags may only be placed in the documentation comments for classes
and interfaces.
@author
@version

1. Documenting the author of a Class or Interface


@author <Author-Name>

In the documentation, an author entry is created with the specified author


name. Several authors can be specified, using a separate @author tag for
each author. The command-line option -author must be given to the
javadoc utility to generate this entry.

PAGE 37
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

@author A. Writer
@author N. Scribble
@author unascribed

2. Documenting the version of a Class or Interface


@version <text>

In the documentation, a version entry is created with the specified text. The
command-line option -version must be given to the javadoc utility to
generate this entry.
@version 1.2.1a, 1-November-2017

Documenting Methods
The following tags may only be placed in the documentation comments for
methods (and constructors).
@param
@return
@exception
@throws

1. Documenting the parameters of a method


@param <parameter-name><description>

The specified parameter and its description are added to the Parameters
section of the documentation pertaining to the current method. Each
parameter should be specified using a separate @param tag.

@param element The Element to push onto the stack

2. Documenting the return value of a method


@return <description>

The description of the returned value is added to the Returns section of the
documentation pertaining to the current method. This tag is omitted if the
return type is void.

@return The value on top of the stack

3. Documenting the exceptions of a method


@exception <exception-class-name><explanation>
@throws <exception-class-name><explanation>

These two tags are synonyms. The specified class name of the exception and
its explanation are added to the Throws section of the documentation
pertaining to the current method. Each exception should be specified using a
separate tag.

PAGE 38
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

@exception EmptyStackException Tried to pop the stack when it was empty.


@throws [Link] Read operation failed.

Documenting Member Variables


There are no specific javadoc tags for documenting member variables. The
documentation comment together with the common javadoc tags @see, {@link},
@deprecated and @since suffice for document variables.

Some Documentation Conventions


The code element of HTML is typically used for formatting Java keywords, and for
formatting package, class, interface, method and variable names, and also for code
in the documentation comment.
@return <code>true</code>, if stack is empty.

The parameter list is not specified with a method name, except when a particular
method signature is desired.
@see [Link]#push
@see [Link]#push(Object)

The tag order is usually;


@author
@version
@param
@return
@exception
@throws
@see
@since
@deprecated
with the {@link} tag being used for in line hyperlinks where necessary.

PAGE 39
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

Common options for the javadoc Utility


-sourcepath <path> List of directories and files containing the source files. List-separator is
platform dependent. i.e. “:” for Unix and “;” for Windows.
-classpath <path> List of directories and files containing the source files. List-separator is
platform dependent. i.e. “:” for Unix and “;” for Windows.
-d <directory> Destination directory for the output files generated by the javadoc
utility. The default is the current directory.
-public Documentation is generated for the public classes, interfaces and
members only.
-protected Documentation is generated for the protected and public classes,
interfaces and members. This is the default action.
-package Documentation is generated for the package, protected and public classes,
interfaces and members.
-private Documentation is generated for all classes, interfaces and members.
-author @author paragraphs are only included if this option is specified.
-version @version paragraphs are only included if this option is specified.
-nodeprecated @deprecated paragraphs are excluded if this option is specified.

Running javadoc
The javadoc utility takes as an input a list of packages or a list of Java source files
specified on the command line;
javadoc [Link] [Link]
javadoc [Link] [Link]

Note that the package names are specified using the dot-notation, not by their
directory location. For the individual classes and interfaces, the filenames must be
specified. If the javadoc utility cannot find the specified input sources, their
location may be specified on the command line using either the -sourcepath or -
classpath option.

The generated files comprising the HTML documentation are placed under the
current directory, unless the destination directory is specified using the -d option.
javadoc -d doc/gui [Link] [Link]

Options are provided to tailor the generated documentation according to the


accessibility modifier of the class, interface or member. The default action of the
javadoc utility is to generate documentation for classes, interfaces and members
that have protected or public accessibility. This corresponds to the -protected
option. Documentation can be restricted to public declarations, using the -public

PAGE 40
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

option. The -package option can be used to expand the documentation to include
classes and interfaces that have package or public accessibility, and members that
are non-private. The -private option can be used to generate documentation for
all classes, interfaces and members.

A simple way to generate documentation for one or more packages is to issue the
javadoc command in the root directory of the package hierarchy, and specify the
names of the relevant packages. For example, if the fully qualified name of the
package is [Link] and it is in a directory called
dev/com/example/extras/util, then the following command can be given in
the util directory;
javadoc -private [Link]

One way to generate documentation for one or more classes is to issue the javadoc
command in the directory containing the source files. For example, if the source
files are in a directory dev/com/example/extras/util, then the following
command can be given in the util directory;
javadoc -private *.java

The author and version information are not included, unless the options -author
and -version are specified. Information about deprecated features are normally
included, unless -nodeprecation is specified.
javadoc -author -version -private [Link]

The generated file named [Link] is the starting point for navigating the
generated documentation. For each class and interface, the (default) generated
documentation includes;
• Class hierarchy diagram for the class or interface.
• Links to inherited members.
• Variable, constructor and method summary sections.
• Variable, constructor and method detail sections.

In summary, a single documentation comment may be placed in front of classes,


interfaces and members. The general syntax of a documentation comment is as
follows;
/**
* A Summary Sentence
* Followed by any additional explanation
* Followed by any Javadoc tags, grouped by name, with each one starting on a
* new line
*/

PAGE 41
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

The summary sentence, the additional explanation and the javadoc tags can span
several lines, and HTML tags can be used to format the contents of a document
comment.

Common pitfalls when using javadoc


1. Trying to generate documentation for the source code in incremental steps.
Documentation for all the classes must be generated in one go.
2. Trying to generate documentation for incomplete code. If the compiler fails to
compile the source code, then javadoc is likely to fail generating the
documentation.
3. Trying to generate documentation for classes that have the package or private
accessibility, without specifying the option -package or -private.

Here is an example of running javadoc


package [Link];
/**
* This class implements a <i>generic stack</i>.
* An array is used to implement the stack
* @author Fred Bassett
* @version 1.4
*/

public class Stack{


/** The array that implement the stack */
private Object[] stackArray;

/** The top of the Stack */


private int topOfStack;

/**
* Initialise the Stack
* @param capacity Length of the Stack
*/
public Stack (int capacity){
stackArray = new Object[capacity];
topOfStack = -1;
}

/**
* Push a value on the Stack
* @param element The Object to push onto the Stack.
* @exception FullStackException The Stack is full.
* @see #pop()
*/
public synchronized void push(Object element) throws FullStackException{
if(isFull()) throw new FullStackException();
stackArray[++topOfStack] = element;
}

/**

PAGE 42
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

* Insert a value on the Stack


* @param element The Object to insert on the Stack
* @exception FullStackException The Stack is full.
* @deprecated as of version 1.3, replaced by the
* {@link #push(Object) <i>push</i>} method. The insert name was misleading.
*/
public synchronized void insert(Object element) throws FullStackException{
push(element);
}

/**
* Pop the value from the top of the Stack
* @return The Object on top of the Stack
* @exception EmptyStackException The Stack is empty.
* @see #push(Object)
*/
public synchronized Object pop() throws EmptyStackException{
if(isEmpty()) throw new EmptyStackException();
Object obj = stackArray[topOfStack];
stackArray[topOfStack] = null;
topOfStack--;
return obj;
}

/**
* Peek at the Object on top of the Stack. The Stack is not popped.
* @return The Object on top of the Stack
* @exception EmptyStackException The Stack is empty.
*/
public synchronized Object peek() throws EmptyStackException{
if(isEmpty()) throw new EmptyStackException();
return stackArray[topOfStack];
}

/**
* Check if the Stack is empty
* @return <code>true</code>, if stack is empty.
*/
public boolean isEmpty(){
return (topOfStack < 0);
}

/**
* Check if the Stack is full
* @return <code>true</code>, if stack is full.
*/
public boolean isFull(){
return (topOfStack == ([Link] - 1));
}

Resulting document...

PAGE 43
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

PAGE 44
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

VARIABLES
In Java the names of variables, methods and labels are called identifiers. These
names can vary from just one character to several. A variable is one of the most
fundamental aspects to any programming language. It is a named location in the
computer memory that is set aside for certain data types. By making reference to
the name, you actually refer to the data.

There are some restrictions that you must be aware of. Names are made up from a
combination of letters and digits. The first character of an identifier must be either a
letter, an underscore (‘_’) or dollar (‘$’). No other symbol is allowed. In Java the
underscore and dollar is considered a letter, however. In Java uppercase and
lowercase letters are different. So the following variable names are different; FROG;
Frog; FrOg;

Theoretically the length of an identifier is unlimited. Remember do not use


reserved words as variables. Make sure that you use a variable name that relates to
the purpose of that variable. This will make your code more readable. Sun
Microsystem’s has recommended a simple standard where all Java identifiers start
with a lowercase letter and each embedded word within the identifier starts with a
capital letter. For example; frog, wetFrog, poisonFrog.

Examples of correct and incorrect identifiers are;

CORRECT INCORRECT
THESHORTYEAR 1999Year

lengthOfTruss9 &&stringLength

item99 this-is-a-variable

PAGE 45
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

DECLARING VARIABLES
The general form of a variable declaration is;
type variable_list;

The type must be any valid Java data type. The variable_list can be one or
more variable names separated by a comma. All the variables declared will be of
the same type. The declaration must end with a semi-colon. In Java the semi-colon
is a statement terminator. Below are some examples of initialized variable
declarations;
int i; // an integer named i
float a, b, g; // floating-points named a, b and g
int end; // an integer called end
char[] frog; // an array of unspecified length of chars named frog

Earlier we said that each instance variable would be initialized to a default value if
a value has not been explicitly assigned to that particular instance variable. Relying
on this default assignment is not good programming practice. You should always
explicitly assign a value to a variable. To do this we make use of the assignment
operator ( = ). For example;
int noOfPupils;
:
:
noOfPupils = 23;

Here noOfPupils has been assigned the value 23. It is possible to declare and
initialize a variable at the same time;
int noOfPupils = 23;
char ch = 'A'

PAGE 46
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

CONSTANTS
In Java, constants refer to fixed values. As the name implies, these values are not
allowed to be altered by the program. One thing that is important is that the
constant type must match the variable type in which the constant will be stored. For
example, an int constant cannot have a fractional component, whereas a float
must. In C and C++ the keyword const is used to define a constant character. This
is not the case in Java. The way Java defines a constant is by using the keyword
final. To declare an identifier of a certain type as being constant you would type
the following;
final double PI = 3.14159;
final int MAX_STUDENT_NO = 100;
final char BACKSPACE = '\b';

Sun Microsystems recommends that all constants be declared as capital letters. By


doing this you will then not become confused between variables and constants. If,
in my code I did the following;
final int MAX_STUDENT_NO = 100;
:
: //some code
:
MAX_STUDENT_NO = 200;
:
: //some code
:

The compiler would generate an error. This is because MAX_STUDENT_NO has been
declared a constant, it cannot change.

PAGE 47
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

OPERATORS IN JAVA
Operators are words or symbols that cause a program to do something to variables.

ARITHMETIC OPERATORS
The arithmetic operators in Java consist of;

Operator Meaning
+ addition
- subtraction, also unary minus
* multiplication
/ division
% modulus division (remainder)

The *, / and % have the same precedence. The + and - have lower precedence
than the aforementioned operators. This means that the *, / and % operators will be
executed first when placed in an expression together with the + and - operators.
Should there be more than one *, / and % operator in the same equation, then the
operators will be executed from left to right. In fact all equations are evaluated
from left to right, unless there are ( ) within the equation. In that case, the
expression within the ( ) is evaluated first.

The +, -, * and / operators will operate on integer and floating-point types. If you
apply / to an int any remainder that results will be truncated. For example
int i=5/2; // i = 2
float f=3.1482f/2.96f; // f = 1.0635811f

In Java, the modulus operator % may be applied to both integer and floating-point
types. (This is unlike the % operator in C/C++ where it may only be applied to
integers). When using this operator, simply perform the operation by dividing. If
there is a remainder, the remainder will be the resultant value. If there is no
remainder, the result is 0 (zero). For example:
y = 10%5; // y = 0, where 10/5 = 2 remainder 0
y = 10%4; // y = 2, where 10/4 = 2 remainder 2
y = 42.3%10; // y = 2.3, where 42.3/10 = 4 remainder 2.3

PAGE 48
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

Below is an example using these arithmetic operators. Do you understand it?


public class OperatorExample{
public static void main(String[] args){
int a = 1, b = 2, c = 8;

a = c-(a+b); // a is 5
b = a*(c/b); // b is 20
b = 9%3; // b is 0
c = 25%7; // c is 4
b = 1;
c = a*c-b; // c is 19
}
}

PAGE 49
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

RELATIONAL AND EQUALITY OPERATORS


These operators are used to determine a true or false condition. In Java, true and
false is a boolean value. There are four relational and two equality operators.

Operator Meaning
< Less than.
> Greater than.
<= Less than or Equal to.
>= Greater than or Equal to.
== Equal to.
!= Not Equal to.

All these operators have the same precedence. Let us first look at the relational
operators;

x < y returns true if x less than y, otherwise returns false.


x > y returns true is x greater than y, otherwise return false.
x <= y returns true if x less than or equal to y, otherwise returns false.
x >= y returns true if x greater than or equal to y, otherwise returns false.

REMEMBER: The equal operator is == and not =. An example using ==.


public class OperatorTst{
public static void main(String[] args){
int speed;
speed = 75;
[Link]("Is the speed equal to 55? " + (speed == 55));
speed = 55;
[Link]("Is the speed equal to 55? " + (speed == 55));
}
}

The output of this above program will look as follows;


Is the speed equal to 55? false
Is the speed equal to 55? true

Note how speed == 55 evaluates to false or true

The inequality operator (!=) is the opposite of the equality operator (==) in that it
returns a true on inequality otherwise returns a false.

PAGE 50
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

INCREMENT AND DECREMENT OPERATORS


These types of operators are usually not found in other programming languages
(other than C and C++). In many programs you need to increment or decrement by
one. The function of these operators is to do just that. So;

++i is the same as i = i + 1 //incrementing by 1


--i is the same as i = i – 1 //decrementing by 1

Now these operators may be used as prefix or postfix operators. The effect of both
methods is to either increment or decrement by 1. The difference is that the prefix
expression (++i) causes the value of i to be incremented by 1 before its value is
used, whereas in the postfix expression (i++) the value of i is increased by 1 after
the value has been used. For example;
public class OperatorTst{
public static void main(String[] args){
int a = 4;
int b = 4;

int c = 2 * ++a;
int d = 2 * b++;

[Link]("c= " + c + " and a= " + a);


[Link]("d= " + d + " and b= " + b);
}
}

The output will be:


c=10 and a=5
d=8 and b=5

Finally, do you think that the following is a legal operation?


4++;

PAGE 51
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

LOGICAL OPERATORS
These operators evaluate to true or false. The logical operators are;

Operator Meaning
|| logical OR
&& logical AND
! logical NOT

Java does not have a logical EXCLUSIVE OR operator. It is important to


remember that logical operators are composed of double symbols (&&). Do not use
single symbols (&) as these have a different meaning. && is a logical AND operator
whereas & is a bitwise AND operator. One other thing, logical operators have a
lower precedence than relational operators.

In the case of the && operator all conditions must be true in order for the
expression to be true. For instance if;
boolean b = true;
boolean bB = true;

then the expression;


(b&&Bb);

would return true. Should either of these variables be false the expression would
evaluate to false. The AND logic is shown in the table below;

variable 1 variable 2 && result


false false false
false true false
true false false
true true true

In Java the expression is evaluated from left to right. So in this above example
should b have been false Java would not have continued evaluating the expression
but return false immediately. This is because irrespective of what the other
variable value is, the statement will be false.

PAGE 52
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

In the case of the || operator only one condition need be true in order for the
expression to be true. For instance if;
boolean b = true;
boolean bB = false;

then the expression;


(b||Bb);

would return true. Should both of these variables be false the expression would
evaluate to false. The OR logic is shown in the table below;

variable 1 variable 2 || result


false false false
false true true
true false true
true true true

When Java evaluates this above expression and the first variable is true, it
immediately terminates the statement and returns true, irrespective of what the
condition of the other variables is. As seen from the above truth table only when all
the variables are false will the expression evaluate to false.

PAGE 53
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

BITWISE OPERATORS
One of the differences and advantages of Java over other programming languages
is that it supports a complete complement of bitwise operators. C and C++ have
these capabilities as well. When using bitwise operators, it is important to
remember that they may only be used on integer types. Below is a table of the
bitwise operators.

Operator Action
& AND
| OR
^ XOR (Exclusive OR)
~ One’s Complement
>> Shift right (arithmetic)
<< Shift left (arithmetic)
>>> Shift right (logical)

Do not get confused between bitwise AND (&) operator and the logical AND (&&)
operator, as well as the bitwise OR (|) operator and the logical OR (||) operator.

AND is usually used for bit masking. As an example, if we want to mask off the
parity bit in a byte of data, which is usually the 8th bit we do the following;
public class OperatorBitAnd{
public static void main(String[] args){
byte j = (byte)0xf5;
[Link]("j(0xf5) ANDed with 0x71 = " + (byte)(j&0x71));
}
}

The output of this above program will be;


j(0xf5) ANDed with 0x71 = 11310

This process is shown below. The AND truth table shown under the logical AND
(&&) operator section of this manual applies to the bitwise AND (&) operator as
well.

PAGE 54
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

MSB LSB
D7 D6 D5 D4 D3 D2 D1 D0
1 1 1 1 0 1 0 1 j = 0xf5
0 1 1 1 0 0 0 1 ANDing with 0x71

0 1 1 1 0 0 0 1 0x71 = 11310

In this example notice how we have masked off the bits D2 and D7 in the variable j.

OR ( | ) is normally used for setting certain bit in a variable. For example;


public class OperatorBitOr{
public static void main(String[] args){
byte j = (byte)0x05;
[Link]("j (0x05) ORed with 0x71 = " + (byte)(j | 0x71));
}
}

The output of this above program will be;


j(0x05) ORed with 0x71 = 11710

This process is shown below. Make reference to the OR truth table shown under the
logical OR ( || ) operator section.

MSB LSB
D7 D6 D5 D4 D3 D2 D1 D0
0 0 0 0 0 1 0 1 j = 0x05
0 1 1 1 0 0 0 1 Oring with 0x71

0 1 1 1 0 1 0 1 0x75 = 11710

In this example notice how we have set the bits D4, D5 and D6 in the variable j.

XOR (Exclusive OR) can be used for data encoding or complementing bits (i.e. Bit
toggling). It is represented by the caret (^) character. This operator returns true
when either bit is true, but not both. This relationship is shown in the truth table on
the next page.

PAGE 55
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

Bit 1 Bit 2 ^ result


false false false
false true true
true false true
true true false

for example;

MSB LSB
D7 D6 D5 D4 D3 D2 D1 D0
1 0 1 1 1 1 0 0 j = 0xbc =18810
0 0 0 0 1 0 0 0 XORing with 0x08

1 0 1 1 0 1 0 0 0xb4 = 18010

Let us now XOR this result again;

MSB LSB
D7 D6 D5 D4 D3 D2 D1 D0
1 0 1 1 0 1 0 0 j = 0xb4 = 18010
0 0 0 0 1 0 0 0 XORing with 0x08

1 0 1 1 1 1 0 0 0xbc = 18810

Notice how we return back to our original value.

Shift left and shift right results in the variable moving to the left or right
respectively. If you move the variable one bit to the left, you then multiply that
variable by two. Likewise, shifting the variable one bit to the right results in that
variable being divided by two. The general form for these bitwise operators is;
variable >> number_of_bits; // for shift right
variable >>> number_of_bits; // for shift right
variable << number_of_bits; // for shift left

When using the shift right operator, the number following the operand determines
the number of bits being shifted to the right. As you shift to the right, those bits
being shifted out of the D6 bit position are replaced by the value of the sign bit (i.e.
The MSB). Therefore the >> is an arithmetic shift operator. For example;

PAGE 56
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

byte b = (byte)0x72;
:
:
(byte)(b>>2); // results in 0x1C. To shift right and save then the
// syntax would be (byte)b=>>2;

Graphically the process is;

MSB LSB
D7 D6 D5 D4 D3 D2 D1 D0
0 1 1 1 0 0 1 0 b = 0x72 =11410
0 0 1 1 1 0 0 1 Shifting once = 0x39
0 0 0 1 1 1 0 0 Shifting twice = 0x1C

Those bits “falling” out of the LSB, disappear. Remember: the >> shift operator
does not rotate the bits, as variables are shifted, the sign bit is brought in and the
shifted off bits are lost. Think of this operator as “right-shift-sign-fill”.

The Java >>> operator performs the same function as the >> operator, except for
one very important feature. As a shift right is executed the higher bits are replaced
by 0(zero) irrespective of the value of the sign bit. This operator is therefor known
as a logical shift right operator. Think of this operator as “right-shift-zero-fill”.

The << shifts the bits in an integer variable to the left. The number of bits shifted is
determined by the number following the operand.

The complement operator ( ~ ) is just that, it complements the bits in the specified
variable. i.e. All the 1’s become 0, and all the 0’s become 1.

PAGE 57
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

ASSIGNMENT OPERATORS
Java has a special shorthand expression that results in a simplification of certain
type of assignment statements. For example;

*= → a *= b is the same as a = a*b


+= → a += b is the same as a = a+b
-= → a -= b is the same as a = a-b
/= → a /= b is the same as a = a/b
& → a &= b is the same as a = a&b
| → a |= b is the same as a = a | b
% → a %= b is the same as a = a%b
^ → a ^= b is the same as a = a^b
>> → a >>=b is the same as a = a>>b
>>> → a >>>= b is the same as a = a>>>b
<< → a <<=b is the same as a = a<<b

Examples using these operators;

a = a*(b+1) is the same as a *= (b+1)


a = a%(b+c) is the same as a %= (b+c)
a = a+(b+c) is the same as a += (b+c)
a = a-(b+c) is the same as a -= (b+c)
a = a/(b+c) is the same as a /= (b+c)

PAGE 58
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

OPERATOR ORDER OF PRECEDENCE


When unsure of the order of precedence, then it is best to use parentheses very
much the same way as in mathematics. The table below lists the hierarchy of
operations of the Java operators with the highest level of precedence being at the
top of the table and the lowest at the bottom. The way the operators are processed
are also listed.

Operators Associatively
[ ] . ( ) (method call) left-to-right
! ~ ++ -- +(unary) –(unary) ( )(cast) new right-to-left
* / % left-to-right
+ - left-to-right
<< >> >>> left-to-right
< <= > >= instanceof left-to-right
== != left-to-right
& left-to-right
^ left-to-right
| left-to-right
&& left-to-right
|| left-to-right
?: left-to-right
= += -= *= /= %= &= |= ^= <<= >>= >>>= right-to-left

PAGE 59
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

BLOCK SCOPE
We have seen that in Java a block (or compound statement) is any number of
statements surrounded by { } brackets. In Java, blocks define the scope of
variables. Blocks can be nested within each other. Variables declared in the outer
blocks are visible from within the inner blocks. On the other hand variables that are
declared within the inner blocks are not visible to the outer blocks. Coupled with
this, all of the variable names must be unique, irrespective of which block they are
declared in. The following code will work;
public class TestScope{
public static void main(String[] args){
int n;
{
int k = 5;
n = 21;
[Link]("The sum of k + n = " + (k+n));}
}
}

However, the following code will not compile. Can you work out why and figure
out what the error message will be?
public class TestScope2{
public static void main(String[] args){
int n;
{
int k = 5;
n = 21;}
[Link]("The sum of k + n = " + (k+n));
}
}

The following code will not compile. Can you work out why and figure out what
the error message will be?
public class TestScope3{
public static void main(String[] args){
int n;
{
int k = 5,
n = 21;
[Link]("The sum of k + n = " + (k+n));}
}
}

PAGE 60
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

STRINGS IN JAVA
Sigerson Holmes: The clue obviously lies in the word ‘cheddar’. Let’s see now.
Seven letters. Rearranged, they come to, let me see: “Rachedd” “Dechdar”
“Drechad” “Chaderd” -- hello, “chaderd!” Unless I'm very much mistaken,
chaderd is the Egyptian word meaning “to eat fat”. Now we're getting somewhere!
From the film: Adventure of SherlocHolmes' Smarter Brother (1975)

Kermit: Durn, I missed. You know, that's the first thing to go on a frog? The
tongue. The tongue goes and you can't catch flies.
From: the Muppet Movie (1979)

Strings are a sequence of characters. As in C, Java does not have a built in type
called string. But what Java does have in its standard library [Link] is a class
called String. Notice that the first character is a capital, indicating that the
identifier is the name of a class, conforming to the recommendations laid out by
Sun Microsystems. Whenever you want to store zero or more characters in a
sequence you will need to create an instance of this String class. A string literal is
zero or more characters enclosed by double quotes (inverted commas). For
example;
"One Cup of Java and Cake Please";
" "; // an empty string.

In order for you to create an instance of the String class, thereby creating an
object, do the following;
String request = new String("One Cup of Java and Cake Please.");

What is happening here? Well, we have a class type called String. Just as we had
to create a variable of a primitive type, we need to create an object variable of a
class type. In our example, our object variable will have the identifying name
request. Notice how we have stuck to the Sun Microsystems recommendation of
starting all variable names with a lower case character. To create an object we need
to make use of the keyword new. new creates an object of the class template. To
expand on this let us look at an example;
class Employee{
:
: // method and data declarations
:
}

If we then typed the following code;


Employee vZapChap;

PAGE 61
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

vZapChap becomes a reference to an object of class Employee. It is not an object.


In order for an object of Employee to exist we need to do the following;
Employee vZapChap = new Employee("Java Junkie");

It is very important that you understand the preceding discussion. Notice how we
have made use of the new operator. Once this statement has been executed, heap
memory space is allocated to the object created. This object will be referenced by
vZapChap. Having said all this, the Java String class has some special built in
functionality, as it is used so often. Both statements below will create an object of
type String;
String request = new String("\nOne Cup of Java and Cake Please.");
String request1 = "\nOne Cup of Java and Cake Please.";

Where the second statement is really a shorthand version of the first.

Within each class there are a number of methods. A method in real terms is a
function and is associated with a class. As we have created an instance of class
String we may invoke methods on it, copy a reference to it etc.

Like all other literals in Java the String literal is immutable. In other words, once
a string literal has been created it cannot be modified. No character at all may be
changed. It is possible however to construct a new string out of pieces from
another. This is known as string concatenation. For example;
public class ZnoskoString{
public static void main(String args[]){
String name = "Znosko-Borovsky ";
String book = "in his excellent book, The Middle Game in Chess, ";
String statement = "says that there are three elements in chess, ";
String elements = "FORCE, TIME and SPACE.";

[Link]("\n"+name+book+statement+elements);
}
}

produces to following screen output;


Znosko-Borovsky in his excellent book, The Middle Game in Chess, says there
are three elements in chess, FORCE, TIME and SPACE.

PAGE 62
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

The following statement is also perfectly legitimate;


String viewerConsent = "PG" + 16; //viewerConsent becomes PG16

We indicated earlier, as we have an instance of the String class it is possible to


invoke methods on it. By the way, in the above example when we performed the
following;
String name = "Znosko-Borovsky ";

We actually called a method of the String class. It is called the constructor


method and is invoked whenever you create an instance of a class. Each class has
its own constructor method. Let us now look at some code that will call a method
that will extract a sub-string out of a String object.
public class SubStringing{
public static void main(String args[]){
String request = "One Cup of Java and Cake Please.";
String secondRequest = [Link](0, 15);
[Link](secondRequest);
}
}

Will produce the output:


One Cup of Java

Do you understand how this is achieved? Well the method called is:
substring(0, 15);

Remember, the format of invoking a method takes on the general form:


[Link](parameters);

In our example we have an object called request and is of type String. As


request is of type String it has access to all methods of the class. One of these
methods is the substring() method. This method requires that two parameters,
the point where the substring must start and its ending point be supplied. In our
example we pass the two arguments 0 and 15. We invoke the method by means of
the dot(.) operator.

Can you work out what the following code will produce on the screen?

PAGE 63
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

public class SubStringing{


public static void main(String args[]){
String request = "One Cup of Java and Cake Please.";
String secondRequest = [Link](0, 15);
String thirdRequest = [Link](20, [Link]());

[Link](secondRequest);
[Link]("\n\n" + thirdRequest);
}
}

How do we test two strings for equality? We make use of the equals() method.
The prototype of this method is;
public boolean equals(Object anObject);

To check for equality using this function we can do the following;


boolean b = [Link](str2);

Where str1 and str2 are objects of the String class. Notice how a boolean
value is returned. If str1 and str2 are equal then true is returned, otherwise
false is returned. You may ask, “What if we want to check and see if the two
strings are equal, but to ignore upper and lower case differences?” Well, the
String class has a method equalsIgnoreCase(). You would invoke it as
follows;
boolean b = [Link](str2);

BEWARE: of an extremely common error. You cannot use the equality operator
to evaluate whether two strings are equal. So the following is incorrect;
str1==str2;

Within the String class there are a number of other string handling features. These
are listed below and I have allocated each to a category. For a fuller discussion on
each of the methods described consult the Java documentation.

• For extracting a character from a String object use the following methods;
char charAt(int getfromhere);
// where getfromhere is an index of the location
// of the character you wish to extract.

void getChars(int starthere, int endhere, char puthere[], int atposition);


// where startfromhere is the index of the beginning of the substring,
// endhere is the end of the substring puthere[] is the character
// array that will receive the substring, and atposition is the index
// of the starting position of the substring in the puthere[] array.

char[] toCharArray();
// converts all the characters in a String object into
// a character array.

PAGE 64
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

• For performing string comparisons use the following String methods;


boolean regionMatches(int toffset, String other, int ooffset, int len);
// This method tests if two string regions are equal,
// where toffset is the index at which the region begins,
// other is the string being compared, starting at ooffset and ending len.

boolean regionMatches(boolean ignoreCase, int toffset, String other, int ooffset, int len);
// This method is the same as above but one can decide
// if case should be ignored or not.

boolean startsWith(String prefix);


// Tests if a string starts with the string prefix.

boolean startsWith(String prefix, int toffset);


// This method is the same as that above except that
// toffset indicates the point the search must begin

We have already discussed the following methods,


boolean equals(Object anObject);
// Compares this string to the specified object.

boolean equalsIgnoreCase(String anotherString);


// Compares this String to another String,ignoring case considerations.

• For performing string searches use the following String methods;


int indexOf(int ch);
// searches for the first occurrence of a character ch.

int indexOf(String str);


// searches for the first occurrence of a string str.

int indexOf(int ch, int startIndex);


// searches for the first occurrence of a character from startIndex onwards.

int indexOf(String str, int startIndex);


// searches for the first occurrence of a string from startIndex onwards.

int lastIndexOf( int ch);


// searches for the last occurrence of a character ch.

int LastIndexOf(String str);


// searches for the last occurrence of a string str.

int lastIndexOf(int ch, int startIndex);


// searches for the last occurrence of a character from startIndex onwards.

int lastIndexOf(String str, int startIndex);


// searches for the last occurrence of a string from startIndex onwards.

PAGE 65
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

• For performing string modifications use the following String methods;


String substring( int beginIndex);
// Returns a new string that is a substring of this string
// starting at the offset beginIndex.

String substring(int beginIndex, int endIndex);


// Same as above except that the substring returned
// starts at beginIndex and ends at endIndex of this string.

String concat(String str);


// Concatenates the specified string to the end of this string.

String replace(char oldChar, char newChar);


// Returns a new string resulting from replacing all occurrences of
// oldChar in this string with newChar.

String trim();
// Removes white space from both ends of this string.

• For performing case changes within a string use the following String methods;
String toUpperCase();
// Converts all of the characters in this String to upper case.

String toLowerCase();
// Converts all of the characters in this String to lower case.

In Java there are two other classes that allow you to work with ‘strings’. These are
the StringBuffer and the StringBuilder classes and are used for modifying
‘strings’. StringBuffer has been around since JDK1.0, whereas StringBuilder
was introduced in JDK5. You use a StringBuffer or StringBuilder when you
know that the character data will change. Declaring a StringBuffer or
StringBuilder object is done in the same way as declaring a String object. If
you can determine the maximum length of buffer you need, then you should
specify this when instantiating the class. Otherwise the length is determined at a
later stage within the program. As you add character data to the buffer so more
memory is allocated to the buffer. This requires overhead code to run in the
background and is therefore costly on resources. Which of these two classes should
you use? The recommendation is that you use StringBuilder rather than
StringBuffer as a StringBuffer is synchronized and therefore requires a
more resources to run. Essentially, StringBuilder is a drop-in replacement for
StringBuffer where synchronization is not required resulting in faster
performance.

PAGE 66
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

As it is possible to change the data in a StringBuilder object there are additional


methods you may use to effect these changes.
int capacity();
//Returns the current capacity of the StringBuilder.

void ensureCapacity(int minimumCapacity);


// Ensures that the capacity of the buffer is at least equal to the specified
// minimum. This allows you to preallocate enough space to hold a certain
// number of characters AFTER you have instantiated a StringBuilder object.

void setLength(int newLength);


// Sets the length of this StringBuilder. To the length contained in newLength.

StringBuilder insert();
// There are numerous overloaded methods accepting arguments of different types.
// What this method does is to insert the string representation of the data
// type argument into this StringBuilder.

StringBuilder reverse();
// The character sequence contained in this string buffer is replaced
// by the reverse of the sequence.

StringBuilder deleteCharAt(int index);


// Removes the character at the specified position found in index in
// this StringBuilder (shortening the StringBuilder by one character).

StringBuilder delete(int start, int end);


// Removes the characters in a substring of this StringBuilder starting at
// the index start and ending at the index end.

In summary:
The class String includes methods for examining individual characters of the
sequence, for comparing strings, for searching strings, for extracting substrings,
and for creating a copy of a string with all characters translated to uppercase or to
lowercase. The StringBuilder and StringBuffer classes offer the same, plus
more in that, you can add or remove characters from the buffer. The down side of
StringBuffer is that it is expensive on resources. For more information with
regards these classes (as well as all other classes) look at Java’s document file.

PAGE 67
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

STRING TOKENISING
Just as in the English language, Java is capable of breaking up strings into
individual components or “tokens”. This is known as parsing. So, parsing is the
division of text into a set of discrete parts (tokens), which in a certain sequence can
convey a semantic meaning. The StringTokenizer class provides the first step in
this parsing process, often called the lexer. Whenever you read a book the human
mind breaks the sentence into individual words. In Java there is a
StringTokenizer class. Its function is to break up a string into its component
tokens (or words). Each token is usually separated by a delimiter. A delimiter is a
character and is usually a white-space character. A white-space character is a space
(or blank), a tab, newline and carriage return. In Java a white-space character is the
default delimiter. We may therefore define a token as being any consecutive string
of visible characters delimited on both sides by white space.

You are not forced to use the default delimiters. It is perfectly legitimate to specify
your own delimiters. This may be done when instantiating a StringTokenizer
object or on a per-token basis. For instance if you want to specify your own
delimiters instead of using the default, all you need do is pass a string containing
your delimiters as an argument to the StringTokenizer constructor. For example
if a string you are wanting to tokenise is delimited by commas, semi-colons and
colons then you would execute the following when instantiating a
StringTokenizer object;
StringTokenizer myToken = new StringTokenizer(myStringToTokenize, ",;:");

In our example, the delimiters myToken object will use are the comma(,), semi-
colon(;) and colon(:)

There are numerous methods contained in the StringTokenizer class. Go and


peruse Java’s documentation.

Some of the more common methods you will use are;


public boolean hasMoreTokens();
// Tests if there are more tokens available from the string you wish
// to tokenise. If this method returns true, then a subsequent call to
// nextToken with no argument will successfully return a token. This method
// returns true if and only if there is at least one token in the string
// after the current position otherwise a false is returned.

public String nextToken();


// Returns the next token from the string you are wishing to tokenise.

public boolean hasMoreElements();


// Returns the same value as the hasMoreTokens method.

PAGE 68
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

public Object nextElement();


// Returns the same value as the nextToken method, except that its declared
// return value is Object rather than String.

Below is an example using the StringTokenizer class. Notice that I have


specified my own delimiter, that being an exclamation mark (!)

public class ReadToken{


static String myText = "Durn, I missed.!" + "You know that's the first
thing to go on a frog?!" + "The tongue.!" +
"The tongue goes and you can't catch flies.";
static String myDelimiter = "!";

public static void main(String[] args){


StringTokenizer myTokens = new StringTokenizer(myText, myDelimiter);
while ([Link]()){
String myNextToken = [Link]();
[Link](myNextToken);
}
}
}

The output you will see is;


Durn, I missed.
You know that's the first thing to go on a frog?
The tongue.
The tongue goes and you can't catch flies.

Recompile the above code, but this time use the default delimiters. Run it and see
the difference. By doing this and comparing the result with the above code and its
resultant output you should easily be able to understand how you may extract
tokens from a string.

When we look at Java input/output we will see tokenisation in operation. For


instance we will obtain a string from say the keyboard, then save it in a buffer and
then tokenise this string to obtain the information entered by a user.

As an aside:
In JDK1.4 Java introduced a new method to the String class called split(). This
method splits a string against a given regular expression and returns a char array.
The two signatures for the split() method are;
public String split(String regex)
public String split(String regex, int limit)

What split() does is that it decomposes the invoking string into parts and returns
an array that contains the result. Each part is delimited by the regular expression
passed in regex. The number of parts is specified by limit. If limit is negative,

PAGE 69
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

then the invoking string is fully decomposed. Otherwise, if limit contains a


nonzero value, the last entry in the returned array contains the remainder of the
invoking string. If limit is zero, the invoking string is fully decomposed, but no
trailing empty strings will be included.

Here is a simple example;


public class SplitTest{
public static void main(String[] args){
String str="Durn, I missed.! "
+"You know that's the first thing to go on a frog?!"
+"The tongue.! The tongue goes and you can't catch flies.";
[Link]("Split output ------>");
for(String retval:[Link]("!")){
[Link](retval);
}
}

This is what the output looks like once you run the example:
Split output ------>
Durn, I missed.
You know that's the first thing to go on a frog?
The tongue.
The tongue goes and you can't catch flies.

Here is a second example where we determine the number of strings (parts) we


want to decompose the ‘parsed’ string into. This example will split on a space as
described by the regular expression (regex) \\s:

public class SplitTest{


public static void main(String[] args){
String str="Splitting VZAP's world";
[Link]("Initial String: "+str);
[Link]("\nReturning all decomposed strings as limit is 0:");
for(String word:[Link]("\\s", 0)){
[Link](word);
}
[Link]("\nReturning one string as limit is 1:");
for(String word:[Link]("\\s", 1)){
[Link](word);
}
[Link]("\nReturning two strings as limit is 2:");
for(String word:[Link]("\\s", 2)){
[Link](word);
}
}

This is what the output looks like once you run the example:
Initial String: Splitting VZAP's world

Returning all decomposed strings as limit is 0:


Splitting
VZAP's

PAGE 70
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

world

Returning one string as limit is 1:


Splitting VZAP's world

Returning two strings as limit is 2:


Splitting
VZAP's world

PAGE 71
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

OUTPUT FORMATTING
JDK5 introduced a feature known as variable arguments or varargs. We shall
discuss this feature later. As a result of this feature, Java created a new method that
almost emulates Cs printf() function. Java also called it printf() and was
added to PrintStream class. It allows you to specify a precise format of the data
to be written. If you know C’s printf() function, you will have no problem
understanding Java’s version.

So far, whenever you have displayed something on your console (or via a stream)
you have been using print() and println(). The printf() method can also be
used. The difference is that it offers a lot more flexibility.

The printf() method has the following general forms:


PrintStream printf(String formatString, Object … args)
PrintStream printf(Locale loc, String formatString, Object … args)

In the above general form, the formatString argument is known as the format
string as it is a literal string that can contain zero or more format specifiers. The
args arguments is the data that will be applied to the format specifies in the format
string.

Here is a simple example showing how to use printf;


[Link]("%s", "One mug of Java please");

The format specification is the coded data that follows immediately after the format
character %. The general format of a format specifier is;
%[flags][width][.precision][argsize]typechar

and again, in a different representation;


% [-] [+-] [0-9] [.0-.9] (dfcsxXoeE)

• A format specifier is identified by the % sign as the first character.


[mandatory]
• A – [minus] symbol as the next character tells printf() to left align the data
item. [optional]
• A + [plus] or - [minus] symbol will tell printf() to display a “+” for
positive or a “-” for negative values. [optional]
• 0-9 determines the width of the field into which the data value will be
placed. [optional]

PAGE 72
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

• .0-.9 determines the decimal component’s (float or double) number of


decimal points. [optional]
• And finally the type char can be one of the following [mandatory]

d Decimal integer
u Unsigned decimal integer
o Octal integer
x, X Hexadecimal integer, lowercase or uppercase
z[n],Z[n] Integer base n, with n coded in decimal; include square brackets
f float, standard notation
e, E float, scientific notation (lowercase or uppercase exponent marker)
g, G Same format as %f or %e, depending on the value. Scientific
notation is used only if the exponent is greater than the precision or
less than -4.
s, S String, lowercase or uppercase
c Character
\n Line separator
n Counts characters

Here is an example using printf();

public class PrintfDemo {


public static void main(String args[]) {
[Link]("Here are some numeric values in different formats.\n");
[Link]("Various integer formats: ");
[Link]("%d %(d %+d %05d\n", 3, -3, 3, 3);
[Link]();
[Link]("Default floating-point format: %f\n",1234567.123);
[Link]("Floating-point with commas: %,f\n",1234567.123);
[Link]("Negative floating-point default: %,f\n",-1234567.123);
[Link]("Negative floating-point option: %,(f\n",-1234567.123);
[Link]();
[Link]("Line up positive and negative values:\n");
[Link]("% ,.2f\n% ,.2f\n",1234567.123, -1234567.123);
}
}

The output looks a follows;


Here are some numeric values in different formats.

Various integer formats: 3 (3) +3 00003

Default floating-point format: 1234567.123000


Floating-point with commas: 1,234,567.123000
Negative floating-point default: -1,234,567.123000
Negative floating-point option: (1,234,567.123000)

Line up positive and negative values:

PAGE 73
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

1,234,567.12
-1,234,567.12

When the % is encountered in the format string, the compiler knows that it has to be
interpreted in a special way. Notice that in the example above a ‘character’ follows
immediately after the %. If it is a d for example, the compiler knows that it must
interpret the corresponding argument as an integer and not as a float or string. If it
were an f, then the compiler would know that the corresponding argument must be
interpreted as a float. What do I mean by the corresponding argument? It is the
argument that corresponds in sequence to the format codes in the format string. So
looking at the following example;
[Link]("%d %(d %+d %05d\n", 3, -3, 3, 3);

• the blue d corresponds to the blue 3.


• the green d corresponds to the green 3.
• the purple d corresponds to the purple 3.
• the orange d corresponds to the orange 3.

The printf() method can handle as many variables and as many different data
types as you like. Just for your edification here are a number of printf()
examples you may find useful.

Control the width of an integer;


The %3d specifier is used with integers and means a minimum width of three
spaces, which by default will be right-justified:
printf("%3d", 0); 0
printf("%3d", 123456789); 123456789
printf("%3d", -10); -10
printf("%3d", -123456789); -123456789

Left-justifying an integer’s output;


To left-justify integer output add a minus sign (-) after the % symbol;
printf("%-3d", 0); 0
printf("%-3d", 123456789); 123456789
printf("%-3d", -10); -10
printf("%-3d", -123456789); -123456789

To zero fill an integer’s output;


To zero-fill your integer’s output, just add a zero (0) after the % symbol;

PAGE 74
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

printf("%03d", 0); 000


printf("%03d", 1); 001
printf("%03d", 123456789); 123456789
printf("%03d", -10); -10
printf("%03d", -123456789); -123456789

Here is a little collection of integer formatting examples showing a minimum width


specification, left-justified, zero-filled, and also a plus sign for positive numbers.
At least five wide printf("'%5d'", 10); ' 10'

At least five-wide, left-justified printf("'%-5d'", 10); '10 '

At least five-wide, zero-filled printf("'%05d'", 10); '00010'

At least five-wide, with a plus sign printf("'%+5d'", 10); ' +10'

Five-wide, plus sign, left-justified printf("'%-+5d'", 10); '+10 '

Here are some examples illustrating how to format floating-point numbers;


Print one position after printf("'%.1f'", 10.3456); '10.3'
the decimal
Two positions after the printf("'%.2f'", 10.3456); '10.35'
decimal
Eight-wide, two
positions after the printf("'%8.2f'", 10.3456); ' 10.35'
decimal
Eight-wide, four
positions after the printf("'%8.4f'", 10.3456); ' 10.3456'
decimal
Eight-wide, two
positions after the printf("'%08.2f'", 10.3456); '00010.35'
decimal, zero-filled
Eight-wide, two
positions after the printf("'%-8.2f'", 10.3456); '10.35 '
decimal, left-justified
Printing a much larger
number with that same printf("'%-8.2f'", 101234567.3456); '101234567.35'
format

PAGE 75
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

Here are examples showing how to format a string;


A simple string printf("'%s'", "Hello"); 'Hello'

A string with a minimum length printf("'%10s'", "Hello"); ' Hello'

Minimum length, left-justified printf("'%-10s'", "Hello"); 'Hello '

In the printf() method, like in the print() and println() methods, there is
another character that has special significance. This is the backslash ‘\’ character.
Like the %, it is followed immediately by a special character that is interpreted in a
special way. You know most of them already. We called them escape characters.
Here is a listing;

\n → Linefeed. \r → Carriage Return.


\f → Form Feed. \\ → Backslash.
\t → Horizontal Tab. \” → Double Quote.
\b → Backspace. \’ → Single Quote.
\a → Audible Alert. \v → Vertical Tab.

With the explanation and all the examples, I am sure you know how to use the
printf() method in Java. This is a brilliant utility, so make use of it. Incidentally,
we will discuss a formatting class later on in the course known as DecimalFormat.

PAGE 76
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

CONTROL FLOW
In Java there are a number of ways in which a program can proceed to another
statement;
a) The simplest is to complete the current statement then execute the statement
following. This is the default in Java.

b) Decisions and branching. Depending on the circumstance a different set of


actions must be able to be performed. In Java we have the if and the
switch statements to do this.

PAGE 77
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

c) Reiteration. This is where we execute the same piece of code over and over
again. In Java we have the loop statements for,for-each,while and do-
while.

for, for-each and while

do while

d) Jump statements namely break,continue and return.

PAGE 78
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

DECISION (CONDITIONAL) STATEMENTS


THE ‘IF’ STATEMENT
The syntax for the if statement is;
if(expression)
statement1;
statement2;

In this statement (expression) is evaluated and executes the associated statement,


statement1, only when the expression is evaluated to be true. After executing
statement1 then statement2 will be executed. If (expression) evaluates to
false, then the next statement, statement2 is executed. From this it should be
clear that (expression) must evaluate to a boolean type. For example;
public class TestCondition{
public static void main(String[] args){
int a=0, b=1;
if (a<b)
a=1;
}
}

In this example a=1 only if ‘a’ is less than ‘b’. If ‘a’ were greater than ‘b’ then the
statement would not be executed.

Note that statement1 can represent a block of statements. Remember that a block
begins with { and ends with }. For example;

public class TestCondition{


public static void main(String[] args){
int a=0, b=1, c;
if (a<b){
a=1;
b=2;
c=3;
}
}
}

PAGE 79
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

We can also use the else statement, which is optional. This allows us to execute a
single statement or a statement block when the if statement evaluates to false.

The general form is;


if(expression)
statement1;
else
statement2;

Here statement1 executes if (expression) evaluates to true. statement2 will


be executed if (expression) evaluates to false.

Does the following example make sense to you and do you think it will compile?
public class TestCondition{
public static void main(String[] args){
int a=5, b=1;
if(a)
b=10;
else
b=20;
[Link]("\nThe value of b = " + b);
}
}

The answer to the question is that the above example will not compile. The error
message generated by the javac compiler will read “Incompatible type for
if. Can’t convert to boolean.” If you are from a C or C++ background
beware of this as the above code is perfectly legitimate in that environment but not
Java. To correct the error, use the relational operators we looked at earlier. For
example;
public class TestCondition{
public static void main(String[] args){
int a=5, b=1;
if(a>b)
b=10;
else
b=20;
[Link]("\nThe value of b = " + b);
}
}

PAGE 80
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

Another example using relational operators. Notice how we have combined them;
public class TestCondition{
public static void main(String[] args){
int a=5, b=6, c=8, d=7, e=0;
if((a<b) && (c>d))
e=10;
else
e=5;
[Link]("\nThe value of e = " + e);
}
}

BEWARE: Be careful that you do not put a semi-colon in the wrong place. The
following example is logically incorrect;
if(expression);
statement1;

In this example statement1 will always be executed irrespective if (expression)


evaluates to true or false because there is a semi-colon after the
if(expression) line.

PAGE 81
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

NESTED ‘IF’ STATEMENTS


A nested if is the target of another if or else. Remember that an else statement
always refers to the nearest if statement that is within the same block. For
example;
public class TestCondition {
public static void main(String[] args){
int i=10, j=12, k=3;
if(i>=0){
if(j>k)
statement1;
if((k<i)&&(k>j))
statement2;
else // this else is associated with if ((k<i)&&(k>j))
statement3;
}
else // this else is associated with if (i>=0)
statement4;
}
}

PAGE 82
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

MULTIPLE NESTED ‘IF’ STATEMENTS


The general syntax is;
if(expression_1)
statement1;
else
if(expression_2)
statement2;
else
if(expression_3)
statement3;
else
if(expression_4)
statement4;

Once a condition is evaluated true, the associated statements are executed. Then
execution begins at the first statement following all of the else if(), and any
else, statements associated with one specific if() statement. In other words, once
one else if() statement evaluates true, no other else if() statement will be
evaluated.

One thing about these if-else-if ladders is that you can easily become confused
in matching the if and else statements, especially when the code is not clearly
indented. A very useful alternative to this if-else-if ladder is the switch
statement, which we will look at later.

PAGE 83
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

THE ? OPERATOR
The ? operator is a ternary operator and is used as an alternative to the if-else
statement. The syntax is;
(expression1) ? expression2 : expression3;

This expression consists of three parts and operates as follows;


(expression1) is evaluated. If it is true then expression2 is evaluated and
becomes the value of the expression. If on the other hand (expression1)
evaluates to false, expression3 is evaluated and becomes the value of the
expression. For example;
public class TestCondition{
public static void main(String[] args){
int x=10, y=0;
y = x>9 ? 100 : 200;
}
}

This above example reads; “if x is greater than 9 then y=100 otherwise y=200”.

Java will allow the ? operator to be used in places where normal if else
statements would not be allowed. Consider the following example;
public class TestCondition {
public static void main(String[] args){
int a=3, b=1;
[Link]("\nValue is = " +((a<b)?1:100));
}
}

Can you work out what is happening in the code above?

PAGE 84
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

‘SWITCH’ STATEMENT
When we looked at the multiple nested if statement we said that a useful
alternative to it is the switch statement. This statement is equivalent to the
‘switch’ statement in C. The general form of the switch statement is;
switch(expression){
case const_expression_1:
statements;
break;
case const_expression_2:
statements;
break;
case const_expression_3:
statements;
break;
:
:
default:
statements;
}

What the statement does is to test the value of an expression against a list of
constants, and then branches accordingly. For versions of Java prior to JDK7, the
constant expression must be of type int, byte, short, char, (but not long) or
enum (enumeration). Enumerations will be described in due course. Starting with
JDK7, expression can also be of type String. If the switch variable does not
match any of the case constants, control then goes to the default keyword which
is usually at the end of the switch statement. It is useful using this default
because basically it acts as an else statement. For instance; “if none of the above,
then do this”. If you do not have this default keyword, then the whole switch
statement simply terminates when no match is found.

Note the keyword break. When break is encountered in a switch, the program
execution exits the switch statement and executes the line of code following the
switch statement block. If this is not encountered the program will not only
execute the statements for a particular case, but all the statements for the following
cases as well. So beware: do not forget the break statements.

PAGE 85
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

An example of a switch statement is;

import [Link];

public class Tester{


public static void main(String[] args){
int value=0;
char ch;
try{
[Link]("Enter a value between 1 and 5: ");
value=[Link]();
ch=(char)value;
switch(ch){
case '1':
[Link]("\n You pressed 1");
break;
case '2':
[Link]("\n You pressed 2");
break;
case '3':
[Link]("\n You pressed 3");
break;
case '4':
[Link]("\n You pressed 4");
break;
case '5':
[Link]("\n You pressed 5");
break;
default:
[Link]("\n You did not press a number between 1 and 5!!");
} //switch
} //try
catch(IOException e){
[Link]("IO ERROR: "+e);
}
}//main
}

If you are using JDK7 or above, you can now switch on a string instance. Here is
an example;

class StringSwitch{
public static void main(String args[]){
String str="vzap";
switch(str){
case "switch":
[Link]("String is: switch");
break;
case "on":
[Link]("String is: on");
break;
case "vzap":
[Link]("String is: vzap");
break;
default:
[Link]("String is: not matched");

PAGE 86
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

break;
}
}
}

Running this program would result in the following appearing on you console;
String is: vzap

Should you change the value contained in str from “vzap” to “flibflob” the
output will be;
String is: not matched

Lastly, it is possible to use a switch as part of the statement sequence of an outer


switch. This is called a nested switch. Since a switch statement defines its own
block, no conflicts arise between the case constants in the inner switch and those
in the outer switch. Here is an example of a nested switch;
switch(count){ // Outer switch
case 1: // case 1 for outer switch
switch(target){ // Nested switch
case 0: // case 0 for nested switch
[Link]("target is zero");
break; // break for case 0 nested switch
case 1: // case 1 nested, no conflicts with outer switch
[Link]("target is one");
break; // break for case 1 nested switch
}
break; // break for case 1 outer switch
case 2: // case 2 for outer switch
:
:

PAGE 87
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

LOOPS
Loops are also known as iteration statements. They allow a set of instructions to be
repeated until a certain condition is reached. There are four loop statements in Java,
namely while, for, for-each and do-while.

THE ‘WHILE’ LOOP


The general form of the while statement is;
while(expression)
statement;

Here the expression is evaluated. Now if it evaluates to true then statement is


executed, and the expression is re-evaluated. This process continues until
expression evaluates to false. Once this happens the program continues
executing after statement. Remember that statement can be either an empty
statement, a single statement or a statement block enclosed in {} brackets.

In the while loop statement, expression is evaluated BEFORE the statement


section. So it is possible that the loop may never be executed at all if expression
evaluates to false the first time it is checked. An example of the while loop is;

public class TestWhileLoop{


public static void main(String[] args){
int i=0;
while(i<=10){
[Link]("i is: " + i);
i++;
}
}
}

Another example;
public class TestWhileLoop2{
public static void main(String[] args){
int a=1;
while(a<100)
a++;
[Link]("a is: " + a);
}
}

This above example prints ‘a is 100’. Do you understand this example?

PAGE 88
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

Beware of the following COMMON ERROR. Do not place a semi-colon on the


same line as the while statement. For example the following is logically incorrect.
while(.......);

This statement will loop without performing any useful task as it terminates in a
semi-colon.

PAGE 89
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

THE ‘FOR’ LOOP


The for loop is a special form of the while loop. The general form of the for loop
is;
for(initialization ; condition ; increment)

Notice that the loop expression is divided by semi-colons into three separate
expressions.

The initialization expression initialises the loop control variable. This part of
the expression is always executed as soon as the loop is entered into. We can
initialize the variable to any desired value. Initialization is only executed once,
and that is when we enter the loop for the first time. The for loop is just like the
while loop in that the loop condition is tested BEFORE the statements within the
loop are executed.

The conditional expression is a relational expression that determines when the


loop will exit. While the conditional expression is true the loop statements are
executed. However as soon as it becomes false, the loop is exited, and the
program statement following the for loop is executed.

The increment defines how the loop control variable will change each time the
loop is repeated.

Just as in the while loop, statement can be a single statement or a statement


block enclosed by {} brackets. Example;
public class TestForLoop{
public static void main(String[] args) {
for(int a = 10 ; a>=0 ; a--)
[Link]("a is: " + a);
[Link]("Bong!!!");
}
}

The program prints the following on the screen;


a is: 10
a is: 9
a is: 8
:
:
a is: 0
Bong!!!

PAGE 90
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

When a < 0 (a is less than zero) the loop is exited.

What we have discussed so far is the most common form of the for loop. There are
however some variations to this loop statement that makes it very powerful.

A common variation is to allow two or more variables to control the loop.


However, the comma delimiter may only be used in the initialization and
incrementation sections not the conditional section. A comma must separate
these variables. The actual meaning of comma delimiting in Java is “do this and
this”. For example;

public class TestForLoop2{


public static void main(String[] args){
for(int a=10, b=0 ; a>=0 ; a--, b++){
[Link]("a is: " + a + " b is: " + b);
}
[Link]("Bong!!!");
}
}

In this example notice how a is used to control the loop in the condition section of
the statement. Both variables are initialized. a=10 and b=0 in the initialization
section of the statement. Each of the three sections of the for loop may consist of
any valid Java statement. The following is perfectly legitimate (where request is
an instance of String);
for (i=1, j=[Link]() ; i<j ; i++, j--){
:
:
}

Remember that in Java a statement may be empty, so the following is perfectly


legitimate;
for(;;);

What happens here is that the loop goes on forever. It is an infinite loop.

PAGE 91
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

THE ‘DO WHILE’ LOOP


Now unlike the while and for loops, the do while loop is always executed at
least once before the loop condition is tested. In the do while loop, the loop
condition is tested at the bottom of the loop. The general form of the do while
loop is;
do{
statement;
}while(condition);

Just like all the other cases statement can be a single statement or a statement
block enclosed in {} brackets.

Once the loop is executed for the first time, the condition is checked. If it is true
then it is repeated. If however it is false, the loop is exited. Please remember that
the do while loop is always executed at least once before condition is
evaluated.

An example of a do while loop;

public class TestDoLoop{


public static void main(String[] args){
int count = 0, total = 0;
do{
total += count;
[Link]("Count = " + count++ + " Total = " + total);
}while(count<10);
}
}

Can you work out what the output will be? Notice the ‘short cuts’ being used.

PAGE 92
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

THE ‘FOR-EACH’ LOOP


Beginning with JDK5, the basic for loop was extended to what we call the
‘enhanced for’ or ‘for-each’ style loop. It is a special form of the for loop making
iteration over arrays and other forms of collections much more convenient and
succinct. The general form of the ‘for-each’ version of the for loop is;
for(type itrVar : collection)

Here, type specifies the data type and itrVar specifies the name of an iteration
variable that will receive the elements from a collection, one at a time, from
beginning to end. The collection being cycled through is specified by collection.
There are various types of collections that can be used with the for, but we will
only look at the array for the moment. Other types of collections that can be used
are Maps, Lists, Sets, etc as defined by the Collections Framework. We will be
discussing collections later on in the course.

With each iteration of the loop, the next element in the collection is retrieved and
stored in itrVar. The loop repeats until all elements in the collection have been
obtained. Because the iteration variable receives values from the collection, type
must be the same data type as (or compatible with) the elements stored within the
collection.

To demonstrate the for-each loop, here is a very simple example. What we are
doing is assign values to a collection, in this instance it is an array of integers, we
called numberCollection. We then iterate through this array. Upon each iteration
an element in the array is assigned to itrVar and then print its value to the
console, as well as summing each together as we proceed;

public class ForEachExample1{


public static void main(String[] args){
int numberCollection[]={1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
int sum=0;
for(int itrVar : numberCollection){
[Link]("Value is: "+ itrVar);
sum+= itrVar;
}
[Link]("\t -----");
[Link]("Total is: "+sum);
}
}

PAGE 93
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

Running this example produces the following result on your console:


Value is: 1
Value is: 2
Value is: 3
Value is: 4
Value is: 5
Value is: 6
Value is: 7
Value is: 8
Value is: 9
Value is: 10
-----
Total is: 55

To understand the motivation behind a for-each style loop, here is the same
example, but this time using the conventional for loop;
public class ForExample{
public static void main(String[] args){
int numberCollection[]={1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
int sum=0;
for(int itrVar=0; itrVar<10;itrVar++){
[Link]("Value is: "+ numberCollection[itrVar]);
sum+= numberCollection[itrVar];
}
[Link]("\t-----");
[Link]("Total is: "+sum); }
}

Essentially the for-each form of loop eliminates the need to establish a loop
counter, specify a starting and ending value, and manually index the array. Instead,
it automatically cycles through the entire array, obtaining one element at a time, in
sequence, from beginning to end.

Although the for-each form of loop may make code much cleaner and simpler to
understand, it cannot be used in all situation situations. So, for-each loops;
1. are not appropriate to use when you want to modify elements within a
collection.
2. do not keep track of its index, meaning that you cannot obtain a collection’s
index.
3. only iterate forward over a collection in single steps.
4. cannot process two decision making statements at once. In other words, you
cannot compare two structures or two elements.

PAGE 94
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

JUMP STATEMENTS
In Java there are three statements that will perform an unconditional branch. The
statements are; return,break and continue.

return: To return a value from a method this is used.

break: We saw this when we looked at the switch statement. There is however
a second use for the break statement, and that is to force immediate
termination of a loop regardless of the result of its test for truth. For
example;

while (this is true){


:
:
break;
:
}
// When break is encountered program execution continues from here

continue: This does the opposite to the break statement. It is found only in the
body of a loop statement. When it is encountered it takes program
execution back to the beginning of the loop (i.e. to the conditional tests
in the while and the do while loops). In other words causing control
to pass to the next iteration of the loop bypassing any statements that
have not yet been executed. This statement makes the program difficult
to read and is generally not used. An example (a segment of code);
months: for(int m=1; m<=12; m++){
//do something
//nested loop
for(int d=1; d<=31; d++){
//do a daily something
if(m==2 && d==28)
continue months;
//Otherwise do something else
}
etc...
}

PAGE 95
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

ARRAYS IN JAVA
An array is a collection of variables of a certain data type. These variables are then
referenced by a common name. In an array the lowest address in memory is
associated with the first element, and the highest address with the last element.
Arrays in Java are similar looking to arrays in C. This is where the comparison
ends. Array types are reference types in Java. In other words the array variable (i.e.
the name you give the array) is really a reference. In Java, arrays are objects. This
therefore implies that operations common to all objects can be performed on arrays.

The general form for declaring an array is;


type array_name[];

OR

type[] array_name;

Either method of array declaration is correct. The use of the square brackets
indicates the declaration of an array. Those persons emerging from the C paddock
will recognise the first form of the declaration. Those starting off in the Java arena
will tend to use the second form of array declaration.

To declare an array of 100 int’s, do the following;


int[] arrayOfInts;

Where int is the data type, [] the array declaration and arrayOfInts (could have
been any name you wish) the array name. What is extremely important to
understand when working with arrays, is that when we perform the above
statement, all we have done is to create a variable that can hold an array. We still
have to create the array itself. We said that we want an array that could contain 100
integers, so once we have the variable we can now create the array. This is done as
follows;
arrayOfInts = new int[100];

This statement creates an array of 100 int’s, that are numbered from 0 through 99.
Those from a C background: be extremely careful that you do not use the C syntax
for declaring an array in Java. This is a common error. Therefore the following
code is incorrect;
int arrayOfInts[100]; //wrong, wrong, wrong.

PAGE 96
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

Only when we create the array using the new operator do we enter the array size.
You do not need to declare and create an array on separate statement lines. It can be
done in one statement. The following is perfectly legitimate;
int[] arrayOfInts = new int[100];

Notice that when we create an array we make use of the new operator. You will see
the use of this operator a lot when we start to work with objects. Once we have
declared and created an array, we need to fill the individual array elements. To
access each one of these elements you use a valid integer expression inside the []
brackets. Types byte, short, char and int are valid. Note however, the use of a
long is not allowed. In actual fact, types byte, short and char are all converted
to type int when they are used as indexes inside the [] brackets. An example of
initializing each element of an array is;
int[] arrayOfInts = new int[100];
for(int i=0; i<100; i++)
arrayOfInts[i] = i; //fills an array from 0 to 99

There is also a short hand method of declaring, creating, as well as initializing an


array all at one time. This is convenient for smaller arrays;
int[] someArray = {1, 2, 3, 4, 5};

The above statement is shorthand for the following;


int[] someArray = new int[] {1, 2, 3, 4, 5};

The above discussion and examples have revolved around arrays containing
primitive types. What happens if the elements within an array need to store
reference types? (i.e. objects). To declare the array is the same. For our discussion
let us assume I have a class that we have created called MyClass, and we now wish
to store ten instances of this class in an array called myArray. The first thing we
would do is to declare and create the array as follows;
MyClass[] myArray = new MyClass[10];

We now need to initialize each element of the array with an instance of MyClass;
for(int cnt = 0; cnt<10; cnt++)
myArray[cnt] = new MyClass();

Each element in myArray now contains an object of MyClass. Failing to create


these objects in an array of reference types is a very common error. So beware;
initialize all elements of an array. If you receive a NullPointerException error,
check your code to make sure you have not made this mistake. By the way, who
said there are no pointers in Java if Java generates this type of exception error?

PAGE 97
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

Once an array has been created and initialized, you can then access and manipulate
the individual array elements. Note however, you cannot change the size of the
array once it has been created. The only way to increase (or decrease) an array size
is by creating a new array of the desired length and then copy the required contents
of the “old” array across to the “new” array. For this to be successful both arrays
must be of the same type and you should make use of the arraycopy method
found in the System class. The signature of this method looks as follows;
[Link](fromArray, fromArrayIndex, toArray, toArrayIndex, count);

Let us look at an example of copying an array. Let us assume that we have two int
arrays. The first array we shall call arrayPrime and initialize it with the first eight
prime numbers. The second we shall call arrayTwo and initialize the five elements
it contains to 0(zero). Graphically they look as follows;

arrayPrime → 2 arrayTwo → 0
3 0
5 0
7 0
11 0
13
17
23

Let us now say that we want to copy the fourth, fifth and sixth elements of
arrayPrime to elements three, four and five of arrayTwo. The code to do this is;

public class ArrayCopyExample{


public static void main(String[] args){
int[] arrayPrime = {2,3,5,7,11,13,17,23};
int[] arrayTwo = {0,0,0,0,0};

for(int i=0; i<[Link];i++)


[Link]("Element " + i + " of arrayTwo before copy: " + arrayTwo[i]);
[Link](arrayPrime,3,arrayTwo,2,3);
for(int i=0; i<[Link];i++)
[Link]("Element " + i + " of arrayTwo AFTER copy: " + arrayTwo[i]);
}
}

The output produced by this program will be;


Element 0 of arrayTwo before copy: 0
Element 1 of arrayTwo before copy: 0
Element 2 of arrayTwo before copy: 0
Element 3 of arrayTwo before copy: 0
Element 4 of arrayTwo before copy: 0
Element 0 of arrayTwo AFTER copy: 0
Element 1 of arrayTwo AFTER copy: 0
Element 2 of arrayTwo AFTER copy: 7
Element 3 of arrayTwo AFTER copy: 11
Element 4 of arrayTwo AFTER copy: 13

PAGE 98
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

Do you understand this code? Notice the use of the [Link] statement in
the conditional section of the for loop. The value within length indicates the
number of elements within an array i.e. the size of the array. Beware of calling
length() as it is a method, not a data field.

You may also clone an array. What cloning an array does, is to create a new array
and then perform a bit-to-bit copy of the array being copied. When we used the
arraycopy() method you had to supply an already created array, of the correct
data type. Then using this method we could copy the desired elements across to this
new array, as long as they were contiguous in memory. Cloning on the other hand
creates the new array and makes a copy of the complete array. When cloning, you
must cast to the correct type. For example;
int[] arrayInt1 = new int[10];
int[] arrayInt2 = (int[])([Link]());

We are sharing features of the Java Object class. This class contains a clone()
method. Notice how we have dynamically performed a typecast by the following;
(int[]).

In Java it is possible to have arrays-of-arrays. We can consider these as being a


form of multidimensional array. To declare an array-of-array the syntax is;
type[][] arrayName;

As before, all we are doing here is declaring an array of specific type. After this we
must instantiate each element in the top most array and at least one element of the
bottom array using the new operator. To visualize an array-of-array the following
graphic should assist;
array1[c]

array1[r][c]

PAGE 99
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

Initializing these arrays can be done in a number of different ways. Two methods
are shown below.
int[][] dim2Array = new int[][]{ {0},
{0, 1},
{0,1,2},
{0,1,2,3}
};
OR

int[][] dim2Array = new int[4][];


for(int i = 0 ; i<[Link]; i++){
dim2Array[i] = new int[i+1];
for(int j=0; j<=i ; j++)
dim2Array[i][j] = j;
}

Notice that we did not initialise the array immediately upon creation in the second
example. What we had to do however is to instantiate the most significant
dimension (i.e. new int[4][]). Because we initialized the array upon creation in
the first example, we did not have to explicitly declare the most significant
dimension.

It is possible to have two different references to the same array. Any changes to the
array made through the one reference variable will be seen through the other
variable. For example we have the following declaration;
int[] arrayOne = {10, 20, 30, 40, 50};
int[] arrayTwo ;

This can be shown graphically as;

arrayOne
10
[Link] == 5 20
30
40
50

arrayTwo
null
[Link] == 0

We now execute the following statement;


arrayTwo = arrayOne;

PAGE 100
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

The reference variable in arrayOne is simply copied to arrayTwo. Graphically this


now becomes;

arrayOne
10
[Link] == 5 20
30
40
50

arrayTwo

[Link] == 5

If we now execute the following statement;


arrayTwo[2] = 1000;

results in a change in the third array element. This is shown below;

arrayOne
10
[Link] == 5 20
1000
40
50

arrayTwo

[Link] == 5

If we now execute the following line of code;


[Link]("The new value is: " + arrayOne[2]);

The output produced on the standard output, namely the screen will be;
The new value is: 1000

Finally those who are from the C background should note a few things;
• In Java, arrays are never allocated on the stack, they are allocated to heap space.
This prevents you getting into all that trouble that C allowed.
• In Java, you cannot exceed the bounds of an array. The compiler checks for all
array indexing. Should you exceed the array size, an exception is generated. In
C this did not happen.

PAGE 101
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

CASTING
Casting is the process of converting one data type to another. In other words,
casting is the conversion of values of one type to another, compatible type. We are
able to cast primitive data types as well as classes, which are in real terms user
defined data types. If the two types are compatible, then Java will perform the
conversion automatically. For example, it is always possible to assign an int value
to a long variable. However, not all types are compatible, and thus, not all type
conversions are implicitly allowed. For instance, there is no automatic conversion
defined from double to byte. Fortunately, it is still possible to obtain a conversion
between incompatible types. To do so, you must use a cast, which performs an
explicit conversion between incompatible types. Let us look at an example using
primitive types;
double d = 3.14159;
int i = (int)d;

In this example notice how we are explicitly casting from a double to an int
value. The type to which we are wanting to cast is placed in ( ) braces before the
type from which we are wanting to cast. So, the double variable d is converted into
an integer i and the fractional part of d is discarded.

A few things to note on casting primitive types are;


• Casting can lead to a loss of information. This happened in our example above
where the fractional component of d was dropped when it was cast to i.
• Casting to a smaller integer type results in the left most bits being eliminated.
• When casting numeric types the sign is maintained.
• You cannot cast to or from a boolean type.

In Java you may also perform conversion on classes. You may do the following;
• Cast from a subclass to a superclass.
• Cast from a superclass to a subclass

However, you are not allowed to cast between sibling classes. Let us look at an
example of casting.
public class Reptile { … }
public class Snake extends Reptile { … }
public class Crocodile extends Reptile { … }

Reptile rep;
Snake moleSnake = new Snake();
Crocodile zambeziCroc = new Crocodile();

PAGE 102
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

You can always make a more generalized object hold a more specialized one
without the need to explicitly cast. Casting from subclass to superclass is
completely reliable. When an object of a subclass is cast to an object of the
superclass, this is sometimes referred to as “widening”. So the following is
perfectly legitimate;
rep = moleSnake; // the same as rep = (Reptile)moleSnake;

Casting from a superclass to a subclass cannot be done automatically. This has to


be performed explicitly. The process of doing this is known as “narrowing”. The
reason why it cannot be done automatically is because the compiler has no way of
knowing if the object being cast is an instance of the subclass. So when casting
from a superclass to a subclass the cast is checked at run-time. If the object is found
not to be an instance of the subclass, then a ClassCastException will be raised.
So to cast from a superclass to a subclass we do the following;
moleSnake = (Snake)rep;

If we did the following a compilation error will occur;


moleSnake = rep; //No No

If you try and cast between siblings of the same superclass you would also generate
an error. For example you cannot do the following;
moleSnake = zambeziCroc; //No

So in summary you can cast;


• superclass = subclass
• subclass = (subclass)superclass

PAGE 103
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

JAVA PACKAGES
Java has a unique way of storing classes. It stores all related classes in a
hierarchical structure known as packages. When you create a new class then this
class needs to be stored in a package. To do this to inform Java of where you
would like to store this newly created class. Using the keyword package does this.
This must appear in the first line of your code. Its syntax looks as follows;
package [Link];

Where;
• package is the Java keyword,
• identifier is the ‘path’ and
• ClassName is the name of the class.

Visualize this hierarchy as a directory structure. Sun Microsystems recommends


that when you create new classes and is storing them in a package, then that
package needs to be unique. The reason for this amongst others is so that you do
not attempt to store your newly created class in a package that contains a class by
the same name. To ensure that your path is unique, make use of your company’s
Internet domain name, in reverse. As each domain in the world is unique there is no
chance another package will ever be the same. So for instance, if we created a new
class by the name of SerialComms we can save it in a package starting with
[Link], which is Van Zyl and Pritchard’s unique Internet domain name. So in
your code you would enter;
package [Link];

This can be visualized as: com\vzap\input;

Our class SerialComms will be present in the input directory. If we now created a
new class called ParallelComms, we could place the same package name in the
first line of our code. This will then result in the SerialComms class and the
ParallelComms class residing in the same ‘directory’. Our code framework would
look something like the following;

PAGE 104
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

//declaring our SerialComms class


package [Link];

public class SerialComms{


. . .
}

and;

//declaring our ParallelComms class


package [Link];

public class ParallelComms{


. . .
}

You should declare your classes to be public if you want universal access to the
class. If you do not declare a class to be public, then your class may only be used
by other classes in the same package. Once you have created classes and put them
into packages, you may now use your classes in your code. Note: if you create
classes and do not specify a package, Java itself will place them in a default
package. This is a package that has no name. Generally speaking, the default
package is only for small or temporary applications or when you are just beginning
development. Otherwise, classes and interfaces belong in named packages.
Incidentally, if you put multiple classes in a single source file, only one may be
declared public and it must share the name of the source file's base name. Only
public package members are accessible from outside the package.

When you start to use your classes you need to inform Java of where to find your
packages and where the compiled code must reside. To do this you need to create
an appropriate directory. You can use any directory name you like, but we at VZAP
will conform to setting up a classes directory off the C drive in Windows, or in
your home directory in Linux. As this directory is not automatically set up, you
must do it explicitly. In windows create your new classes directory in the Java
directory you created when setting up your system initially. For example;
C:\Java\classes

In Linux create your new classes directory in the your home directory, for
example;
~/classes

Once you have done this, modify your CLASSPATH system variable by appending
this path to the end of it. Do you remember how to do this? In windows set-up the
CLASSPATH environment in the [Link] file. This is a simple task of
declaring your directory. For our example mine looks as follows;
set classpath=.;..;c:\Java\classes;

PAGE 105
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

set path=c:\Java\jdk1.8.0_102\bin;

And in Linux edit the startup file ~/.bashrc or ~/.bash_profile or


~/.profile. For all the users globally, then you can add it to /etc/profile file.
export JAVA_HOME=/usr/lib/jvm/java-8-oracle
export CLASSPATH= .:..:~/classes:

Remember to ‘refresh’ the environment.

Now to make sure that all one’s packages are unique we said that we would use an
Internet domain name enforcing this uniqueness. Below is a screen capture of a
directory structure demonstrating this;

Notice how we have created the directory structure. From our example earlier our
SerialComms and ParallelComms classes will both be found in the
c:\Java\classes\com\vzap\input directory.

What many developers do is to zip-up all their packages together into a .jar file.
This can be useful because you can place this jar file in any directory you wish,
where the path to the jar file is defined in the CLASSPATH or we could place this
jar file in the ..JAVAHOME\jre\lib\ext directory. Java automatically goes to
this directory and searches for jar files and if present is able to read the class.

If we now write a program that is going to use our classes, we then need to inform
our program of where to find the classes we are using. Let us assume that our
program wishes to use the SerialComms and ParallelComms classes found in our
[Link] package. Within our code we can write the full path to create an
instance of each class. For example;
[Link] MySerial = new [Link]();
[Link] MyParallel = new [Link]();

This works, but is quite cumbersome, as every time you create an instance of the
classes you need to type the whole package name. A better way is to use the
keyword import. This informs Java where to look for your classes. This import
statement must appear after the package statement (if one is present) but before

PAGE 106
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

any other statements. Each time you need to create an instance of a class you just
needs to list the class name. For example;
import [Link];
import [Link];
:
SerialComms mySerial = new SerialComms();
ParallelComms myParallel = new ParallelComms();
:

This is slightly easier, and is the way to do it. If you are accessing more than one
class in the [Link] package as we are in this example, you can use a
wildcard character in the import statement. For example the above code can be
changed to the following;
import [Link].*;
:
SerialComms mySerial = new SerialComms();
ParallelComms myParallel = new ParallelComms();
:

This means that we have access to ALL classes in the [Link] package.
Let us assume that we have another package [Link]. Then access to
all classes found in this and the [Link] package could be indicated as;
import [Link].*;
import [Link].*;

The principle is exactly the same when using packages supplied with the JDK. You
will often see;
import [Link];
OR
import [Link].*;

Having said all that, I would REALLY recommend you stipulate each class in the
import statement rather than using the wildcard character. So do this;
import [Link];
import [Link];

Instead of this;
import [Link].*;

As your code is far more readable.

There is one package that is automatically imported into every Java program. This
is the [Link] package and it contains basic language support. You therefore
does not need to explicitly import this package. The number of import statements
is unlimited. So in summary, the * indicates that all classes in a package are to be

PAGE 107
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

imported. Importing a class makes it visible and means that one does not have to
write out the fully qualified name when you use a method or field from that class.

Scope of Packages
• If a class is declared public it is then visible from anywhere.
• If the class is declared protected it is then visible to all classes in the same
package as well as any subclasses.
• If the class is declared default, it is then only visible to the package itself and not
any of its subclasses.
• If the class is private it is hidden inside the class itself and only class members
have access.

One last note on packages. If you are storing your .java file in a different
directory in which the .class file is going to be stored then you will need to make
use of the flag –d when compiling your code. For instance, if your source code
(.java file) is in the directory c:\myprogs\mytest in Widows or ~\mytest in
Linux and it contains the statement line;
package [Link];

Then to ensure that the compiled code is in the Java\classes\com\vzap\input


directory you will need to type the following at the command line when compiling
your code;
In Windows
javac –d c:\Java\classes [Link]

Or in Linux
javac –d ~\classes [Link]

This means that the directory specified in your package name should be placed in
the directory c:\Java\classes (Windows) or ~\classes (Linux). If you now go
and look in the directory structure c:\Java\classes\com\vzap\input
(Windows) or ~\classes\com\vzap\input (Linux) you should see a
[Link] file.

JDK5 introduced the concept of static imports. What this means is that you are
now able to import the static members of a class and then use those members
without requiring a reference to their class. As an example let us look at the Math
class. All its class members are defined as static. Before JDK5 you had to
precede any method call to the method with the name of the class. For instance;
[Link]();

PAGE 108
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

However from JDK5 and above you simply call the method. To do so you MUST
declare a static import. For instance;
import static [Link].*;

Here is an example illustrating both approaches. First the old way;


import [Link].*;

public class StaticTest{


public static void main(String[] args){
for(int i=0;i<5;i++){
[Link]("Value = "+[Link]());
}
}
}

And the new way, from JDK5 onwards. Notice;


1. the static keyword in the import statement,
2. No class name prepending the random method.
import static [Link].*;

public class StaticTest{


public static void main(String[] args){
for(int i=0;i<5;i++){
[Link]("Value = " + random());
}
}
}

In summary of static imports: All the methods that are defined as static in any
class can be used directly without any reference to their host class, providing that
you import those static members of a class at the top of your code. It is axiomatic
that if the classes are not declared as static members, and you need to invoke them,
you will continue using the import statement in the standard way.

PAGE 109
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

CLASSES AND OBJECTS


As mentioned at the beginning of the course, Java is an object oriented
programming language. We have been making continual reference to classes,
objects, methods, instance variables etc. The whole idea of OOP’s is to break down
complex problems into smaller, understandable units.

There are four key principles to object oriented programming;


1. Abstraction
2. Encapsulation
3. Inheritance
4. Polymorphism

Books and theses have been written on these topics, so I will not go into detail here
suffice to say that I’ll present a small explanation of each. Grady Booch in his book
“Object Orientation Analysis and Design with Applications, Second Edition”,
defines;
1. Abstraction: as the essential characteristics of an object that distinguish it
from all other kinds of objects and thus provides crisply-defined
conceptual boundaries relative to the perspective of the viewer; The
process of focusing upon the essential characteristics of an object.

2. Encapsulation: is the process of compartmentalizing the elements that are


performed on that data, within an abstraction, are treated as a single unit
of organization. Encapsulation is also a way of restricting access to the
internal representation of an object.

3. Inheritance: is the relationship between classes, wherein your class shares


the structure or behavior defined in one …other class. Inheritance defines
an “is-a” hierarchy among classes in which a subclass inherits one …
superclass; in a subclass typically specializes its superclass by
augmenting or redefining existing behavior.

4. Polymorphism: is a concept in type theory, according to which a name


(such as a variable description) may denote objects of many different
classes that are related by some common superclass; thus any object
denoted by this name is able to respond to some common set of
operations in different ways.

PAGE 110
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

Abstraction and encapsulation in Java will be discussed later in the course whereas
we shall start looking at how Java implements polymorphism and inheritance over
the next few pages.

Classes are fundamental units in Java. In fact all data and functionality in a Java
program are organized into classes. What is a class?

In Java, a class is a collection of data and related methods that operate on that class.
Java makes use of classes to implement encapsulation, inheritance and
polymorphism. Those who are from a procedural background consider a method as
being similar to a function or procedure.

The first step in generating a Java program is to define a class. A class can be
broken down into three basic components;
1. class declaration
2. data
3. methods

Let us look at an example of a class that we have created called Employee.

class Employee {
public String fName;
public String lName;
public float salary;
public int employeeNum;

public Employee(String fName, String lName, int empNo, float salary){


[Link] = fName;
[Link] = lName;
[Link] = salary;
employeeNum = empNo;
}

public float salaryIncrease(int percentageInc){


float increase = (float)percentageInc/100;
salary += salary*increase;
return salary;
}

public float getSalary(){


return salary;
}

public String getFullName(){


return fName + " " + lName;
}
}

PAGE 111
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

Consider a class to be a form of a user-defined type that is non-primitive. The


definition of a class looks as follows;
[<class modifiers>] class <ClassName> [extends <superclass>][implements <interface>]
{
//class body
}

All those with [ ] brackets are optional, and those with <> imply an identifier. You
can see this in our example where its form is basically;
class ClassName{
//class body
}

A class is really a template for objects. Classes provide the mechanism through
which objects are defined. Once a class has been defined you may create an
instance of a class. This instance of a class is known as an object.

Looking at the format of a class definition the [<class modifiers>] can be one
of three types;
1. public
2. final
3. abstract

When we look at the issue of class inheritance we shall discuss these access
modifiers in detail.

class is a keyword informing the compiler that you are creating a new class
template.

In our example Employee is our <ClassName>. Notice the convention


recommended by Java for class name variables. Class names should start with a
capital and all first letters of each word within the class name should be capitalized.

The body of the class is found in between the { and } braces. The first thing that we
declared in our example was to declare the instance variables. These could have
been declared anywhere. I prefer to declare them at the beginning of the class body.
You will find other programmers who prefer to list them at the end. The following
are the instance variables in our example;
public String fName;
public String lName;
public float salary;
public int employeeNum;

PAGE 112
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

Again, notice how we have maintained the Java recommendation of the naming of
instance variables where the variable name begins with a lower case letter and all
first letters of each word within the variable name are capitalized. The declaring of
the instance variables in a class take on the form;
[<access modifier>] type_specifier <variableName>;

In an instance declaration [<access modifier>]can be one of four types;


1. public: This means that the instance variable it precedes is visible and
accessible anywhere the class is accessible. It is not a good idea to make
your instance variables public as this goes against good object oriented
principles and the concept of encapsulation. However circumstances may
deem it necessary to declare your instance variables public.
2. protected: This means that the instance variable it precedes is visible to
all subclasses of this class as well as to all classes in the package.
(packages were discussed in a previous chapter).
3. private: this access modifier only allows methods within the class itself
access to the instance variable.
4. blank: If none of the above three access modifiers are explicitly placed in
front of an instance variable, then the default access modifier applies.
Under this default modifier only classes in the same package have access
to the instance variable, and not subclasses of the current class or classes
outside the current package.

Here is a tabular summary of what is stated above.

Access specifier Accessible by Accessible by Accessible by Accessible by


classes in the classes in other subclasses in the subclasses in
same package packages same package other packages
public yes yes yes yes
protected yes no yes yes
private no no no no
default (blank) yes no yes no

The type_specifier can be any valid primitive or reference type. In our Employee
example we have used both. The primitive types are float and int. The reference
type used is String. We assigned a name to each thereby declaring an instance
variable.

Once we have declared our instance variables we then declared our methods within
the Employee class. These methods we declared are;
1. public Employee(String fName, String lName, int empNo, float salary) { }
2. public float salaryIncrease(int percentageInc){ }

PAGE 113
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

3. public float getSalary(){ }


4. public String getFullName() { }

As indicated earlier a Java method is equivalent to a procedure or function in


PASCAL or C. Methods provide a convenient way of encapsulating some
computation, which can then be used without worrying about its implementation.
With properly designed methods, it is possible to ignore ‘how’ a job is done,
having ‘what’ is done, is adequate. This leads us to the golden rule of methods;

Always ensure that a method performs a single well-defined purpose.

It is therefore important to adequately document each method, defining its purpose,


input parameters, output parameter, date of creation, modification dates etc. This
should be done using the /** and */ form of commenting.

A method can contain one or more lines of code i.e. statements. The general form
of a method is;
[<access modifier>]type_specifier methodName(parameter_list){
declarations;
statements;
}

The [<access modifier>] can be any one of the access modifiers described
earlier under instance variables. i.e.: public, protected, default or private. You
will generally find that instance variables are made private and class methods
public. Access to the instance variables is made via the public or protected
class methods.

The type_specifier informs the compiler of the data type the method will return
by using the return statement. Only one type (primitive or reference) may be
returned to the calling routine. If the method is not going to return anything then
the keyword void is required.

The parameter_list is a comma-separated list of variable names, and their


associated data types that will be passed to the method when it is called. A method
may be without parameters. In other words the parameter_list is empty.
Remember though, parenthesis are still required. For example;
type_specifier methodName() { }

We saw earlier that when defining instance variables we can declare many of them
to be of a common type, by using a comma-separated list of variable names. For
example;

PAGE 114
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

int a, b, c;

However in the parameter_list of a method we cannot do this. Each parameter


must include both the data type and variable name. So the general form (often
referred to as a ‘method signature’) is;
type_specifier methodName (type var_name1, type var_name2,...)

For example;
public int power(int base, n); //NO WAY
public int power(int base, int n); //OK

When passing a value or a reference to a method it is normally called an argument.


Parameters are listed in the method header definition. In Java, depending upon
whether a variable is a primitive type or a reference type, parameter passing differs.

Variables of a primitive data type are passed to a method ‘by value’. These
variables are called the formal parameters to the method. What this means is that a
copy is made of the argument’s value, and then the copy is passed into the method
where it is used. The method may manipulate this value as much as it likes.
However the original argument remains unaffected.

Variables of reference types (i.e. objects) are passed to a method by reference. In


this instance the method does not make a copy of the argument passed to it, but has
direct access to the argument itself. This means that any changes made by the
method to the parameter are made to the actual object used as the argument.

To call a method, make use of the dot(.) operator together with either the instance
name or the class name. For example;

Calling using the class name;


[Link]();

Using an instance of class Employee


[Link]();

Again, looking at our Employee class notice that there is a method name
getSalary(). It returns a floating-point value that represents the salary, which
is the value stored in the instance variable salary. There is a trend in Java to start a
method’s variable name with getXxx if it retrieves a value. In the same light, if one
of the member functions sets an instance variable, its name begins with setXxx.

PAGE 115
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

It should be clear now that you can conceptually view a class as having two parts;
1. An external part.
2. An internal part.

This external part is made up of the public instance variables and methods. These
external parts, also called the class interface, represent all the areas the external
users of the class need to know (or for that matter, are allowed to know). On the
other hand the internal part is made up of mainly the private instance variables
and methods. In Java we refer to instance variables and methods collectively as
class members.

Often a method that is used to modify an instance variable is known as a mutator


method, and those methods that only read the instance variables are known as
accessor methods. You should be careful in supplying public mutator methods as
this allows for a window for corrupting your, hopefully hidden, data.

Notice in our Employee class there is a method whose name corresponds directly
with the name of the class. i.e.;
public Employee(String fName, String lName, int empNo, float salary) { }

This is a special class member method. It is known as a constructor method. The


function of the constructor is to initialize objects of the class. In other words,
constructors are used to initialize instance variables to a known initial state upon
object creation. In our example we have only one constructor method. It is possible
to have more than one, as long as each has a different parameter list in its method
header definition.

There are certain quirks associated with constructors. A constructor method may
only be called once, and this is during the process of object creation. When calling
the constructor you do so using the new operator. Let us look at an example to
clarify this. In our example we created a class called Employee. Let us assume that
we wish to instantiate this class and create an object called person1. To achieve
this we do the following;
Employee person1 = new Employee("Christopher","Robin", 123, 40000);

We have now got an object called person1 whose instance variables have been set
to those arguments in the braces of the constructor Employee(). As the constructor
is a member method of the Employee class it has access to all the instance variables
of the class. Notice the use of the new keyword before the constructor.

PAGE 116
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

Let us look at the statements within this constructor method. It is listed below;
public Employee(String fName, String lName, int empNo, float salary){
[Link] = fName;
[Link] = lName;
[Link] = salary;
employeeNum = empNo;
}

Notice the use of the keyword this. The keyword this refers to the object on
which the method operates. But why do we need to use it in our example? If you
look at the parameters in the parameter list in the Employee() method you will
notice that their names are identical to the instance variable names used in the
Employee class. Now in order for the compiler to differentiate between the objects
instance variable (fName, lName and salary) and the methods parameters (fName,
lName and salary)

What the statement;


[Link] = fName;

does can be translated to: “The string value found in the parameter fName must be
assigned to the object instance variable fName within this object.”

If we had written;
fName = fName; //No No

a fair amount of anxiety would have occurred.

Should you have more than one constructor in a class, you may require the one
constructor to call another upon object instantiation. For example; you may have a
series of constructors that accept different types of arguments and call a single
constructor with the arguments in a standardized form to do the rest of the
processing in one place. This is where this is useful. Let us assume that we have a
constructor with three arguments, and will be called if a new person is employed,
and the salary is fixed. Our new constructor could resemble the following;
class Employee {
:
//Our first constructor.
public Employee(String fName, String lName, int empNo, float salary){
[Link] = fName;
[Link] = lName;
[Link] = salary;
employeeNum = empNo;
}
//Our new constructor.
public Employee(String fName, String lName, int empNo){
this (fName, lName, empNo, 133500);
}

PAGE 117
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

Let us now see what happens when we create a new instance object by means of
this new constructor we have just written. We would write the following;
Employee person2 = new Employee("Mary","Loo", 128);

When this statement is executed our new constructor is called, which in turn calls
the member constructor that matches the parameter list by means of this. So we
have indirectly called our original constructor method. This is quite a common
procedure.

Notice that constructor methods do not have a return type. In summary, remember
that a constructor;
1. Has the same name as the class.
2. May take on zero or more arguments.
3. Is always called once by making use of the new operator when creating an
object.
4. Has no return value.
5. Every Java class has at least one constructor.

Within a class it is possible to have only one instance of a method or variable no


matter how many instances of the class exist. This means that every object has
access to exactly the same variable. So if one instance changes the value in the
variable, all other instances will see this change. To do this we use the keyword
static.

For example;
class Employee{
:
:
private static int lastEmployeeNumber;
:
:
}

In this example there will only be one instance of lastEmployeeNumber no matter


how many instances of the Employee class are created. Notice that its access
specifier is private. This means that only class member methods can see it. It is
not visible to anything outside of the class.

Every instance of a class creates its own, separate copy of instance variables. This
ensures that each object maintains its own unique state. However, all those
variables that are specified as being static are seen across all instances. Because
of this they are known as class variables. All class variables are initialized when the

PAGE 118
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

class is loaded. This means that class variables are initialized before any instances
of the class are created.

Not only are there static class variables but it is also permissible to have static
class methods. The function of these types of methods is usually to provide some
class-wide operations and not be restricted to an individual object. Just as in class
variables, there is only one instance of static methods irrespective of the number
of class instances. They are thus known as class methods. Declaring a method to be
static looks as follows;
public static methodName(parameter_list);

Because class methods and variables are a single instance, irrespective of the
number of instances of the class created, you cannot use the this operator on these
class members. In the same light static methods can only have access to static
variables i.e. class variables (fields).

So as a rule of thumb: ‘You cannot make static references to non-static


variables, nor calls to instance methods.’

For readability and reasons of clarity, when invoking a class method use the class
name, for example;
[Link]();

On the other hand when calling an instance method, invoke it using the object
name, for example;
[Link]();

Within a Java class it is possible to have a static block. The block is bound by {
and } with the keyword static preceding it. Within this block exist valid Java
statements. The role of the static blocks within a class is primarily used for
initialization. These blocks have to be defined within a class but outside any
method declaration. Just as static methods can only access static variables,
static blocks can access only class members (static variables and static
methods). There may be many static blocks within a class. However the order in
which they are executed is the order in which they are declared. static blocks are
executed at the time when the class is loaded, just like class members, before any
instances of the class are created. An example of a static block;

public class StaticExample{


String name;
float salary;
static int payroll;

PAGE 119
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

static {
:
payroll = ..;
:
}
:
:
}

and another fun example;


public class AnotherStaticExample {
:
static double[] buffer = new double[BUFSIZE];
:

static{
for(int i=0; i<BUFSIZE; i++)
buffer[i] = [Link]();
}
:
}

Java even allows for static classes. A static class is just the declaration of an
entire class (i.e. constructors, methods, instance variables (or fields)) as a static
member of another class. All limitations concerning the previous static issues
apply equally to static classes.

So as far as classes are concerned;


1. Always try and keep data (instance variables) private.
2. Always initialize your instance variables.
3. Try not to use too many primitive data types within your classes.
4. Not all fields need accessors and mutators.
5. Keep all your class definitions standard.
6. Break up classes with too many responsibilities.
7. Use class, method and variable names that reflect their responsibilities.

Below is a diagram depicting scope in Java. It provides a pictorial representation of


scope with a Java class. Some of it you may not understand yet (i.e. the exception
handling). It will become clear.

PAGE 120
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

Variable-arity methods and varargs


Let us go back and discuss methods a little further. Before JDK5, every Java
method had a fixed number of parameters. However, beginning with JDK5 you are
now able to create methods that may take a variable number of arguments, or
varargs for short. The method that takes on a variable number of arguments is
known as a variable-arity method.

Varargs allow you to write a method that can take on different numbers of
arguments of the same type. The type can be primitive or complex. A variable
length argument is specified by three periods … The definition of a variable-arity
method is;
[<access modifier>]type_specifier methodName(type... parameter_list){
declarations;
statements;
}

Let us look at a simple example. The method of interest is in bold;

PAGE 121
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

class VzapVarargs{
public static void main(String[] args){
VzapVarargs varagreEx=new VzapVarargs();
[Link]("Answer to first example: "+[Link](2,5,8));
[Link]("Answer to second example: "+
[Link](2,5,8,9,34,6,7));
}

private int multiply(int... numbers){


int result=1;
for(int number: numbers){
result*=number;
}
return result;
}
}

Take a look at multiply() method and its parameter list. The three dots are the
key to variable arguments. What they actually do is tell Java to create an array of
the type specified, in this case int[]. Essentially, you can view numbers as an
array of integers. In our example the first call to multiply will create an array of
ints whose length is 3 where each element is populated by the value separated by
the comma. In the second call to multiply an int array of length 7 will be created
where each element is populated by the value separated by the comma. Just to
prove that it is an array that Java creates, change your multiply() method to the
following where you are now using the standard form of for loop to iterate over
the collection (i.e.: array);
private int multiply(int... numbers){
int result=1;
for(int number=0; number<[Link]; number++){
result*=numbers[number];
}
return result;
}

If you run this your result should be identical to the first example;
Answer to first example: 80
Answer to second example: 1028160

If you are going to make use of variable-arity methods, there are a few things to
keep in mind;
• You may have only one varargs in the method parameter list, but as may
fixed arguments as you like. For instance;
private int fooMethod(double d, long ln, int... numbers)

is perfectly legitimate, but the following is not;

PAGE 122
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

private int fooMethod(double d, long ln, int... numbers, String... names)

• Only the last argument of a method can be varargs. This is legitimate;


private int fooMethod(double d, long ln, int... numbers)

whereas this is not;


private int fooMethod(double d, int... numbers, long ln)

• You should not overload a method which contains varargs as the complier
may get confused during reflection.
• Every call to a varargs method require an array to be created and initialized
which could affect performance in time critical applications. So if you are
able to, rather stay clear of using varargs methods if possible.

PAGE 123
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

INHERITANCE
Now that we have looked at classes and how they are defined, the next issue to
understand is how to build on a class that is already defined in order to extend it in
some way. This extending of classes is commonly known as inheritance. It is
essential to understand in order to use Java successfully. In fact, without you
possibly knowing, all the classes we have looked at so far inherit from a class
called Object, either directly or indirectly. The Object class is known as the root
class in Java. (i.e. [Link]).

When one class inherits from another class, the new class is known as the subclass.
The class it is inheriting from is known as the superclass. A subclass acquires
(inherits) all the non-private instance variables and methods from the superclass.
Once the subclass has acquired the superclass methods, then these methods may be
overridden, thereby redefining the method’s functionality.

For a new class to inherit the contents of an existing class we make use of the
keyword extends. For example;
public class MyNewClass extends ClassX {
:
}

This above class declaration explicitly states that a new class, MyNewClass, is
inheriting the superclass ClassX. For interest sake had we written;
public class MyNewClass{
:
}

Notice that we have not explicitly stated the class we are deriving this new class
from (i.e. inheriting). As already established, all classes are directly or indirectly
descendants of the Object class. So this above statement is really a short cut for
the following declaration;
public class MyNewClass extends Object{
:
}

It should therefore be axiomatic that the only class in Java that does not have a
superclass is the Object class. This Object class contains methods and no instance
variables.

As an example of inheritance we will create some new classes that descend from
the Employee class we created earlier. At present our hierarchy is looking as
follows;

PAGE 124
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

Object

Employee

Here, our Employee class is a subclass of the Object class. Let us now assume that
we are wanting to create a new class called PartTimeEmployee that must inherit
all aspects of our Employee class. It is no good inheriting a class and not changing
it in some way. Our PartTimeEmployee class is different in that;
• A part-time employee does not work a full week.
• A part-time employee is paid by the hour.
• A part-time employee’s weekly salary will be the rate multiplied by a new
variable we shall call hoursWorked.

Let us now create our new class and inherit all the non-private Employee class
members. To do this we execute the following declaration;
class PartTimeEmployee extends Employee{
//Declaring the class instance variables
public int hoursWorked;

//Declaring the constructor for this class


PartTimeEmployee(String fName, String lName, int empNum, float salary,
int hoursWorked){
super(fName, lName, empNum, salary);
[Link]=hoursWorked;
}

public float getWeeklySalary(int hoursWorked){


if(hoursWorked==0){
return (salary*(float)[Link]);
}
return (salary*(float)hoursWorked);
}
}

PAGE 125
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

Our hierarchy structure now looks as follows;


Object

Employee

PartTimeEmployee

Our new class PartTimeEmployee inherits all the non-private members of the
Employee class and adds a little more functionality by adding a new method called
getWeeklySalary(). This is a trait of inheritance. The subclass tends to have
more functionality than its superclass. In other words a subclass is less abstract than
its superclass. Inheritance tends to be an “is-a” relationship. This is true of our
example where PartTimeEmployee “is-an” Employee.

Even though PartTimeEmployee is a subclass of Employee we still declared a


constructor method. Notice the use of the super operator. The statement;
super(fName, lName, empNum, salary);

invokes the constructor, in the superclass whose parameters match the number of
arguments passed. This technique you will see frequently in classes that inherit a
superclass. The reason for this is that every constructor of a subclass must invoke
the constructor in order that the instance variables of the superclass are initialized.
When using super in a constructor, the Java compiler insists that it must be the
first statement executed.

Should you not explicitly call a superclass constructor, then the no argument
constructor of the superclass is automatically called for you. Should the superclass
not have a no-argument constructor then a compilation error will be generated. So
if you come across the error message along the lines: “no constructor found
in superclass”, you should now know why it was generated.

Incidentally, you are not allowed to call a superclass of a superclass. The following
is incorrect.
[Link](a, b, c); //No No

PAGE 126
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

Declaring an instance variable in a subclass where the same identifier name is


declared in the superclass, then the subclasses variable will “shadow” the
superclass’s variable. To access the instance variable in the superclass we then need
to explicitly state this by using the super keyword. To improve readability try not
to declare instance variables with the same name.

By now you should know that inheritance could result in methods becoming
overridden and thereby redefining the object’s functionality. This overriding of
methods is known as polymorphism. To expand on this let us now create a new
class that will be a subclass of Employee and notice how we redefine the
salaryIncrease() method.

class ContractEmployee extends Employee {


public ContractEmployee(String fName, String lName, int empNum, int salary){
super(fName, lName, empNum, salary);
}

public float salaryIncrease(int percentageInc){


if(percentageInc >= 5){
percentageInc = 0;
[Link]("Limit is 5%.\n");
}
return([Link](percentageInc));
}
}

Study the differences between the Employee class salaryIncrease() method and
the ContractEmployee class salaryIncrease() method. It is imperative to
remember that whenever you override a method, the method name, number of
arguments passed and the return type must be identical. The only aspect that may
differ is the name of the parameters. The newly defined method in the subclass,
“shadows” the method of the same name in the superclass. It is possible to call the
superclass method by using the super keyword. This is demonstrated in the above
example. For interest our hierarchical tree now looks as follows;

PAGE 127
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

Object

Employee

PartTimeEmployee ContractEmployee

There is another form of polymorphism in Java. This is referred to as overloading.


Overloaded methods differ from Overridden methods in that you can use the same
method name for a number of different methods. The number of arguments
determines the way the system knows which method to invoke. In other words, the
method signature. This is the method name and parameters (i.e. method1(int a) )
for each method must be different. For example;
public int add(int a, int b);
public float add(int a, float b);
public double add(double a, double b);

Depending on the argument types passed, Java is capable of determining which


method to invoke at run-time. This ability to make decisions at run-time is
commonly known as late binding. As you work more in Java you will see that most
classes contain a number of constructor methods. When using overloaded or
overridden methods, make sure they perform a similar task to the method they are
overloading or overriding. Do not for instance redefine an add() method to
perform complex number multiplication.

There may be times when you does not want your methods to be overridden. To
prevent overriding from occurring on your methods, make use of the final
keyword. When we looked at constants we saw the use of this operator. By
proceeding a method name with the final keyword such as;
final int myMethod(int a, int b);

prevents the myMethod() from being redefined. The same can be applied to
classes. By declaring a class to be final implies that no subclasses may exist of
this type of class. i.e. You cannot inherit from a final class.

There are two reasons for declaring classes and methods to be declared final.
1. Early binding is more efficient than late binding.

PAGE 128
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

2. Safety. No one is allowed to redefine your code to do something obscure.

The converse to this is that we sometimes want to force persons to extend a class or
method. Using the keyword abstract does this. By definition an abstract class
cannot be instantiated. The abstract keyword is telling the compiler that “this
class (or method) is incomplete and needs to be extended to be used.”
public abstract class myClass{
:
}

When declaring abstract methods, these methods may only appear in an


abstract class. The body of an abstract method is empty. This therefore forces
the subclass to override the method and thereby provides a concrete
implementation of the method. Abstraction is extremely useful in that it allows for
“clean class design”. Everything that is common can be declared in an abstract
class, and then the subclass specializes these common features. For instance we can
have an abstract method called play() in an abstract class. We can then create
three new subclasses called TextMessage, FaxMessage and VoiceMessage that
will provide their own unique implementation of play().

Remember,
1. private methods and private instance variables cannot be inherited by a
subclass.
2. Java does not support multiple inheritance. In all our examples only one class
was extended when creating a new class. Java uses a technique called an
interface where a class may reflect the behavior of two or more parent classes.

Now that we have looked at inheritance and discussed the two forms of
polymorphism found in Java, namely method overriding and method overloading,
let us now take the concept of polymorphism a little deeper. We have demonstrated
the mechanics of method overriding, but have yet to look at the full benefit of it,
and making use of one of Java’s most powerful concepts, that of dynamic binding
(also known as late binding).

Let us go back to our Employee class. In this class we declared a number of


variables as well as methods. This Employee class became the superclass of a
number of subclasses that inherited it, namely the PartTimeEmployee class and
the ContractEmployee class. Inside each of these classes we overrode the
superclass’ method SalaryIncrease().

PAGE 129
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

To understand the power of dynamic binding it is essential that you remember a


very important principle.

“A superclass reference variable can refer to a subclass object”

What Java is capable of doing is to use a superclass reference to resolve calls to


overridden methods contained in any of its subclasses AT RUN TIME. To
understand how this works let us once again look at our Employee class and its
subclass hierarchy. Inside the Employee class we have declared and defined a
method SalaryIncrease(). This method is then overridden in the
ContractEmployee class. Our class PartTimeEmployee inherits the
SalaryIncrease() method declared in the Employee class. As our class
hierarchy stands at present, if we create an instance of PartTimeEmployee and
invoke the SalaryIncrease() method then the method inherited from Employee
will be executed. On the other hand, should we create an instance of class
ContractEmployee and invoke the SalaryIncrease() method then the
overridden method in ContractEmployee class will be executed.

There is nothing much wrong with what we have done, but as far as OOP’s
principles are concerned we can improve on this. The higher up the hierarchy, the
more general the class. So what we should do is specify methods in a class that will
be common to all of its subclasses. The subclasses of the more abstract (less
specified) class are then flexible to not only declare and define their own methods
but also to override the methods in the superclass, defining the manner in which it
should respond. So by combining inheritance with overridden methods, a
superclass can declare the general form of methods that will be used by all of its
subclasses. Declaring these methods to be abstract not only results in the class
itself becoming abstract but also forces the subclass to define the method (unless
the subclass itself is abstract).

If we now use a superclass reference to refer to a subclass object and invoke say the
salaryIncrease() method, the program will choose the correct subclass
salaryIncrease() method dynamically, at run-time. Let us look at an example
that will assist in consolidating all that has been said above.

First, let us redefine our Employee class;

PAGE 130
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

package [Link];

public abstract class Employee {


private String fName;
private String lName;
private int employeeNum;

public Employee(String fName, String lName, int empNo){


[Link] = fName;
[Link] = lName;
employeeNum = empNo;
}

public String getFirstName(){


return fName;
}

public String getLastName(){


return lName;
}

public String getFullName(){


return (fName + ' ' + lName);
}

public void setEmployeeNo(int newEmpNo){


employeeNum = newEmpNo;
}

public int getEmployeeNo(){


return employeeNum;
}

// Here we are defining the method to be abstract.


// This means that any subclass of this class must
// declare it.
public abstract void setSalary(float newSalary);
public abstract float salaryIncrease(int percentageInc);
}

If you study this class you will notice that we have changed it. Notice that all the
instance variables are now private and the original salary instance variable has
been removed. We have also defined and declared a number of methods that will
operate on the instance variables. As you look through this code, and that which
follows, notice how we are encapsulating our data as well as performing
polymorphism. We have declared two methods to be abstract. These are the
setSalary() and the salaryIncrease() methods. As they are abstract, the
Employee class is abstract. All subclasses of Employee need to define these
methods. The code above should be self-explanatory, but notice the package
statement. This, and all of Employees subclasses will reside in the
[Link] package.

PAGE 131
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

Let us now look at the code for our ContractEmployee class, which is a subclass
of Employee.
package [Link];

public class ContractEmployee extends Employee{


private float salary;

public ContractEmployee(String fName, String lName, int empNum, float salary){


super(fName, lName, empNum);
setSalary(salary);
}

public void setSalary(float theSalary){


salary = theSalary;
}

public float getSalary(){


return salary;
}

public float salaryIncrease(int percentageInc){


if(percentageInc >= 5){
percentageInc = 0;
[Link]("Limit is 5%.\n");
}
float increase = (float)percentageInc/100;
salary += salary*increase;
return salary;
}
}

The code for this class is a little different from our original version earlier. A few
points for you to notice.
• This class resides in the [Link] package and is declared public.
This is done so that this class may be seen from anywhere. (Remember our
access specifiers?)
• The Employee class is being extended (i.e. inherited).
• We define the setSalary() and salaryIncrease() methods that were
originally declared abstract in Employee and have their own unique
declaration. (Well.. This is not really true for setSalary() in this example, but
should there be a special formula in setting the salary that is unique to a contract
employee, its implementation could be added here without affecting any of the
remaining code)
• A new method getSalary() has been added.

PAGE 132
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

This above code you should easily understand. Now let us look at our other final
subclass, PartTimeEmployee.
package [Link];

public class PartTimeEmployee extends Employee{


//Declaring the class instance variables
private int hoursWorked;
private float salary;

//Declaring the constructor for this class


public PartTimeEmployee(String fName, String lName, int empNum, float salary){
this (fName, lName, empNum, salary, 0);
}

public PartTimeEmployee(String fName, String lName, int empNum, float salary,


int hoursWorked){
super (fName, lName, empNum);
setSalary(salary);
[Link] = hoursWorked;
}

//now let us declare the setSalary() method that was defined as


//being abstract in the superclass class Employee.
public void setSalary(float newSalary) {
salary = newSalary > 0 ? newSalary:0;
}

public float getSalary( int hoursWorked){


if(hoursWorked == 0){
return(salary* (float)[Link]);
}
return(salary* (float)hoursWorked);
}

public void setHoursWorked(int theHoursWorked){


hoursWorked = theHoursWorked > 0 ? theHoursWorked : 0;
}

public int getHoursWorked(){


return hoursWorked;
}

//now let us declare the salaryIncrease() method that was defined as


//being abstract in the superclass class Employee.
public float salaryIncrease(int percentageInc){
float increase = (float)percentageInc/100;
salary += salary*increase;
return salary;
}
}

PAGE 133
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

Notice a few points;


• This class also resides in the [Link] package and is declared
public.
• We are extending the Employee class.
• We also define the setSalary() and salaryIncrease() methods that were
originally declared abstract in Employee. Each has their own unique
declaration. (Well.. This is not really true for setSalary() in this example, but
should there be a special formula in setting the salary that is unique to a part-
time employee its implementation could be added here without affecting any of
the rest of the code)
• New methods getSalary(), setHoursWorked(), getHoursWorked() have
been added.

All the methods defined in the Employee class are available to each subclass, as
they are all declared public. You should be comfortable with the fact that each
one of the subclasses are “more specialized” than the superclass Employee. Now
that we have our structure in place let us see late binding in action. Below is a test
program written using the above classes.
import [Link];
import [Link].*;

public class PolyExample{


public static void main(String[] args){
// Declaring a reference to the superclass
Employee superRef;
String outputString;

DecimalFormat decimalPoints = new DecimalFormat("0.00");


//creating instances of each of the subclasses
ContractEmployee aContractor = new ContractEmployee("Fred", "Bassett",
1234, 1000.00f);
PartTimeEmployee aPartTimeWorker = new PartTimeEmployee("Janet", "Heberden",
237, 18243.98f, 73);

//using aContractor as a reference.


[Link]("\nLooking at ContractEmployee.");
outputString = [Link]() + " of employee number: " +
[Link]() + " earns: R" +
[Link]([Link]());
[Link](outputString);

//Now lets make superRef reference aContractor and use it as a reference.


[Link]("\nNotice how the same information is obtained using a
superclass reference.");
superRef = aContractor;
outputString = [Link]() + " of employee number: " +
[Link]() + " earns: R" +
[Link]([Link]());

PAGE 134
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

[Link](outputString);

//using aPartTimeWorker as a reference.


[Link]("\n\nLooking at PartTimeEmployee.");
outputString = [Link]() + " of employee number: " +
[Link]() + " earns: R" +
[Link]([Link](0));
[Link](outputString);

//Now lets make superRef reference aPartTimeWorker and use it as a reference.


[Link]("\nNotice how the same information is obtained using a
superclass reference.");
superRef = aPartTimeWorker;
outputString = [Link]() + " of employee number: " +
[Link]() + " earns: R" +
[Link]([Link](0));
[Link](outputString);
}

The output of the test program PolyExample is;


Looking at ContractEmployee.
Fred Bassett of employee number: 1234 earns: R1000.00

Notice how the same information is obtained using a superclass reference.


Fred Bassett of employee number: 1234 earns: R1000.00

Looking at PartTimeEmployee.
Janet Heberden of employee number: 237 earns: R1331810.62

Notice how the same information is obtained using a superclass reference.


Janet Heberden of employee number: 237 earns: R1331810.62

Read through this code carefully. You will notice a few interesting aspects. Notice
how we are importing our classes from the [Link] package.

The first statement line inside the main() method declares a reference to our
superclass Employee.
Employee superRef;

Further down in the main() method we instantiate each of our subclasses creating
objects as follows;
ContractEmployee aContractor = new ContractEmployee("Fred", "Bassett",
1234, 1000.00f);
PartTimeEmployee aPartTimeWorker = new PartTimeEmployee("Janet", "Heberden",
237, 18243.98f, 73);

What our code does next is to use the reference to these objects and return some
result. For example;

PAGE 135
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

outputString = [Link]() + " of employee number: " +


[Link]() + " earns: R" +
[Link]([Link]());
[Link](outputString);

Here we are invoking the methods in an instance of ContractEmployee via the


aContractor reference. The result of each method invoked is displayed on the
screen.

Next, we assign to the superclass reference superRef a reference to the subclass


object to which aContractor refers. This is done as follows;
superRef = aContractor;

By using the superRef reference we can invoke all the methods that are in the
subclass and which appear in the superclass Employee. The result of each method
invoked is displayed on the screen. The code performing this is;
outputString = [Link]() + " of employee number: " +
[Link]() + " earns: R" +
[Link]([Link]());
[Link](outputString);

Later in the code we once again assign to the superclass reference a reference to a
different subclass object. Notice that the code invoking the getFullName() and
getEmployeeNo() methods are invoked. This depends upon which object the
superclass reference is referring to. This is true polymorphism in action. Through
the double mechanism of inheritance and run-time polymorphism, it is possible to
define one consistent interface that is used by several different, yet related types of
objects.

What happens now if we want to create a new subclass of Employee called


TraineeEmployee? Well, we go through the process of inheriting the superclass
Employee defining the two abstract methods declared in the Employee class and
declare any new methods required by this new class. We can then create an
instance of TraineeEmployee and assign the reference to our superRef reference.
At runtime the program will then determine which method to invoke. For example
during the lifetime of the program, the program will decide, for example, whether
the getFullName() method of the ContractEmployee, PartTimeEmployee or
TraineeEmployee class object should be invoked. This depends upon which object
the superRef reference is referring to at the time. It is really very important that
you understand all this, as it is one of the huge benefits of Java and Object
Orientation.

The lines not yet discussed in the code above are;


:

PAGE 136
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

DecimalFormat decimalPoints = new DecimalFormat("0.00");


:
[Link]([Link]());
:

In our example, a DecimalFormat object (decimalPoints) is initialised with the


string “0.00”. Each 0 in the string is a format flag that specifies a required digit
position in the formatted floating-point number. It means that exactly one digit to
the left and two to the right of the decimal point will be displayed. If the number
does not meet the formatting requirements then 0’s are automatically inserted in the
formatted number in the required positions. This is achieved when invoking the
format() method of the DecimalFormat object.

In closing this section; Polymorphism results in your programs taking on a


simplified appearance. They contain less branching logic in favour of simpler
sequential code.

PAGE 137
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

INTERFACES
When we discussed inheritance we saw that we were able to create a new class as a
subclass of a superclass by using the extend keyword. It is important to remember
that we were only allowed to inherit from one superclass and this is known as
single inheritance. If we write the following class declaration
public class NewClass extends ClassA, ClassB, ClassC { //No No
:
}

in order to attempt to inherit more than one class, the Java compiler will generate
an error. Java does not allow multiple inheritance. The main reason for this
decision is because multiple inheritance can become complex and lead to
performance degradation. To mimic multiple inheritance Java uses a technique
known as interfacing. An interface provides a promise that your new class will
implement certain methods of specific signatures. The syntax for an interface is;
interface InterFaceName{
:
}

Its implementation is almost identical to that of an abstract class declaration


except that of the keyword interface. The important thing to remember about an
interface is that an interface does not have any behavior. When we looked at
abstract classes, we saw that we could define both abstract as well as non-
abstract methods. This is not true of interfaces. All methods in an interface are
implicitly abstract and therefore unimplemented. Because of this it is impossible
to have a static or final method declared in an interface. The method
signature declared in an interface tells us what the class implementing the
interface is capable of doing.

Therefore an interface may say what a class must do, but not how to do it. This
implies that each class that implements an interface may decide how each
method in it will act. Interfaces are designed so as to support dynamic method
resolution at run-time. As interfaces are in a different hierarchy from classes, it is
perfectly legitimate for classes that are unrelated in terms of the class hierarchy to
implement the same interface. This is really where the power of interfaces lie.

PAGE 138
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

As starters let us look at a very simple example. Shortly we shall look at a more
“real life” example.

Firstly let us define the interface itself.


package [Link];

public interface ValuePassed{


void theValuePassed(int theValue);
}

This extremely trivial interface, ValuePassed, contains a method called


theValuePassed() which takes on an integer parameter. Notice that there is no
body to this method and a semi-colon terminates it. We have also declared the
interface to be public so that it may be seen from anywhere and placed it in its
own package.

When declaring the method within your class that implements the interface, you
must ensure that your implementation meets the definition. To implement an
instance of an interface the syntax is as follows;
public class ClassName implements InterfaceName{
:
}

Let us create a class that will implement an instance of our interface. We shall
call this class TestInterface.
package [Link];

public class TestInterface implements ValuePassed {


// Let us now define the method declared in the interface ValuePassed
public void theValuePassed(int theValue){
[Link]("The value passed is: " + theValue);
}

// Let us declare and define a method that is part of the


// TestInterface class
public void partOfTestInterface(){
[Link]("\nI am declared in the TestInterface class.");
}
}

When we defined the method that we are implementing, which is declared in the
ValuePassed interface, we declared it as being public. This is required. Also
notice that those classes which implement the interface are also allowed to declare
and define their own member methods and instance variables.

Now that we have created an interface and have implemented it in a separate class,
let us write a simple driver program to show it working.

PAGE 139
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

import [Link].*;

public class UseInterface{


public static void main(String[] args){
ValuePassed vp = new TestInterface();
[Link](234);
}
}

Notice something in the above code. We have declared a variable vp to be of the


interface type ValuePassed, yet we assigned it an instance of TestInterface.
Do you remember us doing this when we discussed polymorphism? We are able to
access the theValuePassed() method which was declared in the interface.
Using this reference, should we have included the following statement in the above
code;
[Link]();

an error would have been generated. The reason for this is that an interface
reference variable only has knowledge of the members declared by the interface
declaration and no knowledge of the class member methods that implements the
interface. Didn’t we mention this when we discussed abstract classes and
polymorphism earlier? Can you see the similarity?

Should we now declare another class that implements our interface, we may use
the interface reference to reference an instance of this class. This means that at
run time, depending upon which object instance the reference is pointing to, the
program will decide which one of the implemented instance methods should run.
Once again this is late binding and polymorphism in action.

As a more “real life” example of using an interface, let us look at an interface


that is part of the Java standard library. Looking at the [Link] package, you
will see three interfaces defined. These are; Cloneable, Comparable and
Runnable.

Let us look at Comparable.


public interface Comparable{
public int compareTo(Object O);
}

This is the total declaration of the Comparable interface. Go and peruse the Java
JDK documentation on this and investigate the other two interfaces mentioned
above. What this Comparable interface is promising is that any class that
implements this interface will definitely have a compareTo() method with the

PAGE 140
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

identical signature. The class that implements this interface is responsible for
declaring the method. If you read the Java documentation on this interface it
informs you of what this method is supposed to do and accomplish. For instance it
says;

public int compareTo(Object o)


Compares this object with the specified object for order. Returns a negative
integer, zero, or a positive integer as this object is less than, equal to, or
greater than the specified object.

The implementer must ensure


sgn([Link](y)) == -sgn([Link](x)) for all x and y.
(This implies that [Link](y) must throw an exception if
[Link](x) throws an exception.)

The implementer must also ensure that the relation is transitive:


([Link](y)>0 && [Link](z)>0) implies
[Link](z)>0.

Finally, the implementer must ensure that [Link](y)==0 implies that


sgn([Link](z)) == sgn([Link](z)), for all z.

It is strongly recommended, but


not strictly required that
([Link](y)==0) == ([Link](y)). Generally speaking, any class
that implements the Comparable interface and violates this condition
should clearly indicate this fact.

The recommended language is "Note: this class has a natural ordering that is
inconsistent with equals."

Parameters: o - the Object to be compared.

Returns: a negative integer, zero, or a positive integer as this object is less


than, equal to, or greater than the specified object.

Throws: ClassCastException - if the specified object's type prevents it


from being compared to this Object.

Let us look at an example and use the Employee class created earlier. What we are
going to do is provide the Employee class with the ability to sort according to

PAGE 141
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

salary. To do this we shall implement the Comparable interface. Below is the


complete listing of our example. NOTE: Just for fun I have included a random
number generator to generate different salaries each time our code is executed.
import [Link].*;
import [Link];

public class LargestEarner{


public static void main(String[] args){
Employee[] e = new Employee[5];

e[0]=new Employee("Steve", "Hayworth", 001,(int)(10000*[Link]()));


e[1]=new Employee("Gill", "Hobbs", 002,(int)(10000*[Link]()));
e[2]=new Employee("Mary", "Rose", 003,(int)(10000*[Link]()));
e[3]=new Employee("Sarah", "Thomas", 004,(int)(10000*[Link]()));
e[4]=new Employee("Tim", "Heberden", 005,(int)(10000*[Link]()));

[Link](e);
[Link]("The order of Salaried employees from Lowest to Highest:");
for(int i=0; i<[Link]; i++){
[Link](e[i].getFullName() + " Salary is: R" + e[i].getSalary());
}
}
}

class Employee implements Comparable{


public String fName;
public String lName;
public int salary;
public int employeeNum;

public Employee(String fName, String lName, int empNo, int salary){


[Link] = fName;
[Link] = lName;
[Link] = salary;
employeeNum = empNo;
}

public float salaryIncrease(int percentageInc){


int increase = percentageInc/100;
salary += salary*increase;
return salary;
}

public int getSalary() {


return salary;
}

public String getFullName() {


return fName + " " + lName;
}

public int compareTo(Object b) {


Employee emp = (Employee)b;
return salary - [Link];

PAGE 142
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

}
}

Let us discuss this code a little. Firstly notice how we have created an array of
Employee objects, each statically declared. Since Employee is the class that is
implementing the Comparable interface, Employee is responsible for defining
all methods in the interface. Notice that there is a new method in Employee by
the name of public int compareTo(Object b). The signature matches the
method declared in the Comparable interface. Let us look a little closer at this
method. What is important to note is that the implementation of the method
matches the description detailed in the interface documentation. An Object is
passed to the method that is explicitly typecast to be of type Employee. We then
subtract the salary of the passed object from this object. The result of this
subtraction could be negative, zero or positive.

You may ask, “Where are we using this method?” Looking at the main() method,
you will see that we are invoking the sort(object obj) method found in the
Arrays class. The statement is;
[Link](e);

If you study this class, you will see that the sort() method requires all elements in
the array that is to be sorted to implement the Comparable interface. This is
exactly what we have done in the Employee class.

By using interfaces, a single Java class can inherit unimplemented methods from
many different classes. It is also permissible to extend one interface in order to
create another. For example we may have an interface;
public interface BoxType{
String getBoxType();
}

Which we can extend as follows;


public interface ColourBoxType extends BoxType{
Color getBoxColour();
}

The derived interface implicitly inherits all the data fields and methods of the
parent interface. Java allows a single interface to be derived from more than
one other interface. The syntax for this is;
public interface Racket extends Sport, Tennis, Squash{
:
}

PAGE 143
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

Notice how a comma separates each interface name. In a similar manner it is


possible for a class to implement any number of interfaces. Remember though, a
class may only extend one other class. To implement multiple interfaces you would
use the following syntax;
public class ClassName implement InterfaceOne, InterfaceTwo, InterfaceThree{
:
}

Notice how a comma separates each interface name. Earlier it was stated that
interfaces implicitly inherit all data fields and methods of the parent interface.
This statement reveals that is it possible for interfaces to possess data, but this data
has to be of a constant nature (i.e. static final). It is through interfaces that
Java implements a type of enumeration. For example there is a Java system
interface, [Link] that looks as follows;
public interface WindowsConstants{
public static final int DO_NOTHING_ON_CLOSE;
public static final int HIDE_ON_CLOSE;
public static final int DISPOSE_ON_CLOSE;
}

To see more examples of interfaces supplied by the Java JDK go and peruse
through [Link]. It is easy to implement our
own interface containing static final data elements as well. Below is an
example;
public interface Door {
public static final boolean DOOROPEN = true;
public static final boolean DOORCLOSED = false;
}

Now let us create a class that will implement this interface.


class House implements Door {
boolean backDoor;
:
:
if (backDoor == DOOROPEN)
:
:
}

You should have noticed that throughout our discussions the interface
declaration and implementation of their methods are separate. It is therefore
axiomatic that they will be stored separately too. The method implementations are
stored in the class that uses or “implements” the interface.

Since interface methods are unimplemented, they allow you to define methods
for a class without worrying about the implementation details. This implies that

PAGE 144
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

should the implementation of the interface method be altered, the change will
not disturb the associated interface. Because implementation code changes are
isolated, they prevent the propagation of bugs.

Note: Just as abstract methods in abstract classes, methods declared in an


interface are implicitly public. It is therefore optional to explicitly include the
public access specifier. In the same light, data fields in interfaces are implicitly
static final and are also optional to include the static final specifier.
However for readability purposes you should include these default keywords
within your code.

In closing this section; Interfaces, like abstract classes can act as a template for
deriving new classes in a structured way.

PAGE 145
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

NESTED AND INNER CLASSES


Java has the ability to create classes that are members of other classes; classes that
are nested inside a block; classes that are part of an expression and classes that are
anonymous. What you need to note is that inner classes or class nesting is a
relationship between classes not objects.

The basic syntax is;


class EnclosingClass{
:
class ANestedClass{
:
}
:
}

Here, in its basic form you can see that a nested class is a member of another class.
This is sometimes referred to as a member class. Nested classes, like other class
members have unlimited access to the enclosing class members, even if they are
private. One of the big drawbacks of object orientation is that you may want a
method to perform some simple task. To do this you need to create a new class
containing this method, then instantiate the class in order that you may invoke the
method. The chance too is that this class may be many hundreds of code lines away
from where it is to be used. Nested classes overcome this scenario. The enclosing
class needs however to declare an instance of the nested class before it can invoke
any of the nested class’s methods, assigning data to fields, etc.

Nested classes may also be declared to be static. Placing the static keyword in
front of the class declaration does this. For example;
class EnclosingClass{
:
static class AStaticNestedClass{
:
}
:
}

Just as in static methods and static variables, a static nested class cannot
directly access non-static class members of its enclosing class’s methods and
instance variables. The only way it can do it is through an object reference. static
classes allow you to hide a class inside another class, preventing the nested class
from having access to the outer class object. static classes are sometimes referred
to as “nested top-level classes”.

PAGE 146
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

Inner Classes
A slight twist in nested classes comes in the form of inner classes (or local classes).
These are nested classes whose instance exists within an instance of its enclosing
class. These inner classes, like nested classes have direct access to the instance
members of its enclosing class. Typically these forms of classes are declared
within a method. Below is an example of an inner class that is an event handler for
a button on a screen. Incidentally, when you start to do swing and applet
programming, this form of class declaration will become very familiar as it is used
extensively in event handling;
import [Link].*;
import [Link].*;
import [Link].*;

public class MyAppletClass extends Applet {


Button myButton = new Button("Press Me");

public void init() {

class MyInnerButtonHandlerClass implements [Link] {


int i = 1;

public void actionPerformed(ActionEvent e) {


[Link]("Button has been pressed " + i + " times.");
}
} //end of MyInnerButtonHandlerClass

add(myButton);
[Link](new MyInnerButtonHandlerClasss());
} // This is the end of the init() method.

} // end of the MyAppletClass.

Note that an inner class can be placed anywhere a declaration can be placed.

Anonymous Classes
There is one more type of inner class in Java, and that is the anonymous class. This
form of class definition allows you to combine the definition of the class along with
the instance allocation. In other words, instead of just nesting and declaring a class
as we have been doing before, what we do is to instantiate an object (i.e. new
ClassName()) and put the entire class in brackets. Beware however, anonymous
classes can lead to cryptic code, leading you into the dreaded area of obfuscated
Java code that really plagued C. Anonymous classes should be limited to very
small classes whose use is well understood, such as event handling. An example of
an anonymous class is;

PAGE 147
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

import [Link].*;
import [Link].*;
import [Link].*;

public class MyAppletClass extends Applet {


Button myButton = new Button("Press Me");

public void init() {


add(MyButton);
[Link](new ActionListener(){
public void actionPerformed(ActionEvent e) {
[Link]([Link]() + " pressed");
}
} // This is the end of the anonymous class.
); // This is the end of the method. Notice semi-colon.
} // This is the end of the init() method.
} // end of the MyAppletClass.

Anonymous classes are really just a short hand way of creating a simple local
instance of an object, by wrapping it in a new expression. Finally note that
anonymous classes cannot have constructors, but they can have initializers.

PAGE 148
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

WRAPPER CLASSES AND AUTOBOXING


As you already know, there are eight primitive data types in Java. These data types
are fundamentally different in the fact that they are not classes, and therefore
cannot become objects in the normal sense of the word. However there are
numerous occasions that data of a primitive type needs to be represented as an
object. For example, the classes in the Collections API (like ArrayList) can
only hold Object references. So what Java has are a number of classes that wrap
around these primitive types allowing them to be reflected as an object. The result
is that you are able to invoke a number of methods on these classes allowing you to
manipulate the primitive type it represents. Most of these methods are related to
conversions such as converting primitives to and from String objects, and
converting primitives and String objects to and from different bases (or radix), such
as binary, octal, and hexadecimal. These wrapper classes are;

Primitive type Wrapper


boolean Boolean
byte Byte
char Character
short Short
int Integer
long Long
float Float
double Double

As these wrappers are classes, each of them have constructors. So you may create
an instance of a wrapper class by passing as an argument to the constructor, the
primitive type you are wrapping. It is axiomatic that if you want to wrap an int
type then you would need to make use of the Integer wrapper class. For example;
int i = 34;
Integer wint = new Integer(i);

Or
Integer wint = new Integer(34);

In this example, wint is an instance of class Integer. Below are a few examples;

class Test{
public static void main(String args[]) {
Boolean boolNum = new Boolean(true);
Byte byteNum = new Byte((byte)56); // notice casting
Character charNum = new Character('A');
Short shortNum = new Short((short)87); // notice casting
Integer intNum = new Integer(123);
Long longNum = new Long(123456);

PAGE 149
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

Float floatNum = new Float(1234.5678);


Double doubleNum = new Double(987654.5678987);

[Link]("Boolean number: " + boolNum);


[Link]("Byte number: " + byteNum);
[Link]("Character number: " + charNum);
[Link]("Short number: " + shortNum);
[Link]("Integer number: " + intNum);
[Link]("Long number: " + longNum);
[Link]("Float number: " + floatNum);
[Link]("Double number: " + doubleNum);
}
}

Next program;
class Test{
public static void main(String args[]){
Boolean boolNum = new Boolean(true);
Byte byteNum = new Byte("56");
Character charNum = new Character('A');
Short shortNum = new Short("87");
Integer intNum = new Integer("123");
Long longNum = new Long("123456");
Float floatNum = new Float("1234.5678");
Double doubleNum = new Double("987654.5678987");

[Link]("Boolean number: " + boolNum);


[Link]("Byte number: " + byteNum);
[Link]("Character number: " + charNum);
[Link]("Short number: " + shortNum);
[Link]("Integer number: " + intNum);
[Link]("Long number: " + longNum);
[Link]("Float number: " + floatNum);
[Link]("Double number: " + doubleNum);
}
}

The output for both of the above programs looks as follows;


Boolean number: true
Byte number: 56
Character number: A
Short number: 87
Integer number: 123
Long number: 123456
Float number: 1234.5677
Double number: 987654.5678987

Beware; When using Long, do not include the postfix ‘l’ or ‘L’ to the String value
you are passing. These last two programs illustrate that data can be passed to a
wrapper class constructor in the form of either a literal or as a String version of a
literal value. Now an important thing to remember is; once a wrapper class has
been constructed with a value, like a String, it is immutable. The value represented

PAGE 150
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

by the object cannot be changed. If you want to ‘change’ the value you need to
create a new object.

Let us look at some of the methods that are common to the wrapper classes.

The xxxValue() method


The methods intValue() in the Integer class and the floatValue() in the
Float class return the data held in their respective classes as primitive values.
Study the program below as an illustration;
class Test{
public static void main(String args[]){
Boolean boolNum = new Boolean(true);
Byte byteNum = new Byte("56");
Character charNum = new Character('A');
Short shortNum = new Short("87");
Integer intNum = new Integer("123");
Long longNum = new Long("123456");
Float floatNum = new Float("1234.5678");
Double doubleNum = new Double("987654.5678987");

boolean bool = [Link]();


byte b = [Link]();
char ch = [Link]();
short s = [Link]();
int i = [Link]();
long ln = [Link]();
float f = [Link]();
double d = [Link]();

[Link]("boolean value: " + bool);


[Link]("byte value: " + b);
[Link]("char value: " + ch);
[Link]("short value: " + s);
[Link]("int value: " + i);
[Link]("long value: " + ln);
[Link]("float value: " + f);
[Link]("double value: " + d);
}
}

Once you have constructed an object of the required wrapper class, you have access
to a whole range of useful methods that can be used to work on the data contents of
the class. Some of the methods are more specialised and apply to one particular
class. For instance, the Character class has methods that are to be used with
characters. Other methods are more general and are found in almost all the wrapper
classes. As in good coding practice, many of the method names describe what they
do. However, there is one method that could do with a little more explanation. This
is the valueOf() method.

PAGE 151
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

The valueOf() method is defined in seven of the eight wrapper classes, as well as
being present in the String class. The wrapper class that does not possess this
method is the Character wrapper class. We need to eliminate any form of
confusion, so let us look at the valueOf() method in the wrapper classes first.

valueOf() method in the wrapper classes:


This static method allows for a single String instance argument passed into it
which then passes this String object onto the constructor of the class on which it is
called. The String instance passed should be that of the appropriate sequence of
digits either with or without a decimal point (depending of course on the class on
which the method is called).
[Link](String s)
[Link](String s)
[Link](String s)
[Link](String s)
[Link](String s)
[Link](String s)
[Link](String s)

So the [Link](String s) constructs an object wrapper class xxx that holds


the String instance s passed to it. To clarify, the expression
[Link]("123") results in a new object of the Integer wrapper class
being constructed. The method will return a handle of the newly created object.
Below is an example;
class Test{
public static void main(String args[]){
Integer i=[Link]("123"); //the same as Integer i=new Integer(123);
[Link](i);
}
}

So, in the seven wrapper classes that possess this method, each of them take a
String argument representing the number to be passed into the method. Make sure
that the String value does represent the correct primitive data type. For instance, do
not pass a String instance that has a point (decimal point) into the
[Link]() method. If you do, an exception will be thrown.

Another interesting aspect of this method, is that in the following “whole number”
wrapper classes, the valueOf() method is overloaded as follows;
[Link](String s, int x)
[Link](String s, int x)
[Link](String s, int x)
[Link](String s, int x)

Where the second argument is the base value of the counting system of the value in
the String. For instance;

PAGE 152
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

[Link]("1010", 2); //String 1010 passed as a binary value. This is 10 in decimal.


[Link]("1010", 3); //String 1010 passed as a ternary value. This is 30 in
decimal.
[Link]("1010", 10); //String 1010 passed as a decimal value. This is 1010 in
decimal.
[Link]("1010", 16); //String 1010 passed as a hexadecimal value. This is 4112 in decimal.

valueOf() in the String class


The static valueOf() method in the String class has no fewer than nine overloaded
methods. Here they are;
[Link](boolean )
[Link](char c)
[Link](char data[])
[Link](char data[], int offset, int num)
[Link](double d)
[Link](float f)
[Link](int j)
[Link](long L)
[Link](Object o)

Note that the argument passed is usually a literal value of a primitive type. These
methods return the String equivalent. Notice the last overloaded method in the list
above. The fact that the valueOf() method will accept an Object as an argument
implies that you may pass an object representing any value to the method and it
will work. Below is some code showing these things.
class Test{
public static void main(String args[]) {
char data[] = {'1', '2', '3', '4', '5', '6', '7', '8', '9'};
String s1 = [Link](data, 3, 6);
[Link]("String s1 holds: " + s1);
String s2 = [Link](123);
[Link]("String s2 holds: " + s2);
}
}

The output of this example is:


String s1 holds: 456789
String s2 holds: 123

The parseXXX() method


The parseXXX() method is defined in the following wrapper classes;
Byte
Short
Integer
Long
Float
Double

It is called on the appropriate wrapper class, and returns a value directly from a
string expression of the value that was passed to it. This return value is of a
primitive type. Methods parseByte(), parseShort() and parseLong() are

PAGE 153
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

overloaded methods in their respective classes. They can each take on one or two
arguments. The first argument is always a String instance that is to be returned as a
primitive value. The second argument can be the base value of the String’s number
system, for instance; A1B2 to base16.

Following are a few of examples illustrating what I have said above. Please study
them closely.

Example 1;
class Test {
public static void main(String args[]){
byte b = [Link]("123");
[Link]("byte: " + b);
short s = [Link]("123");
[Link]("short: " + s);
int i = [Link]("123");
[Link]("int: " + i);
long ln = [Link]("123456789");
[Link]("long: " + ln);
float f = [Link]("12345.6789");
[Link]("float: " + f);
double d = [Link]("1234567.8909876");
[Link]("double: " + d);
}
}

The output looks as follows:


byte: 123
short: 123
int: 123
long: 123456789
float: 12345.679
double: 1234567.8909876

Example 2;
class Test{
public static void main(String args[]) {
byte b = [Link]("64",10);
[Link]("byte b from decimal format: " + b);
short s = [Link]("12", 8);
[Link]("short s from Octal format: " + s);
int i = [Link]("101101011", 2);
[Link]("int i from Binary format: " + i);
long ln = [Link]("A1b2", 16);
[Link]("long ln from Hex format: " + ln);
}
}

The output looks as follows:


byte b from decimal format: 64
short s from Octal format: 10
int i from Binary format: 363

PAGE 154
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

long ln from Hex format: 41394

Example 3;
class Test{
public static void main(String args[]){
Integer wholeNum = [Link]("1234");
int i = [Link]();
String bin = [Link](i);
String hex = [Link](i);
String oct = [Link](i);
[Link]("Bin of 1234: " + bin +"\nOct of 1234: " + oct +
"\nHex of 1234: " + hex);
int j = [Link]("9876");
char dat[] = {'A','B','C','D','E'};
String s = [Link](1234);
[Link]("s = " + s);
String s1 = [Link](dat,1,3);
[Link]("s1 = " + s1);
}
}

The output looks as follows:


Bin of 1234: 10011010010
Oct of 1234: 2322
Hex of 1234: 4d2
s = 1234
s1 = BCD

Beginning with JDK5, Java added two important features: autoboxing and auto-
unboxing. Autoboxing is the process by which a primitive type is automatically
encapsulated (boxed) into its equivalent type wrapper whenever an object of that
type is needed. There is no need to explicitly construct an object like you have seen
earlier. Auto-unboxing is the process by which the value of a boxed object is
automatically extracted (unboxed) from a type wrapper when its value is needed.
There is no need to call a method such as intValue() or doubleValue() any
longer if you are using JDK5 and later versions.

Let us look at a few examples;


Before JDK5 you would write:
int intPrimitive = 10;
intPrimitive++;
Integer intObject = new Integer(intPrimitive);

But from JDK5 and later you do the following;


Integer intObject = new Integer(10);
intObject++;

The output for the above examples will be same. In the pre-JDK5 example we are
creating a primitive int value, incrementing it, then wrapping it in an Integer

PAGE 155
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

object. In the JDK5 and later example when the compiler encounters the line
intObject++ the compiler unwraps Integer object to primitive type, increments it
and rewraps to Integer object again. Essentially, when the compiler got to the
line intObject++ it substitutes the code which will be something like the
following:
[Link]([Link]()+1);

With autoboxing, it is no longer necessary to manually construct an object in order


to wrap a primitive type. You need only assign that value to a type-wrapper
reference. Java automatically constructs the object for you. To unbox an object,
simply assign that object reference to a primitive-type variable. Here is a very
simple example showing autoboxing and unboxing in action;
class Autoboxing {
public static void main(String args[]) {
Integer intObject = 10; // autobox an int
int intPrimitive = intObject; // auto-unboxing an int

[Link]("Primitive value: "+intPrimitive +


" ; Object Value: " + intObject);
}

Running this example produces the following output on your console;


Primitive value: 10 ; Object Value: 10

Autoboxing automatically occurs whenever a primitive type must be converted into


an object and auto-unboxing takes place whenever an object must be converted into
a primitive type. So autoboxing/unboxing can also happen when an argument is
passed to a method, or when a value is returned by a method. For example;
class ArgumentAutoboxing {
public static void main(String args[]) {
ArgumentAutoboxing aa=new ArgumentAutoboxing();
int intPrimitive=100;
[Link]("The primitive value: "+intPrimitive);
Integer intObject = [Link](intPrimitive); // passing a primitive which gets
// autoboxed to Integer
[Link]("The value after being passed into and returned from a method:"+
intObject);
}

private int foo(Integer value) {


value+=1;
return value ; // auto-unboxing to an int and returned
}

Running this example will result in the following appearing on you console;
The primitive value: 100
The value after being passed into and returned from a method: 101

PAGE 156
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

I think this example is self-explanatory.

In general, autoboxing and unboxing takes place whenever a conversion into an


object or from an object is required, which also applies to expressions. Within an
expression, a numeric object is automatically unboxed. The outcome of the
expression is reboxed, if necessary. Also, because of auto-unboxing, you can use
Integer numeric objects to control a switch statement and a Boolean as a
conditional expression in an if statement as well as in while, for and do-while
loop statements.

There are a few things you need to be aware of when using autoboxing and unboxing.
1. Compare autoboxed objects with .equals() method not the ‘==’ operator. For
example, look at the following code;
public class AutoboxingBeware1 {
public static void main(String[] args) {
AutoboxingBeware1 ab=new AutoboxingBeware1();
int a = 1000;
int b = 1000;
[Link](a, b);
}

private void compare(Integer a, Integer b) {


if(a == b) {
[Link]("a and b are equal");
}else {
[Link]("a and b are not equal");
}
}
}

The output we expect in the usual way may be “a and b are equal” but the
actual output is “a and b are not equal”. It is because the int values a and
b are “autoboxed” to their wrapper objects Integer which uses their object
reference in the memory to compare when we use “==” operator. So what we
need in situations like this is to use the .equals() method in the object as
follows; replace the line
if(a == b)

with
if([Link](b))

The output is now as expected.

PAGE 157
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

2. If you use a wrapper object to compare against a primitive using relational


operators, for instance “<” or “>“, the unboxing of that wrapper can cause a
NullPointerException. For example;

public class AutoboxingBeware2 {


private static Integer intObject;

public static void main(String[] args) {


if(intObject < 10) { //unboxing
[Link]("intObject is less than 10");
}
}
}

The program tries to unbox the Integer variable, intObject, which has not
been initialized. When it tries to unbox it, a NullPointerException is
thrown, as primitive variables cannot hold null values whereas wrapper
objects can. So, make sure you initialize your wrapper objects before unboxing.
3. A boxing conversion may result in an OutOfMemoryError if a new instance of
one of the wrapper classes needs to be allocated and insufficient storage is
available.
4. Autoboxing or unboxing degrades the performance of an application as it
creates an unwanted object resulting in the garbage collector to executing more
frequently.
5. Since the .valueOf() method is used to create boxed primitive objects, the
used objects are cached. Since Java caches integers from -128 to 127, these
cached objects may behave differently.

PAGE 158
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

EXCEPTION HANDLING
In a perfect world, code would have no bugs. Unfortunately this is not the case. So
at best a robust program is one that will operate correctly even under unusual or
exceptional circumstances. To achieve a robust program Java allows the
programmer the ability to anticipate exceptional conditions that may effect the
program’s operation. This form of error trapping is known as exception handling.

In your program what would happen if a user entered the wrong type of
information such as integers instead of characters? What would happen if your
program tried to open a non-existent file? The program must be able to cope with
this type of problem. In real terms exception handling allows the programmer to
separate the functional part of a program from the error handling part. This is
extremely useful as it improves program clarity, thereby allowing for enhanced
modifiability. In procedural languages like C this is not the case. All error checking
surrounds and is intimately bound to the normal processing. Error handling
techniques eliminate this.

To prevent program failure your program should;


1. return to a safe state and allow the user to execute another command or,
2. allow the user to save all work and exit the program.
These two basic approaches to error handling in Java are called resumption and
termination.

Resumption: Here we expect the exception handler to handle the error in such a
way that the situation that caused the error is corrected and then the
code that was faulty, re-executed.

Termination: These types of errors are so serious that the exception handler may
find it impossible to correct the situation. So under these conditions a
block of code is terminated, and program execution continues in the
next block of code. Mostly under these conditions, your program will
terminate. The type of error that usually causes this is commonly
known as a run-time error.

As with everything else in Java, exceptions are objects. All exceptions are derived
from (subclasses) of class Throwable. The error handling class structure looks as
follows;

PAGE 159
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

Throwable

Exception Error

IOException RuntimeException

Notice the two subclasses of Throwable. These are the Exception and Error
classes. In most cases the exceptions you will explicitly handle in your programs
will be an instance of the Exception class. You will rarely create an instance of
the Error class. The Error class is usually used by the Java run-time system for
handling internal errors and resource exhaustion. Objects derived from the
Exception class can be of two types;
1. Those derived from run-time exceptions,
2. those that are not.
A run-time exception is usually a direct result of something erroneous in your
programming. All other exceptions occur because a well-written program was used
incorrectly. To view the classes inherited from the Exception class and the
RuntimeException class go and view the tree structure of the [Link] package
found in the JDK documentation. For instance you will see exceptions derived from
the RuntimeException include;
a) Attempting to access an out-of-bounds array element
(ArrayIndexOutOfBoundsException).
b) A bad cast (ClassCastException).
c) An exceptional arithmetic condition, like divide-by-zero (ArithmeticException).
d) A null pointer access. i.e. where an application attempts to use a null in a
case where an object is required. (NullPointerException).

Exceptions not derived from the RuntimeException include;


a) an end-of-file or stream has been reached unexpectedly (EOFException).
b) Trying to open an incorrect (malformed) URL (MalformedURLException).
c) Trying to access a class object using a string that contains the name of a non-
existent class (ClassNotFoundException).

PAGE 160
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

Items a) and b) above are subclasses of the IOException class, which is in-turn a
subclass of the Exception class.

If you see a RuntimeException occurring, you can generally blame yourself for
some poor programming. When errors occur, the Java run-time system generates an
exception object. This process is known as “throwing an exception”. Any exception
thrown, needs to be caught, and handled. This catching and handling process is
known as exception handling and achieved through an exception handler.

When an exception is thrown, the Java run-time environment will begin to search
for a handler. The first place it looks is in the method where the error occurred. If it
does not find the appropriate handler here, it then starts migrating up the run-time
stack, until either an appropriate handler is found or the top of the stack is reached.
Should no appropriate handler be found, then a default handler is executed. This
default handler displays a message describing the exception and then dumps a stack
trace to the standard output, which is usually a screen. The program then
terminates.

To be able to catch a thrown exception object we must first set up a try-catch


block. Its syntax looks as follows;
try{
//some code that could throw an exception.
}catch (ExceptionType e){
//handler for thrown type
}

The normal process code resides in the try block (i.e. you ‘try’ to run the code
successfully) as well as any code that may throw an exception. The code that
handles the thrown exception object resides in the catch block. It is actually the
catch block that handles the exception. Notice that this technique allows you to
separate your normal code from your error handling code. Let us look at an
example;

PAGE 161
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

public class Exception1Example{

public static void main(String[] args){


try{
int [] arrayPrime = {2,3,5,7,11,13,17,23};
int [] arrayTwo = {0,0,0,0,0};
for (int i=0; i<([Link]+1) ;i++){
[Link]("Element " + i + " of arrayTwo: " + arrayTwo[i]);
}
[Link](arrayPrime,3,arrayTwo,2,3);
for(int i=0; i<[Link];i++){
[Link]("Element " + i + " of ArrayTwo AFTER copy: " + arrayTwo[i]);
}
}catch(Exception e){
[Link]("Oops - My Mistake!!!");
}
}

In our example, the code that Java attempts to run first resides in the try block. If
an error occurs then an exception is thrown. If the exception object is of the same
type as that in the catch clause then the catch block will be executed. In our
example there is an error. Before reading on look at the code and see if you can
work out where it is.

We are exceeding the bounds of an array. Notice the compiler cannot detect the
type of error above. It is a programming error. What we have tried to do is print the
contents of arrayTwo that are outside its bounds. When we try and do this, an
exception gets thrown. All the code following on after the error in the try block is
not executed. Control is transferred to the exception handling catch block where
an error message is generated and the program ends. You could have written this
code without using the try-catch block and the error would still have been
generated. The run-time environment will throw an
ArrayIndexOutOfBoundsException that RuntimeException handler would
process. Should there have been no error in the try block then all statements in the
try block would have been executed, and the catch block would have been
skipped.

In Java every single method may be provided with a mechanism allowing it to exit
if it were unable to complete its task in a normal way. In such cases, the method
does not return a value but rather throws an exception object that encapsulates the
error information, and then terminates. To explicitly throw an exception use the
keyword throw. The syntax is as follows;
throw Exception_Object;

PAGE 162
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

In most cases Exception_Object will be a newly constructed object, created like


all other objects, using the new operator. This construction and throwing can be
accomplished in two ways;
EOFException e = new EOFException();
throw e;

OR

throw new EOFException();

A method that throws an exception needs to advertise the fact that it may throw an
exception. This is done in the method header declaration by adding;
throws Exception_Class_Name

For example the method header below indicates that a string will be returned under
normal conditions, but the method also has the capacity to throw an exception if
something goes wrong;
public String readLine() throws IOException{
:
}

Having stated that a method needs to advertise if it is going to throw an exception,


it is not necessary for it to advertise every possible throwable object it may throw.
To understand what and what not to advertise in the method header, keep in mind
that an exception is thrown in any one of the four following situations;

1. You anticipates an error and writes code that throws an exception by means of
the throw keyword.
2. You calls a method that throws an Exception.
3. You inadvertently makes a programming error that causes a run-time error.
4. An internal error occurs in the Java run-time system.

If condition 1 or 2 occur then you must advertise publicly that your method may
throw an exception. For example;
class SoundStuff{
:
public Sound loadSound(String soundName) throws IOException{
:
}
:
}

Should a method deal with more than one exception then all exceptions should be
advertised;
class SoundStuff {
:

PAGE 163
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

public Sound loadSound(String soundName) throws IOException, EOFException{


:
}
:
}

Those exceptions that inherit from Error do not have to be explicitly advertised
within your method header. Any code can potentially throw an exception of this
type and is way beyond your control. Also, any exceptions inheriting the
RuntimeException class need not be advertised. RuntimeException errors are
under a programmer’s control. It is up to you to ensure that these types of errors do
not occur. This is seen in our example earlier. In Java parlance errors due to either
programming errors (RuntimeException) or errors out of your control (Error) are
called implicit or unchecked exceptions. All other exceptions are called explicit or
checked exceptions. So a general rule of thumb for methods explicitly advertising
exceptions that may be thrown is;

A method must advertise all the explicit exceptions it throws.

A note of warning is necessary:


If you override a method from a superclass in the subclass, the subclass
cannot throw more explicit exceptions than the superclass. It may throw
fewer, however. Likewise, if the superclass throws no exceptions, neither can
the subclass.

Let us look at another example;


:
String readData(BufferedReader in) throws EOFException{
:
while(..){
if(ch==-1){ //See if End of File
if (n < len)
throw new EOFException();
}
:
}
return s;
}
:

The EOFException class has two constructors, the default constructor and a second
one that allows a string to be passed, that becomes the error message. For example,
instead of;
throw new EOFException(); //bolded in our example

We could have done the following;

PAGE 164
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

{
String s = "Content Length: " + len;
throw new EOFException(s);
}

Resulting in a more “user friendly” way of exiting the program, in that a message
relating to the error is relayed to the user.

So far in the discussion we have been using the standard exception classes that
come with Java and reside in the [Link] package. It is possible to create your
own exception class. All that is required is that you create a new class that is a
descendent of the Exception class. As stated earlier it is common to have two
constructors; one with no parameter list and one with a String parameter. As an
example let us create a new exception class called FileFormatException.

class FileFormatException extends IOException{


public FileFormatException() {
}

public FileFormatException(String s){


super (s);
}
}

Notice that our new class is a subclass of IOException that is a subclass of the
Exception class. An example of a method using our newly created class is;
String readData(BufferedReader in) throws FileFormatException{
:
throw new FileFormatException();
:
}

Please do not forget that if you explicitly throw an exception, then there must be a
mechanism in place to catch the exception, otherwise the program will terminate
(crash). As a reminder look at the following code;

public static String readLine(){


int ch;
String r = " " ;
boolean done = false;
while(!done){
try{
ch = [Link]();
if(ch <0 || (char)ch =='\n')
done = true;
else
r+= (char)ch;
}catch(IOException e){
done = true;
}

PAGE 165
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

}
return r;
}

Any explicit exception thrown must be handled or passed on. It is quite permissible
to have nested exceptions. Likewise, we may have multiple exceptions. Under this
arrangement there tends to be one try block and a separate catch block for each
exception type that may be thrown. For example, the following code will pop ten
integers off a stack and then write them to a file;
:
try{
for(int i = 0; i<10; i++){
n=[Link]();
[Link](n);
}
}catch(IOException e){
[Link]("Problem writing to file.");
}catch(EmptyStackException e){
[Link]("Stack is empty.");
}
:

There may be times when you may want to catch an exception without addressing
its root cause. For instance you may want to do some local cleaning up. Under
these circumstances we call throw, thereby sending the exception back up the
calling chain. For example;
Graphics g = [Link]();
try{
: // code that may throw an exception
}catch(MalformedException e){
[Link]();
throw e;
}

In the above code segment, if you do not dispose of the graphics object, which is
local, then it may not be disposed of for a long time. So the right thing to do is to
dispose of it inside the catch block. This has the effect of relieving some system
resources. On the other hand the reason why the exception was thrown was because
a malformed URL was generated. This MalformedException still has not
disappeared. So we then re-throw it so it may be dealt with further up the calling
chain. It is also permissible to throw a different exception from the one caught. The
example below demonstrates this;
try{
: // Code that may throw an exception
}catch (RuntimeException e){
throw new Exception("Foo Error");
}

PAGE 166
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

There may be times when you will want to run some code irrespective of whether
an exception was thrown or not. We already know that Java stops processing all the
code in the try block that appears after the point at which an error was generated
and an exception was thrown. A typical problem is: a local method may acquire
resources that only the method knows about. If these resources are not cleaned up
by the method, problems may arise. One solution to this scenario is to do
something like the previous example where you catch and then re-throw the
exception. This however is not a clean solution. A far better approach is to use the
finally clause. finally is an optional block, which provides code to be executed
regardless of whether an exception occurs. It is generally used for doing essential
cleaning up, that may not be omitted under any circumstance. The general syntax
is;
try{
: // The code here may generate an exception.
}
catch(Exception e){
: // The code here handles the exception.
}
finally{
: // The code here is always executed after a try or
// catch block is finished.
}

Let us now use this syntax and improve on the code for our Graphics example we
demonstrated earlier;
Graphics g = [Link]();
try{
: // code that may throw an exception
}
catch(MalformedException e){
done = true;
}
finally{
[Link]();
}

Finally;
• A try block must have at least one catch or finally or both blocks;
• If you have an exception object e, that contains information about the nature of
the exception, and we wish to find out more about the object, you can do the
following;
[Link]() // This retrieves a detailed message if one
// is present.

[Link]().getName(); // This retrieves the actual type of the


// exception object.

PAGE 167
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

Beginning with JDK1.4, a feature was incorporated into the exception subsystem
known as chained exceptions. This feature allow you to relate one exception with
another exception. In other words, one exception describes cause of another
exception. For example, consider a situation in which a method throws an
ArithmeticException because of an attempt to divide by zero but the actual
cause of exception was an I/O error which caused the divisor to be zero. The
method will throw only ArithmeticException to the caller. So the caller would
not come to know about the actual cause of exception. Chained exception is used in
such type of situations.
Two new constructors and two new methods were added to Throwable class to
support chained exception. The new constructors are;
Throwable(Throwable cause)
Throwable(String str, Throwable cause)

In the first form, the parameter cause specifies the actual cause of exception. In the
second form, it allows you to add an exception description in string form with the
actual cause of exception. The two methods added to Throwable class are;
getCause()
initCause()

The getCause() method returns the actual cause associated with current
exception. If there is no underlying exception then a null is returned. The
initCause() method sets an underlying cause(exception) with the invoking
exception. Therefore, you can associate a cause with an exception after the
exception has been created. However, the cause exception can be set only once,
meaning that you can call initCause() only once for each exception object. Here
is a simple example illustrating the mechanics of handling chained exceptions:
import [Link];

public class ChainedException{


public static void main(String[] args){
ChainedException ce= new ChainedException();
try {
[Link](5, 0);
}catch(ArithmeticException ae) {
[Link]("Caught: " +ae);
[Link]("Cause of exception: "+[Link]());
}
}

private void divide(int a, int b){


if(b==0){
ArithmeticException ae = new ArithmeticException("Vzap Math Exception");
[Link](new IOException("IO caused exception"));
throw ae;
}else{

PAGE 168
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

[Link](a/b);
}
}
}

Running this simple example will result in the following appearing on your
console;
Caught: [Link]: Vzap Math Exception
Cause of exception: [Link]: IO caused exception

Beginning with JDK7, three features have been added to the exception system.
• The first automates the process of releasing a resource, such as a file, when it
is no longer needed. It is based on an expanded form of the try statement
called try-with-resources.
• The second feature is called multi-catch.
• The third feature is sometimes referred to as final rethrow or more precise
rethrow.

Let us look at the second a third feature here. The first one we will look at later on
in the course. The multi-catch feature allows two or more exceptions to be caught
by the same catch clause. It is not uncommon for two or more exception handlers
to use the same code sequence even though they respond to different exceptions.
Instead of having to catch each exception type individually, you can use a single
catch clause to handle all of the exceptions without code duplication.

To use a multi-catch, separate each exception type in the catch clause with the OR
[|] operator. Each multi-catch parameter is implicitly final. You can explicitly
specify final, if desired, but it is not necessary. Because each multi-catch
parameter is implicitly final, it cannot be assigned a new value. Here is a catch
statement that uses the multi-catch feature to catch both ArithmeticException
and ArrayIndexOutOfBoundsException:
try{
:
}catch(ArithmeticException | ArrayIndexOutOfBoundsException e) {
:
}

Here is a simple example illustrating the multi-catch feature in action:


class MultiVzapCatch {
public static void main(String args[]) {
int a=10, b=0;
int vals[] = {1, 2, 3};

try {
int result = a / b; // generate an ArithmeticException

PAGE 169
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

// vals[10] = 19; // generate an ArrayIndexOutOfBoundsException

// This catch clause catches both exceptions.


}catch(ArithmeticException | ArrayIndexOutOfBoundsException e) {
[Link]("Exception caught: " + e);
}
[Link]("After multi-catch.");
}
}

Our program will generate an ArithmeticException when the division by zero is


attempted. If you comment out the division statement and remove the comment
symbol from the next line, an ArrayIndexOutOfBoundsException is generated.
Both exceptions are caught by the single catch statement.

The more precise rethrow feature restricts the type of exceptions that can be re-
thrown to only those checked exceptions that the associated try block throws, that
are not handled by a preceding catch clause, and that are a subtype or supertype of
the parameter. For the more precise rethrow feature to be in force, the catch
parameter must be either effectively final, which means that it must not be
assigned a new value inside the catch block, or explicitly declared final.

PAGE 170
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

THREADS IN JAVA
What is a thread? It is a single sequence of control within a program.

A computer gives the impression that it is running several programs at one time. It
achieves this by allocating a certain amount of time to each program. This is
commonly known as time slicing or time-sharing. Each program gets allocated a
certain amount of time in which it may execute its code. After the time period has
lapsed then the next program begins its term of execution. The operating system
manages where the program ends and where execution needs to continue, when
another time slot gets allocated to the program again. Threads are similar, except
that they operate within a program itself. Many threads of execution may run in a
single program simultaneously. This is known as a multithreaded program. There
are times when you will see threads referred to as “lightweight processes”. This is
because they do not generate the same level of overhead as processes do. A Java
program always has at least one thread running. This is the main thread of your
program, and is executed when the program begins. It is the first thread that is
executed when a program starts and the last one to stop, resulting in the
termination of your program. One other thing; it is from this main thread that all
other “child” threads are spawned.

In multithreaded programs the program divides up its time slices among several
independent threads of control. Effectively you get several things to happen at once
within a program. In Java there are two techniques to obtain a new thread of
control.

1. Subclass the Thread class and override the run() method.


2. Implement the Runnable interface.

Subclass the Thread class and override the run() method.


You can make use of this technique only if your class is not extending any other
class besides the Thread class. The syntax is;
class MyThreadClass extends Thread{
public void run(){ //overriding Thread’s run() method.
:
}
:
}

PAGE 171
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

Implement the Runnable interface.


You have to make use of this technique when one class is extending another class
and wish to make use of threads. A good rule of thumb is: If your class must
subclass another class then implement the Runnable interface. The Runnable
interface looks as follows;
public interface Runnable{
public void run();
}

It contains only the one run() method. To use the Runnable interface the syntax is
as follows;
class MyThreadClass implements Runnable{
public void run(){ // implements the run() method.
:
}
:
}

and instantiating is done as follows;


// creating an instance of the class and thereby creating the thread
// object
MyThreadClass testingThreads = new MyThreadClass();

//Now lets get the thread to run


new Thread(testingThreads).start();

Perusing the documentation on the Thread class, you will see that there are many
other methods which may be used in connection with threads; for instance
sleep(), getName(), currentThread(), setPriority() etc. If you need to
make use of these methods then you will need to make use of the first technique
when declaring a thread run() method.

At this point it is very important to note that it is the run() method that is the heart
of any thread and it is here that the action of the thread takes place. Within this
run() method it is perfectly legitimate to call other methods, use other classes and
even declare variables.

Once you have implemented the Runnable interface, you have to instantiate an
object to be of type Thread, from within the class that implements the Runnable
interface. In other words, a class that implements the Runnable interface can
run without the need of subclassing the Thread class by simply instantiating a
Thread object and then passing itself as one of the arguments to the constructor.
Thread defines a number of constructors. Two of the constructors you will most
commonly use are;

PAGE 172
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

Thread(Runnable target);
Thread(Runnable target, String targetStringName);

Here target is the class name that implements the Runnable interface.
targetStringName is a name that you may give the thread. Once you have
defined what the thread must do (in the run() method) and has instantiated an
object to be of type Thread, you then need to start the thread executing. The
start() method creates the system resources necessary to run the thread,
schedules the thread to run and calls the thread’s run() method.

To make the above discussion a little clearer let us look at an example. Firstly, let
us create a class that implements the Runnable interface.
class MyNewThread implements Runnable{
Thread trd;

MyNewThread(){
trd = new Thread(this, "My Thread");
[Link]("\nI am now creating a new thread called: " + trd);
[Link]();
}

public void run(){


// We have to run the following code in a try catch block as sleep() may throw
// an exception, InterruptedException, if another thread has interrupted the
// current thread.
try{
for(int i=1; i<=5;i++){
[Link]("I am now drinking nip number " + i + " of Irish Mist.\n");
[Link](500); // as sleep() is static we may call it via its class
// name Thread
}
} // end of try
catch (InterruptedException ie){
[Link]("Oops! an exception has been thrown by the child thread");
} // end of catch
[Link]("No more Irish Mist Please. hic!!\n");
} // end of run()
} // closing class

Let us now discuss the code above. We are creating a class MyNewThread that
implements the Runnable interface. Within this class we implement the method
run(). Remember that the run() method is the place where the thread will start.
A possible way of remembering this is that the run() method is the main method
for a thread in much the same way that the main() method is for a program. You
do not call it directly, it is called on your behalf. All that we are doing in our run()
method is looping five times. Within this loop we invoke the sleep() method
defined in the Thread class. We may call this method via the Thread class name as
it is declared as being static. The purpose of the sleep() method is to cause the
thread to delay its operation, in our case, by 500mS.

PAGE 173
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

Within the above class we are also defining a constructor. We declare a reference
to Thread. Notice that within the constructor we are instantiating a Thread class.
We pass to the Thread constructor a reference to the class that is implementing the
Runnable interface. In our example we use the this operator. Once we have an
instance of the Thread class we can now start the thread running by invoking the
start() method. Occasionally you will see a Thread instance being created and
the thread started in one statement, for example;
Thread trd = new Thread(this, "thread One").start();

Try this in the above code, it does work. Note that in our example we will start the
thread running inside the class that implements the Runnable interface.

Now that we have a class that has implemented the Runnable interface, let us
write a small program that will make use of this class.
class TestMyThread {

public static void main(String[] args){


// MyNewThread myThread = new MyNewThread();
new MyNewThread();
try{
for (int i = 1; i<=5; i++){
[Link]("Hello I would like cup number " + i +" of Java please.\n" );
[Link](1000);
}
} // end of try
catch (InterruptedException ie){
[Link]("Oop's an exception has been thrown by the main program thread");
} // end of catch
[Link]("Enough is enough ! GoodBye!! (exiting the program).");
} // end of main()
} // end of class

In this program we create an instance of our class that implements the Runnable
interface. As soon as this is done the so-called child thread will come into
operation. Remember that the main thread is already in operation, otherwise our
program would not be running. In the main() method all we are doing is looping
five times. Notice however that we have caused this loop to delay longer than the
loop in our class that implemented the Runnable interface. Can you answer
why I have done this? Well the reason is, if this loop ran faster than the loop in the
child thread, then the program may end before the total number of loops in the
child thread has been completed. Delaying this main thread for longer means that
the child thread will definitely complete all operations before the program exits.
This by the way is NOT good programming. There are far better mechanisms you

PAGE 174
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

may use to prevent a program terminating before all operations are complete. We
shall see this later.

By studying this code above you should get a good understanding of how to
implement the Runnable interface. If many threads are “running” they cannot
run at precisely the same time (especially on machines that only have one
microprocessor). Therefore the Java run time library must implement a scheduling
scheme that then shares the processor between all the “running” threads. What Java
runtime does is to use a very simple scheduling algorithm based on priorities. Each
thread has a priority level.

PAGE 175
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

THREAD PRIORITY
When a thread is created it is allocated a priority. One problem with threads is that
they may be assigned the same priority. If this is the case then one of the threads
with the same priority may be blocked. One way of getting around this problem is
to make use of the yield() method. This prevents any thread from hogging the
CPU. Another way is to change a methods priority by making use of the
setPriority() method resident in the Thread class. These priority levels run
from a low of 1 to a high of 10. The lowest priority is found in MIN_PRIORITY and
is usually 1. The highest priority is in MAX_PRIORITY and is usually 10, and a
default priority value found in NORM_PRIORITY and is usually set to 5. These
constants are defined in the Thread class. Let us assume that you wish to increase
the priority of a thread, this can be done as follows;
[Link]([Link]() + 1);

This sets the priority to one higher.


Note:
• The Java runtime’s thread scheduling system is preemptive. This means that the
thread with the higher priority becomes ‘runnerable’. In other words, the higher
priority threads preempt any lower priority threads.
• Do not rely on the priority of threads for correctness. Ideally the highest thread
will run, but this is not guaranteed.
• Java will not preempt a thread for another thread of the same priority. Java
therefore does not time slice.
• If you have threads of the same priority and you yields()them, then the
scheduler will choose the next thread in a non-preemptive, round robin fashion.
Any attempts to yield() to a thread of lower priority are ignored.

We can divide threads into basically four kinds;


1. Unrelated threads.
2. Related but unsynchronized threads.
3. Mutually exclusive threads.
4. Communicating mutually exclusive threads.

PAGE 176
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

UNRELATED THREADS
This is the simplest form of thread programming. Each thread contains all of the
data and method’s required for its execution and does not require any outside
resources for its execution. The threads do not interact with each other. In our
example below we run two threads. The process remains in an endless loop. We
use the yield() method to relinquish each thread from the CPU as each would
have been assigned the same default value.
public class JavaTime{
public static void main(String[] args){
Coffee cup = new Coffee();
Cake cake = new Cake();
[Link]();
[Link]();
}
}

//******************************************************
class Coffee extends Thread{
public void run(){
while(true){
[Link]("One cup of Java ");
yield();
}
}
}

//******************************************************
class Cake extends Thread{
public void run(){
while(true){
[Link]("and some brandy cake please.");
yield();
}
}
}

The output looks as follows;


One cup of Java and some brandy cake please.
One cup of Java and some brandy cake please.
One cup of Java and some brandy cake please.
One cup of Java and some brandy cake please.

To get out of the program press Ctrl–C. As you can see, each thread runs totally
independently.

PAGE 177
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

RELATED BUT UNSYNCHRONIZED THREADS


What this does is to allow for a program to be partitioned in such a way that it uses
multiple threads to assist in solving a problem, where each thread operates on
different pieces of the same data structure. Having said that, the threads still do not
interact with each other. Because they are not sharing data, each thread can operate
independently and none of the threads need to be synchronized. So the threads are
related but not synchronized. An example is spawning a thread for each time a new
socket is established. On the next page is an example where the code creates
multiple threads in determining prime numbers within a certain range. Can you
figure out what is happening?
public class TestPrime{
public static void main(String[] args){
long possPrimeNumber = [Link](args[0]);
int hundreds = (int)(possPrimeNumber/100)+1;
for(int j=0; j<hundreds; j++)
new TestPrimeRange (j*100, possPrimeNumber).start();
}
}

//************************************************************************
class TestPrimeRange extends Thread{
static long possPrime;
int from, to;

TestPrimeRange(int checkFrom, long possibleNum){


if (checkFrom == 0)
from = 2;
else
from = checkFrom;
possPrime = possibleNum;
to = checkFrom+99;
}

public void run(){


for(long j=from; j <= to && j < possPrime; j++){
if (possPrime%j == 0){
[Link]("Factor " + j + " found by thread " + getName());
[Link](); // please note that stop() is a deprecated
// method, but one can still compile it.
}
yield();
}
}
}

The output if you enter: java TestPrime 4096 is


Factor 2 found by thread Thread-0
Factor 512 found by thread Thread-5
Factor 128 found by thread Thread-1
Factor 1024 found by thread Thread-10
Factor 256 found by thread Thread-2
Factor 2048 found by thread Thread-20

PAGE 178
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

MUTUALLY-EXCLUSIVE AND
COMMUNICATING MUTUALLY-EXCLUSIVE
THREADS.
Mutually exclusive threads are those threads (two or more) that run concurrently
having access to the same data and therefore need to consider the state and
activities of the other threads. To assist in the discussion here I have written a
small program that is part of a much larger system. Let us assume that we are
doing low temperature research in super-conductive materials. In order for us to do
certain testing on ceramic that super-conducts at temperatures of below –70oC we
need to place the ceramic inside a cryostat containing liquid nitrogen. What is
important is that the level of the liquid needs to be maintained. If it gets too low
then the ceramic will not be in the liquid and may stop super-conducting during the
two day experiment. So our system has an AnalogToDigital converter that converts
the level to a digital value that is stored. We then want to read this value when it
changes. Should the level decrease below a certain level, then the cryostat is
automatically filled with liquid nitrogen. So we shall create three classes
SaveLevel, ReadLevel and LevelContainer. We shall work through these
classes throughout the discussion and make improvements to them as we move on
in order that we may achieve correct results and explain mutual threads. Our first
iteration of our ReadLevel and SaveLevel look as follows. Please note that in this
code we are simulating data being entered and then read out when changed. I will
now write the SaveLevel class that will simulate data being read from the A-to-D
and entered into the LevelContainer. The code would look something like;

class SaveLevel extends Thread {


private DecimalFormat myFormat = new DecimalFormat("#0.00");
private LevelContainer levelContainer;

public SaveLevel(LevelContainer con){


levelContainer = con;
}

public void run() {


double i;
for (int j=0; j<10; j++){
i = (double)([Link]()*100);
[Link](i);
[Link]("Cryostat Writing Level Value: " + [Link](i));
}
try {
sleep((int)([Link]() * 100));
}catch(InterruptedException e){ }
} //end of run
} // end of class

PAGE 179
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

To add a little twist, I have included a delay in the SaveLevel class. Depending on
how you implement A-to-D conversion, it is pretty slow compared to the running
of a processor. We are also ensuring that one piece of thread code runs more
slowly than the other in order that we may simulate errors. Notice the use of
DecimalFormat. The class that now reads the data ReadLevel entered would look
something like this;
class ReadLevel extends Thread {
private DecimalFormat myFormat = new DecimalFormat("#0.00");
private LevelContainer levelContainer;

public ReadLevel(LevelContainer levCont){


levelContainer = levCont;
}

public void run(){


double value = 0;
for int i=0; i<10; i++){
value = [Link]();
[Link]("Cryostat Reading Level Value: " + [Link](value));
}
}
}

The class that is the container will look as follows;


class LevelContainer{
private double liquidLevel;

public double getLevel(){


return liquidLevel;
}

public void setLevel(double aToDValue){


liquidLevel = aToDValue;
}

We have not made any effort to perform any form of synchronization. We said that
we wanted the value to be read out only when the inputted level had changed. We
would like to see the relationship between the value stored to the value read to be
along the following;
Cryostat Writing Level Value: 14.96
Cryostat Reading Level Value: 14.96
Cryostat Writing Level Value: 40.70
Cryostat Reading Level Value: 40.70
Cryostat Writing Level Value: 15.33
Cryostat Reading Level Value: 15.33
Cryostat Writing Level Value: 38.10
Cryostat Reading Level Value: 38.10

PAGE 180
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

However, because we are not synchronizing all the code, we are not achieving
what we desire. If we ran the unsynchronized code our output would look as
follows;
Cryostat Writing Level Value: 16.93
Cryostat Writing Level Value: 52.42
Cryostat Writing Level Value: 28.16
Cryostat Reading Level Value: 28.16
Cryostat Writing Level Value: 24.90
Cryostat Reading Level Value: 24.90
Cryostat Reading Level Value: 24.90
Cryostat Reading Level Value: 24.90

This is not good. We are making multiple writes and reads when we only want to
read once the data has changed. Without synchronizing our threads there may also
be occasions when we may lose a value somewhere. In our example we write
multiple values before one is read. The reading misses values. Our example does
not suffer from this but you will see it happening in your programming career
where two threads may be writing data to the same variable. If this happens, errors
are bound to occur unless steps are taken to protect the reading and writing
process. These types of condition are known as a data race or race condition. It
results because the threads asynchronously access the same data. To avoid this
racing condition the rule of thumb is:

“whenever two threads access the same data then they must use mutual exclusion.”

This means that you must allow for only reading or writing to take place at any one
time. To achieve this mutual exclusion a Java thread has the ability to lock an
object. To lock an object from a low-level perspective is complex. Fortunately Java
hides these complexities. This locking is achieved in Java by making use of the
synchronized (NB: American spelling) keyword. When an object is locked by
one thread and another thread tries to call a synchronized method on the same
object, the second thread will block until the object is unlocked. In Java it is
possible to synchronize a block of statements as well as methods. This is known as
a critical section. In other words code segments within a program that access the
same object from separate, concurrent threads which are identified by the keyword
synchronized are called critical sections.

In our example let us now ensure that our code that writes the new level of the
liquid nitrogen and reads this new level, are synchronized. This will ensure that
when control enters a synchronized method, the thread that calls the method
locks the object whose method has been called. This results in no other threads
being allowed to call a synchronized method on the same object until such time as
the object is unlocked.

PAGE 181
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

Our amended LevelContainer code looks as follows. Notice the new keyword in
bold;
class LevelContainer{
private double liquidLevel;

public synchronized double getLevel(){


return liquidLevel;
}

public synchronized void setLevel(double aToDValue){


liquidLevel = aToDValue;
}
}

Fortunately the acquiring and releasing of locks are done automatically for us. By
the way Java allows for re-entrant locks. This means that if there are two
synchronized methods and the first synchronized method calls the second
synchronized method, the thread attempts to acquire the same lock acquired
when control entered the first method. As Java supports this lock re-entry, this
syntax is allowed. If Java did not allow this then this sequence of commands would
result in a deadlock.

So far so good. Our code will now prevent asynchronous access to the same data.
We still have a problem however. One thread is running faster than the other in our
example. We are still not guaranteed that the data will only be read once it has
been updated and changed. We need to make a few changes to our getLevel and
setLevel methods. We could do the following;

class LevelContainer{
private double liquidLevel;
private boolean updated = false;

public synchronized double getLevel(){


if(updated){ //same as if(updated==true)
updated = false;
return liquidLevel;
}
}

public synchronized void setLevel(double aToDValue){


if(!updated){ //same as if(updated==false)
liquidLevel = aToDValue;
updated = true;
}
}
}

PAGE 182
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

We still have a small problem. What would happen if SaveLevel as not actually
saved a value yet, resulting in updated still remaining false? Well getLevel() will
do nothing. In the same light; what would happen if SaveLevel call setLevel()
before ReadLevel has read the level? Well setLevel()will do nothing. Oh dear !!

To solve this problem what we really need to do is make ReadLevel wait until
SaveLevel does actually save something and then get it to notify ReadLevel that
it has done so. Then, we make SaveLevel wait until the ReadLevel has read the
value. When it has done so, it then notifies SaveLevel it has done so. To do this
we make use of Object’s wait() and notifyAll() methods. Our final code
looks as follows;
class LevelContainer{
private double liquidLevel;
private boolean updated = false;

public synchronized double getLevel() {


while(!updated){
try{
wait();
}catch (InterruptedException e){}
} // end while
updated = false;
notifyAll();
return liquidLevel;
} // end getLevel()

public synchronized void setLevel(double aToDValue){


while(updated){
try{
wait();
}catch (InterruptedException e){}
}// end while
liquidLevel = aToDValue;
updated = true;
notifyAll();
} // end setLevel()
}

What happens here is that the getLevel() method loops, as update is false,
until the SaveLevel has written a new value. Each time through the loop the
getLevel() method calls the wait() method. This wait() method then causes
the lock held by ReadLevel to be relinquished, thereby allowing SaveLevel to
receive the lock and update the data. It then sits and listens for notification from
SaveLevel. Once SaveLevel has saved the new data and set update to true, it
then notifies ReadLevel by calling the notifyAll() method. This then results in
ReadLevel to stop waiting (i.e. comes out of the wait state) and then checks the
variable updated which is now true, then exits the loop, reads the newly entered

PAGE 183
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

data, and returns it. Whilst ReadLevel is doing this, SaveLevel is in a wait()
state. This process is repeated as many times as required.

Note the wait method here waits indefinitely. There are other methods namely
wait(long timeout) and wait(long timeout, int nanos). Go and study
them. They are useful in places where you want delays.

Our complete code listing plus a small driver test program looks as follows;
import [Link];

public class CryostatLevels{


public static void main(String[] args){
LevelContainer cryLevel = new LevelContainer();
SaveLevel cryLevelPut = new SaveLevel(cryLevel);
ReadLevel cryLevelGet = new ReadLevel(cryLevel);

[Link]();
[Link]();

while(true);
}
}

//*********************************************************************
class LevelContainer{
private double liquidLevel;
private boolean updated = false;

public synchronized double getLevel() {


while(!updated){ //same as while(updated==false)
try{
wait();
}catch(InterruptedException e) {}
}
updated = false;
notifyAll();
return liquidLevel;
}

public synchronized void setLevel(double aToDValue){


while(updated){ //same as while (updated==true)
try{
wait();
}catch(InterruptedException e){}
}
liquidLevel = aToDValue;
updated = true;
notifyAll();
}
}

//*********************************************************************
class SaveLevel extends Thread{
private DecimalFormat myFormat = new DecimalFormat("#0.00");
private LevelContainer levelContainer;

public SaveLevel(LevelContainer con){


levelContainer = con;

PAGE 184
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

public void run(){


double i;
for(int j=0; j<10; j++){
i = (double)([Link]()*100);
[Link](i);
[Link]("Cryostat Writing Level Value: " + [Link](i));
}
try{
sleep((int)([Link]() * 100));
}catch (InterruptedException e){}
}
}

//*********************************************************************
class ReadLevel extends Thread{
private DecimalFormat myFormat = new DecimalFormat("#0.00");
private LevelContainer levelContainer;

public ReadLevel(LevelContainer levCont){


levelContainer = levCont;
}

public void run(){


double value = 0;
for(int i = 0; i < 10; i++){
value = [Link]();
[Link]("Cryostat Reading Level Value: " + [Link](value));
}
}
}

PAGE 185
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

DAEMON THREADS
Daemon threads are threads that run in the background, usually when processor
time that is available would otherwise go to waste. Daemon threads normally
denote “server” threads and are of a low priority. A server thread is a thread that
services client requests. In other words it runs for the benefit of others. The Java
run time system treats daemon threads differently from normal threads. You will
not be able to exit a program until all normal threads have been terminated, but this
is not true of daemon threads. Daemon threads may still be in existence when a
program terminates. This makes sense because there are no more clients running
for the daemon to provide a service to. An example of a daemon thread in Java is
the garbage collector. It runs for the benefit for others. The next section discusses
garbage collection.

To assign a thread to become a daemon thread you invoke a call to the method;
setDaemon(true);

An argument of false means that the thread is not a daemon. If a daemon thread
is not set to daemon before its start() method is invoked then an
IllegalThreadStateException is thrown.

To find out whether a thread is a daemon you can make use of the;
final boolean isDaemon()

method. If a true is returned then the thread is a daemon thread.

PAGE 186
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

GARBAGE COLLECTION
Java allocates memory on the heap space by means of the new keyword. Generally
the stack space is used for local instance variables, method calls etc. In fact
additional stacks are created for each thread in Java. This means that Java’s virtual
memory management system needs to be of the highest standard. Every time an
instance of a class is created, space is allocated on the heap.

Once an object is no longer required, then the space allocated to it on the heap
needs to be reclaimed. In C and C++ this has to be done by the programmer by
dynamically reclaiming allocated memory. Very efficient memory management
programs are in existence in the C and C++ environments. However the problem
with memory management in these environments is, should the reference to the
allocated memory become lost then there is no way to reference that memory in
order to free it. This then becomes known as a memory leak.

Sometimes you will hear of orphaned objects. An orphaned object is an object that
is no longer referenced. In C and C++ orphaned objects result in memory leaks. In
Java the run time system performs the memory management task for us. It is not as
efficient as that of the C and C++ environments but its trade off is that it is much
safer. Java’s memory management is automatic and is commonly known as
garbage collection.

There are a number of garbage collection algorithms, each with their own
strengths. Three are “reference counting”, “stop and copy” and “mark and sweep”.

Java uses the “mark and sweep” method of garbage collection. The process is as
follows. Java’s garbage collection runs on a lower priority daemon thread, waiting
for time on the CPU. It goes and sweeps the heap spaces for any object that no
longer has any references. All those objects that have references to them are then
marked. It sweeps all possible paths to objects and once all these have been
investigated, those objects not marked (i.e. they are no longer referenced) are then
known to be garbage. These are collected thereby releasing the memory. The
process is much more complicated than this, but in essence this is what occurs.
Incidentally, as soon as your system is out of memory, garbage collection occurs
automatically.

It is quite possible to explicitly drop an object (i.e. orphaning it) by setting to null
the value of the variable whose data type is a reference type. For example;
myObjectReference = null;

PAGE 187
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

Setting an object reference to null ensures that that object is not referenced and
therefore becomes garbage. Incidentally, if another reference should exist to this
object then the object will not be garbage collected. There must be no reference to
the object at all in order for garbage collection to take place.

Usually before an object is garbage collected, the garbage collector gives it an


opportunity to clean up after itself through a call to the object’s finalize()
method. The finalizing and freeing of an object takes place asynchronously in the
background. However it is possible to force object finalization and garbage
collection by invoking a call to [Link](). Using this method does not
guarantee that your object will be garbage collected immediately. All it does is
invoke the static gc() method to schedule the garbage collector to execute as soon
as it can.

PAGE 188
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

ENUMERATIONS
Beginning with JDK5, enumerations were added to the Java. Consider
enumerations, represented by the enum type as a list of named constants. So, an
enum type is a special data type, in fact it is a special kind of Java class that enables
for a variable to be a set of predefined constants. Although you cannot inherit a
superclass when declaring an enum, all enumerations automatically inherit one:
[Link]. This class defines several methods that are available for use by
all enumerations. If your program consists of a fixed set of constants like choices
on a menu, days of the week, operations, statuses and so on, you should consider
using enumerations. For example, you would specify a user’s status enum type as
follows:
public enum UserStatus {
PENDING,
ACTIVE,
INACTIVE,
DELETED
}

Notice how the enum keyword is used in place of class or interface indicating
to the Java compiler that this type definition is an enum. You may now save this
enumeration in a .java file with the same name as the enumeration, in our case
[Link]. The identifiers PENDING, ACTIVE, and so on, are called
enumeration constants. Each is implicitly declared as public static final
members of UserStatus. Notice to that the names of an enum type's fields are in
uppercase letters, because they are constants. Furthermore, their type is the type of
the enumeration in which they are declared, which is UserStatus in our case.
Thus, these constants are called self-typed, in which “self” refers to the enclosing
enumeration.

Once you have defined an enumeration, you can create a variable of that type. Even
though enumerations define a class type, you do not instantiate an enum using new.
Instead, you declare and use an enumeration variable in much the same way as you
do one of the primitive types. For example, this declares aUser as a variable of
enumeration type UserStatus:
UserStatus aUser;

The aUser variable can take one of the UserStatus enumeration constants as a
value i.e. PENDING, ACTIVE, INACTIVE or DELETED. For instance, let us set aUser
to an ACTIVE status;
aUser=[Link];

PAGE 189
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

Two enumeration constants can be compared for equality by using the == relational
operator. For example;
UserStatus aUser = ... //assign some UserStatus constant to it

if(aUser == [Link]) {
:
:
} else if(aUser == [Link]) {
:
:
} else if(aUser == [Link]) {
:
:
}

Here is a complete example. First create your enumeration and save it in a file
called the same name as your enumeration. In our example it will be
[Link]. Go ahead and compile it. Next create the following code, and
place it on the same directory as the [Link] file;

public class EnumDemoOne{


public static void main(String args[]){
UserStatus uStat = [Link];

if(uStat == [Link]) {
[Link]("User status is: Pending");
} else if(uStat == [Link]) {
[Link]("User status is: Active");
} else if(uStat == [Link]) {
[Link]("User status is: Inactive");
} else {
[Link]("User status is: Deleted");
}
}
}

Running this code should produce the following on your console;


User status is: Inactive

An enumeration value can also be used to control a switch statement. Of course,


all of the case statements must use constants from the same enum as that used by
the switch expression. For example,

UserStatus aUser = ... //assign some UserStatus constant to it

switch (aUser) {
case PENDING:
:
break;
case ACTIVE:
:

PAGE 190
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

break;
case INACTIVE:
:
break;
case DELETED:
:
break;
default:
:
}

Notice that in the case statements, the names of the enumeration constants are used
without being qualified by their enumeration type name. For instance, PENDING,
not [Link], is used. This is because the type of the enumeration in
the switch expression has already implicitly specified the enum type of the case
constants. There is no need to qualify the constants in the case statements with
their enum type name. In fact, attempting to do so will cause a compilation error.

Here is a complete example using a switch expression;

public class EnumSwitchDemo{


UserStatus uStat;

public EnumSwitchDemo(UserStatus uStat) {


[Link] = uStat;
}

public static void main(String[] args) {


EnumSwitchDemo usr1 = new EnumSwitchDemo([Link]);
[Link]();
EnumSwitchDemo usr2 = new EnumSwitchDemo([Link]);
[Link]();
}

public void getUserStatus() {


switch (uStat) {
case PENDING:
[Link]("User status is: Pending");
break;

case ACTIVE:
[Link]("User status is: Active");
break;

case INACTIVE:
[Link]("User status is: Inactive");
break;

default:
[Link]("User status is: Deleted");
break;
}
}

PAGE 191
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

Running this code should produce the following on your console;


User status is: Inactive
User status is: Deleted

All enumerations automatically contain two methods: values() and


valueOf(String str). The values() method returns an array containing a list
of the enumeration constants. The valueOf(String str) method returns the
enumeration constant whose value corresponds to the string passed in str. In both
cases, the array type is the same type of the enumeration. For example, in the case
of the UserStatus enumeration shown earlier, the return type of
[Link]("Deleted") is Deleted.

The following program demonstrates the values() and valueOf(String str)


methods:
class EnumMethodsDemo {
public static void main(String args[]){
UserStatus uStat;
[Link]("All possible user statuses are:");

// using the values() method


UserStatus allStatus[] = [Link]();
for(UserStatus us : allStatus){
[Link](us);
}

// using the valueOf() method


uStat = [Link]("ACTIVE");
[Link]("\nuStat variable contains " + uStat);
}

Running this program should result in the following appearing in your console;
All possible user statuses are:
PENDING
ACTIVE
INACTIVE
DELETED

uStat variable contains ACTIVE

The fact that enum defines a class gives the enumeration extraordinary power. For
example, you can give them constructors, add instance variables and methods, and
even implement interfaces. You are not restricted to simple accessor (getter) and
mutator (setter) methods. For example you can create methods that perform

PAGE 192
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

calculations based on the field values of the enum constant. It is just like any
normal class. If your fields are not declared final you can even modify the values
of the fields, although this may not be such good an idea, considering that the
enums are supposed to be constants. It is important to understand that each
enumeration constant is an object of its enumeration type. So, when you define a
constructor for an enum, the constructor is called when each enumeration constant
is created. Incidentally, the constructor must be either private or default (package
scope). You cannot make it public or protected. Each enumeration constant has
its own copy of any instance variables defined by the enumeration. For example,
consider our new version of UserStatus enumeration where we have added our
own constructor, instance variable and a member method (looks like any normal
class does it not?);
public enum UserStatus {
PENDING(2), //calls constructor with value 2
ACTIVE(1), //calls constructor with value 1
INACTIVE(7), //calls constructor with value 7
DELETED(-1) //calls constructor with value -1
; // semicolon needed when fields and/or methods follow.
// Can always put a semicolon in even if there are NO fields and methods
private final int statusCode;

UserStatus(int statusCode) {
[Link] = statusCode;
}

public int getStatusCode() {


return [Link];
}
}

As you can see in this example we have a field statusCode for each of the
constants, along with a method getStatusCode() which is basically a getter
method for this field. When you define a constant, for instance, PENDING(2) it calls
the enum constructor UserStatus(int statusCode) passing it the argument of
2. The passed value is then assigned to statusCode of the corresponding enum’s
constant. You must remember that the constructor is called once for each constant.
Because each enumeration constant has its own copy of statusCode, you can
obtain the statusCode of a specified type of UserStatus by calling
getStatusCode(). For example;
[Link]();

Here is an example where we use our new enumeration;


class EnumMembersDemo {
public static void main(String args[]){

PAGE 193
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

UserStatus uStat;
[Link]("All possible user statuses and their codes are:");

// using the values() method


UserStatus allStatus[] = [Link]();
for(UserStatus us : allStatus){
[Link](us + " status as a status code of: "+[Link]());
}
}

Do you understand this program? If all goes well you should see the following on
your console;
All possible user statuses and their codes are:
PENDING status as a status code of: 2
ACTIVE status as a status code of: 1
INACTIVE status as a status code of: 7
DELETED status as a status code of: -1

Just for fun, can you work out what is happening here? The enumeration is;
public enum VzapMathsOperation {
PLUS,
MINUS,
MULTIPLY,
DIVIDE;

double calculate(double x, double y) {


switch (this) {
case PLUS:
return x + y;
case MINUS:
return x - y;
case MULTIPLY:
return x * y;
case DIVIDE:
return x / y;
default:
[Link]("Unknown math operation. " + this);
return 0;
}
}
}

And the programme using the enumeration;


public class VzapEnum {
public static void main(String[] args) {
[Link]("Answer is "+[Link](1, 2));// Answer is 3.0
VzapMathsOperation op = [Link]("multiply".toUpperCase());
[Link]("Answer is "+[Link](10, 3)); // Answer is 30.0
}
}

PAGE 194
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

Summary of enumerations in Java;


• Java enums implicitly extend [Link]
• Java enums are type-safe.
• An enum specifies a list of constant values assigned to a type.
• enum constants are implicitly static and final, so cannot be changed once
created.
• enums may contain constructors, methods, variables and constants.
• You may specify enum constant values at creation time.
• An enum may be declared outside or inside a class, but not in a method.
• An enum declared outside a class cannot be static, final, abstract,
protected or private.
• You may not create enum instances by using the new operator.
• enum instances are created when any of the enum constants are first called or
referenced in your code.
• The .values() method returns an array containing the enumeration’s
values.
• enum can be safely perform comparisons using:
 Switch statement
 == operator
 .equals() method

PAGE 195
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

ANNOTATIONS
JDK5 introduced a new feature enabling you to embed supplemental information
alongside a Java entity (such as classes, interfaces, fields and methods). This
information, called an annotation or metadata does not change the action of a
program but can be read and interrelated by the compiler or other utilities. They
may be stored in the class files and the runtime can discover these metadata via
Java’s reflection API. One of the main reasons for adding annotation and metadata
to the Java platform is to enable development and runtime tools to have a common
infrastructure so as to reduce the effort required for development and deployment.

An annotation always starts with the symbol @ followed by the annotation name,
for example; @Override. Here @ indicates to the compiler that this is an annotation
and Override is the name of this annotation. Here is an example of an annotation
being applied to a method.
@Override
void myFooMethod() {
//Do something
}

As of JDK8, Java has five built in annotations;


@Override
@Deprecated
@SuppressWarnings

The following two were introduced in JDK8


@FunctionalInterface
@SafeVarargs

1. @Override
When you override a method in a subclass, you use this annotation to inform
the compiler you are overriding an existing method. Should the compiler find
that there is no matching method in the superclass, it will generate a warning
informing you of this. Using this annotation makes your code more readable
and avoids maintenance issues. It is not mandatory to use the @Override
annotation when overriding a method but is considered best practice to do so.
Here is an example using @Override;
public class VzapParentClass {
public void fooMethod() {
[Link]("Super class method");
}
}
//****************************************
public class MyChildClass extends VzapParentClass {

PAGE 196
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

@Override
public void fooMethod() {
[Link]("Child class method");
}
}

2. @Deprecated
The @Deprecated annotation informs the compiler that the marked element
(class, method or field) is deprecated and should no longer be used. The
compiler generates a warning whenever a program uses a method, class or
field marked with the @Deprecated annotation. When an element is
deprecated it should also be documented using the Javadoc @deprecated
tag. When doing so, note the case difference of @Deprecated and
@deprecated. @deprecated is used for documentation purposes only. Here
is an example using @Deprecated;
@Deprecated
public void fooMethod(){
// Do something
}

3. @SuppressWarnings
This annotation instructs compiler to ignore specific warnings. This is like
saying, “I know what I am doing, so do not worry”. Essentially you are
telling the compiler not to raise any warnings. Below is an example using
@SuppressWarnings. For this example assume the method
deprecatedMethod() has been marked with the @Deprecated annotation.
So, in this example the compiler will suppress any deprecation warnings.
@SuppressWarnings("deprecation")
void myMethod() {
[Link]();
}

4. @FunctionalInterface
This annotation is designed for use on interfaces. It indicates that the
annotated interface is a functional interface. A functional interface is an
interface that contains one and only one abstract method. Functional
interfaces are used by lambda expressions which we will not discuss on this
course.

PAGE 197
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

5. @SafeVarargs
This annotation is designed to be applied to methods and constructors. It
indicates that no unsafe actions related to a varargs parameter occur. It is
used to suppress unchecked warnings on otherwise safe code as it relates to
non-reifiable vararg types and parameterized array instantiation. Incidentally,
a non-reifiable type is, essentially, a generic type. We will look at generics
later on in the course. Here is an example of @SafeVarargs;
@SafeVarargs
void fooMethod(List<String>... stringLists) {
String s = stringLists[0].get(0);
[Link](s);
}

PAGE 198
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

CREATING CUSTOM ANNOTATIONS


You are able to create your own annotations and use them. There are two main
components in annotations.

1. The annotation itself


2. The annotation type

An annotation is defined like an ordinary Java interface, as it is based on the same


mechanism as Java’s interface. You precede the interface keyword with ‘@’
(i.e., @interface). Next, you declare methods inside the annotation definition,
similar to the way you declare abstract methods inside an interface. In an
annotation these methods are known as elements. It is very important to note that
these method (element) declarations may not have any formal parameters nor a
throw clause. Also, their return types are restricted to primitives, String, Class,
enum, annotation and arrays of the preceding types. These elements may be
assigned a default value. Finally, they may also be unnamed.

The general syntax for declaring an annotation is;


@interface <name> {
//method [element] declaration;
}

And here is a simple example;


@interface VzapAnnotation {
String course();
int courseNo();
String company() default "VZAP";
}

Because of the ‘@’ before the keyword interface, Java’s compiler will know that
you are defining an annotation, in our case VzapAnnotation. Notice too that we
have declared three methods without any body and where the third element is
assigned a default value. As mentioned earlier, this is exactly the same as when you
create an interface. An annotation cannot include an extends clause, but all
annotation types automatically extend the [Link]
interface.

Once you have declared an annotation, you can use it to annotate something. When
applying an annotation, you give values to its elements (members). For example,
here is an example, we will call VzapAnnotation annotation, being applied to a
method declaration:
@VzapAnnotation(course = "Java 101", courseNo = 123)

PAGE 199
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

public void myMethodFoo() {


:
:
}

In this example, our annotation is being applied to a method myMethodFoo. Notice


that our annotation VzapAnnotation, which is proceeded by a ‘@’ is followed by a
parenthesized list of member initializations. The string "Java 101" is assigned to
the course element and the value 123 assigned to courseNo element of
VzapAnnotation. Observe that no parentheses follow course or courseNo in this
assignment. When an annotation member is assigned a value, only its name is used.
Essentially, annotation members look like fields. As company was set with a
default value, you can skip assigning it a value. If you wanted to, you can assign
company a new value in just the same way as you did for the other elements.

Let us now look at annotation types. Essentially, these are meta information about
an annotation. For example, if you want to ensure that an annotation may only be
applied a method, you would do the following when declaring the annotation;
@Target([Link])
public @interface VzapAnnotation { }

There are four annotation types.


1. @Documented: When an annotation type is annotated with @Documented
then wherever this annotation is used those elements should be documented
using the Javadoc tool. Here is an example. Note; when you generate the
javadoc for class OurClass, the annotation @VzapAnnotation will be
included in that documentation process.
[Link]

@Documented
public @interface VzapAnnotation {
//Annotation body
}

@VzapAnnotation
public class OurClass {
//Class body
}

2. @Inherited: This meta annotation denotes the annotation type can be


inherited from a superclass. When a class is annotated with this type then
when a request for a specific annotation is made to the subclass, if that
annotation is not present in the subclass, then its superclass is checked. If
that annotation is present in the superclass, and if it is annotated with
@Inherited, then that annotation will be returned. In the example below

PAGE 200
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

notice that the class SuperClass is using annotation @VzapAnnotation


which is marked with @inherited annotation. It means the subclass
ExtendedClass inherits the @VzapAnnotation.

[Link]

@Inherited
public @interface VzapAnnotation {
}
// ************************************
@VzapAnnotation
public class SuperClass {
...
}
// ************************************
public class ExtendedClass extends SuperClass {
...
}

3. @Retention: Its general form is @Retention(retention-policy). A


retention policy determines at what point an annotation is discarded. There
three possible values:
• Class
An annotation with this retention policy will be compiled and included in
the class file .class, however it is not available through the JVM during
the runtime.
• Runtime
An annotation with this retention policy will be compiled and included in
the class file .class, and is available through the JVM during the
runtime.
• Source
An annotation with this retention policy will be will be available only in
the source file and is discarded at compile time.

Here is a simple example illustrating the use of @Retention;


@Retention([Link])
public @interface VzapAnnotation {
String value();
}

4. @Target: takes one argument, which is an array of constants of the


ElementType enumeration. Possible values for ElementType are:
o CONSTRUCTOR
o FIELD
o LOCAL_VARIABLE
o METHOD
o PACKAGE

PAGE 201
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

PARAMETER
o
TYPE
o
TYPE_PARAMETER
o
TYPE_USE
o
TYPE_PARAMETER and TYPE_USE were introduced in JDK8.

Here is a simple example illustrating the use of @Target;


@Target([Link])
public @interface VzapAnnotation {
String value();
}

To specify multiple values, you must specify them within a braces-delimited


list. For example;
@Target( {[Link], ElementType.LOCAL_VARIABLE} )
public @interface VzapAnnotation {
String value();
}

Now that you know a lot about annotations, how would you go about parsing them?
To show you how to do this, we will create our own annotation using a number of
features explained above, assign it to a method and then create a test program to
run it. Here goes..

First, here is our custom annotation;


package [Link];

import [Link];
import [Link];
import [Link];
import [Link];

@Target([Link])
@Retention([Link])
public @interface VzapDeveloperAnnotation {
String developer() default "Vzapper";
int version() default 1;
}

Not too taxing is it? Next, let us create a class called OurSillyClass, which has a
few methods and assign our custom annotation @VzapDeveloper to each of them;
package [Link];

import [Link];

public class OurSillyClass {


@VzapDeveloper (developer="Stuart")

PAGE 202
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

public void fooMethodA() {


[Link]("This method is written by Stuart");
}

@VzapDeveloper (developer="Gill", version=4)


public void fooMethodB() {
[Link]("This method is written by Gill");
}

@VzapDeveloper ()
public void fooMethodC() {
[Link]("This method is written by Vzapper");
}
}

Notice in OurSillyClass: for the annotation assigned to fooMethodA, we


assigned a developer, yet left the version as default. For the annotation assigned
to fooMethodB, we assigned a developer and an updated version. Lastly, for the
annotation assigned to fooMethodC, we are using the default values.

Now for our test method. Here we are using reflection to read the annotations and
get the method names, which we print out;
import [Link];
import [Link];
import [Link];
import [Link];

public class CustomAnnotationParsingTest {

public static void main(String[] args) throws ClassNotFoundException {


Method[] methods = [Link]("[Link]").getMethods();
for(Method meth : methods){
for(Annotation ann : [Link]()){
if(ann instanceof VzapDeveloper){
VzapDeveloper dev = (VzapDeveloper)ann;
[Link]("Developer's name: "+[Link]());
[Link]("Version number: "+[Link]());
[Link]("Method's name: "+[Link]());
[Link]("***********************\n");
}
}
}
}

Do you understand this code? I am sure you do! If you run this example, your
output should look like this;
Developer's name: Stuart
Version number: 1
Method's name: fooMethodA
***********************

PAGE 203
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

Developer's name: Gill


Version number: 4
Method's name: fooMethodB
***********************

Developer's name: Vzapper


Version number: 1
Method's name: fooMethodC
***********************

There is still more we can discuss regarding annotations but what you have here
gives you most of what you need to know.

In closing - just some other notes on annotations:


• A marker annotation is a special kind of annotation that contains no members.
Its sole purpose is to mark an item. @FunctionalInterface and
@SafeVarargs are examples of marker annotations. Here is another;
public @interface VzapAnnotate{ }
• When using default values, the actual value assigned the element must be of a
type compatible with the element’s type.
• A single-member annotation contains only one member. It works like a normal
annotation except that it allows a shorthand form of specifying the value of the
member. When only one member is present, you can simply specify the value
for that member when the annotation is applied you do not need to specify the
name of the member. However, in order to use this shorthand, the name of the
member must be value.

PAGE 204
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

GENERICS
One of Java’s strengths is type checking. If you declare a variable as a type int,
you will not be allowed to assign a double to it. We have not yet discussed Java’s
Collections [essentially data structures] API as yet, but will make reference to it in
this section. So prior to JDK5, collection classes held type Object. This meant that
an object of any type could be assigned to the elements of a collection, as every
class in Java extends from Object. This is a problem, as ClassCastException is
regularly generated during runtime as incorrect objects were being assigned to the
collection’s elements. To overcome this problem JDK5 introduced generics.
Generics provide compile-time type checking thereby removing the risk of
ClassCastException from occurring at runtime. The whole collection framework
has been re-written to use generics for type-safety.

Let us look at a simple example;


List list = new ArrayList();
[Link]("abc"); //adding a String to the collection
[Link](new Integer(5)); //adding an Integer to the collection

// Iterate through the collection


for(Object obj : list){
String str=(String) obj; //ClassCastException at runtime
}

Here we have created a collection instance, in our case a List. We next add a few
Java Object instances, namely a String and an Integer to this collection. We then
iterate through the collection. Writing this code and compiling it with a compiler
lower that JDK5, compiles fine. However, when you run this code, as you iterate
through the collection, a ClassCastException is thrown as you are trying to cast
Object in the list to String whereas one of the elements in the collection is of type
Integer. If you used generics, this would not happen. So from JDK5 and later,
you use collection classes as follows;
List<String> list1 = new ArrayList<String>();
[Link]("abc");
[Link](new Integer(5)); //compiler error

for(String str : list1){


//no type casting needed, avoids ClassCastException
}

If you compile this code a compiler error will be generated. This is due to the fact
you have specified the element type in the list to be of type String by using the
notation <String> where the angled brackets define the generic parameter. Doing
this prohibits you adding any other type of object to the list. Notice too, in the for

PAGE 205
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

loop you no longer type cast each element in the list, thereby preventing the
ClassCastException occurring at runtime.

Incidentally, from JDK7 and later you can replace the line
List<String> list1 = new ArrayList<String>();

With the following;


List<String> list1 = new ArrayList<>();

Java Generic Class


You may define your own classes with a generic type. A generic type is a class or
interface that is parameterized over types. As mentioned you use angle brackets
(<>) to specify the type parameter. To understand the benefit, let us say we have a
simple class;
public class VzapGenerics{
private Object name;
public static void main(String args[]){
VzapGenerics vg = new VzapGenerics("Stuart");
[Link]("Name is: "+(String)[Link]()); // type casting, error prone and
// can cause ClassCastException
[Link]("Bob");
[Link]("Name is: "+ (String)[Link]()); // type casting, error prone and
// can cause ClassCastException
}

public VzapGenerics(Object aname){


[Link]=aname;
}

public Object getName(){


return name;
}

public void setName(Object aname) {


[Link] = aname;
}
}

Notice have had to type cast, which could result in ClassCastException being
thrown at runtime. Before I illustrate how to modify this class using generics, it
would be fruitful to understand Java’s generic types first.

Java’s generic type naming convention help understand your code. Usually type
parameter names are single, uppercase letters to make them easily distinguishable
from your variables. The most commonly used type parameter names are:
• E - Element
• K - Key
• N - Number

PAGE 206
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

• T - Type
• V - Value
• S, U, V etc - 2nd, 3rd, 4th types

Let us rewrite the class shown earlier, and include Java’s generic types naming
convention we have just looked at. Here is the modified class;
public class VzapGenerics<T> {
private T name;
public static void main(String args[]){
VzapGenerics<String> vg = new VzapGenerics<String>("Stuart");
[Link]("Name is: "+[Link]());
[Link]("Bob"); //valid
[Link]("Name is: "+[Link]());

VzapGenerics vg1 = new VzapGenerics("Gillian"); //raw type


[Link]("Name is: "+[Link]());
[Link](10); //valid - autoboxing support
[Link]("Name is: "+[Link]());
}

public VzapGenerics(T aname){


[Link]=aname;
}

public T getName(){
return [Link];
}

public void setName(T aname){


[Link]=aname;
}

Let us examine this program carefully. First, notice how VzapGenerics is declared
by the following line:
public class VzapGenerics<T> {

Here, T is the name of a type parameter. This name is used as a placeholder for the
actual type that will be passed to VzapGenerics when an object is created. Thus, T
is used within VzapGenerics whenever the type parameter is needed. Notice that T
is contained within <>. Whenever a type parameter is being declared, it is specified
within angle brackets. Because VzapGenerics uses a type parameter,
VzapGenerics is a generic class, which is also called a parameterized type.

Next, T is used to declare an object called name, as shown here:


private T name;

PAGE 207
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

As explained, T is a placeholder for the actual type that will be specified when a
VzapGenerics object is created. So, name will be an object of the type passed to T.
For example, if type String is passed to T, then in that instance, name will be of type
String. Now consider VzapGenerics’ constructor:
public VzapGenerics(T aname){
[Link]=aname;
}

Notice that its parameter, aname is of type T. This means that the actual type of
aname is determined by the type passed to T when a name object is created. Also,
because both the parameter aname and the member variable name are of type T,
they will both be of the same actual type when a VzapGenerics object is created.
This also applies to the method;
public void setName(T aname){
[Link]=aname;
}

Here both the parameter aname and the member variable name are of type T, and so
will both be of the same actual type.

The type parameter T can also be used to specify the return type of a method, as is
the case with the getName()method, shown here:
public T getName(){
return [Link];
}

Because name is also of type T, its type is compatible with the return type specified
by getName().

The main() method demonstrates our class. It first creates a version of


VzapGenerics for Strings, as shown here:
VzapGenerics<String> vg = new VzapGenerics<String>("Stuart");

Look closely at this declaration. First, notice that the type String is specified within
the angle brackets after VzapGenerics. In this case, String is a type argument that
is passed to VzapGenerics’s type parameter, T. This effectively creates a version
of VzapGenerics’s in which all references to T are translated into references to
String. So, for this declaration, name is of type String, and the return type of
getName() is of type String.

It is interesting to note that the Java compiler does not actually create different
versions of VzapGenerics or of any other generic class. Instead, the compiler
removes all generic type information, substituting the necessary casts, to make your
code behave as if a specific version of VzapGenerics were created. Thus, there is

PAGE 208
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

really only one version of VzapGenerics that actually exists in your program. The
process of removing generic type information is called erasure.

Notice that when the VzapGenerics constructor is called, the type argument String
is also specified. This is because the type of the object (in this case vg) to which the
reference is being assigned is of type VzapGenerics <String>. Thus, the
reference returned by new must also be of type VzapGenerics <String>. If it is
not, a compile-time error will result. For example, the following assignment will
cause a compile-time error:
VzapGenerics<String> vg = new VzapGenerics<Double>(3.14159);

Because vg is of type VzapGenerics<String>, it cannot be used to refer to an


object of VzapGenerics<Double>. This type checking is one of the main benefits
of generics because it ensures type safety.
[Link](10);

makes use of autoboxing to encapsulate the value 10, which is an int, into a
String.

Next, the program displays, on your console, the value of name by use of the
following line:
[Link]("Name is: "+[Link]());

Because the return type of getName() is T, which was replaced by String when vg
was declared, the return type of getName() is also a String. Thus, there is no need
to cast. Should you not provide the type at the time of creation, as we do in the
following line;
VzapGenerics vg1 = new VzapGenerics("Gillian");

The compiler issues a warning along the lines of:


warning: [unchecked] unchecked call to VzapGenerics(T) as a member of the raw
type VzapGenerics
VzapGenerics vg1 = new VzapGenerics("Gillian"); //raw type
^
where T is a type-variable: T extends Object declared in class VzapGenerics

By the way you can use @SuppressWarnings("rawtypes") annotation to


suppress the compiler warning. But you knew this already, didn’t you?

So, the full syntax for declaring a reference to a generic class and instance creation
is;
class-name<type-arg-list> var-name = new class-name<type-arg-list>(arg-list);

PAGE 209
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

In similar way, you are able to create generic interfaces. For example, here is Java’s
Comparable interface definition;
public interface Comparable<T> {
public int compareTo(T o);
}

You may also have multiple type parameters such as in Java’s Map interface. For
example:
new HashMap<String, List<String>>();

Generic Methods
Sometimes you may not want the whole class to be parameterized as we did in our
previous example. In situations like these you may create a generic method. For
example;
public class VzapGenericsMethods {
public static void main(String args[]){
VzapGenericsMethods vgm=new VzapGenericsMethods();
VzapGenerics<String> vg1 = new VzapGenerics<>("Stuart");
VzapGenerics<String> vg2 = new VzapGenerics<>("Gill");

boolean isEqual = vgm.<String>isEqual(vg1, vg2);


[Link]("1] Are they equal? "+isEqual);

vg2 = new VzapGenerics<>("Stuart");


isEqual = vgm.<String>isEqual(vg1, vg2);
[Link]("2] Are they equal? "+isEqual);
}

//Java Generic Method


public<T> boolean isEqual(VzapGenerics<T> vgA, VzapGenerics<T> vgB){
return [Link]().equals([Link]());
}

Notice the isEqual method signature;


public<T> boolean isEqual(VzapGenerics<T> vgA, VzapGenerics<T> vgB)

illustrating how to use generic types in methods. If you peruse the code, I am sure
you will be able to understand what is going on.

Generics Bounded Type Parameters


What if you want to restrict the object type that may be used in the parameterized
type? For example in a method that compares two objects and you want to make
sure that the accepted objects are Comparables. To do this you declare a bounded
type parameter, list the type parameter’s name, followed by the extends keyword

PAGE 210
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

which in turn is followed by its upper bound. Sounds complicated, so here is an


example;
public static <T extends Comparable<T>> int compare(T t1, T t2){
return [Link](t2);
}

The invocation of methods like these is similar to unbounded methods, as shown


earlier, except that if, in this example, you use any class that is not of type
Comparable, a compile time error will be thrown. Bounded type parameters may
also be used with classes and interfaces.

Java Generics supports multiple bounds, for example;


<T extends A & B & C>

A may be an interface or class. If A is class then B and C should be interfaces. You


cannot have more than one class in multiple bounds.

Java Generics and Inheritance


You know that you may assign a reference variable B to another reference variable
A if B is a subclass of A. So naturally, you might think that any generic type of B can
be assigned to generic type of A. This in not allowed, for example;

public class VzapGenericsInheritance {


public static void main(String[] args) {
String str = "VZAP";
Object obj = new Object();
obj=str; // works because String is-a Object

MyClass<String> myClass1 = new MyClass<String>();


MyClass<Object> myClass2 = new MyClass<Object>();
myClass2=myClass1; // compilation error since MyClass<String> is not
// a MyClass<Object>
obj = myClass1; // MyClass<T> parent is Object
}

public static class MyClass<T>{}

Look at the program’s comments. You are not allowed to assign a


MyClass<String> variable to a MyClass<Object> variable because they are not
related, as MyClass<T> parent is Object. The compiler error generated when you
compile this example will be along the lines of;
error: incompatible types: MyClass<String> cannot be converted to
MyClass<Object>

PAGE 211
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

Java Generic Classes and Subtyping


You can subtype a generic class or interface by extending the class or
implementing the interface. The relationship between the type parameters of one
class or interface and the type parameters of another are determined by the
extends and implements clauses. For example, ArrayList<E> implements
List<E> which in fact extends Collection<E>. This therefore means that
ArrayList<String> is a subtype of List<String> and List<String> is
subtype of Collection<String>.

The subtyping relationship is preserved as long as you do not change the type
argument. Here is an example of multiple type parameters.
interface VzapList<E,T> extends List<E>{
}

So in this
the case,
subtypes of List<String> may be
VzapList<String,Object>, VzapList<String,Integer> and so on.

Java Generics Wildcards


Wildcards may be used in generics that represent an unknown type. You make use
of the Question mark (?). A wildcard may be used as the type on a parameter, field,
or local variable and return type. We may not use wildcards while invoking a
generic method or instantiating a generic class. In following sections, we will look
at upper bounded wildcards, lower bounded wildcards, and wildcard capture.

Upper Bounded Wildcard


Upper bounded wildcards are used to relax the restriction on the type of variable in
a method. Assume you want to write a method that will return the sum of numbers
in a list, so your implementation will be something like this;
public double sum(List<Number> list){
double sum = 0;
for(Number n : list){
sum += [Link]();
}
return sum;
}

There is a problem with this code. It will not work with a List of Integer or
Double because, as you already know, List<Integer> and List<Double> are not
related. In situations like these, upper bounded wildcards may be used. You use a
wildcard with the extends keyword and the upper bound class or interface that
will allow you to pass an argument of upper bound or its subclass’ types. Let us
ammend our sum() method and write a simple test example to illustrate this;

PAGE 212
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

import [Link];
import [Link];

public class VzapGenericsWildcards {

public static void main(String[] args) {


VzapGenericsWildcards vgw= new VzapGenericsWildcards();
List<Integer> ints = new ArrayList<Integer>();
[Link](3);
[Link](5);
[Link](10);
double sum = [Link](ints);
[Link]("Sum of the integers = "+sum);
}

public double sum(List<? extends Number> list){


double sum = 0;
for(Number n : list){
sum += [Link]();
}
return sum;
}
}

Notice that an extends clause has been added to the wildcard in the declaration of
parameter list in the sum() method’s declaration. It states that the ? can match
any type as long as it is Number, or a class derived from Number. Thus, the extends
clause establishes an upper bound that the ? can match. Additionally, note that with
upper bounded list, you are not allowed to add any object to the list. If you try
to add an element to the list inside the sum() method, the program will not
compile.

Java Generics Unbounded Wildcard


Sometimes you may have a situation where you want your generic method to be
working with all types, in this case unbounded wildcards can be used. For example;
public static void vzapData(List<?> list){
for(Object obj : list){
[Link](obj + " -> ");
}
}

Essentially this is the same as using <? extends Object>. So, in our example
you may provide List<String> or List<Integer> or any other type of Object
as an argument to the vzapData() method. As is the case in the upper bound list,
you are not allowed to add anything to the list.

Java Generics Lower bounded Wildcard


Suppose you would like to add Integers to a list of integers in a method. You can
keep the argument type as List<Integer> but it will be tied up with Integers

PAGE 213
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

whereas List<Number> and List<Object> can also hold integers, so what you
can do is make use of lower bound wildcards. To achieve this use the generics
wildcard (?) together with the super keyword and lower bound class. For example;
public void addIntegers(List<? super Integer> list){
[Link](new Integer(50));
}

Java Generics Type Erasure


As you know, generics were added to provide type-checking at compile time and it
has no use at run time. An important constraint that governed the way that generics
were added to Java was the need for compatibility with previous versions of Java.
Simply put, generic code had to be compatible with preexisting, non-generic code.
So, any changes to the syntax of the Java language, or to the JVM, had to avoid
breaking older code. The way Java implements generics while satisfying this
constraint is through the use of erasure. This is essentially how erasure works.
When your Java code is compiled, all generic type information is removed (erased).
This means replacing type parameters with their bound type, which is Object if no
explicit bound is specified, and then applying the appropriate casts (as determined
by the type arguments) to maintain type compatibility with the types specified by
the type arguments. The compiler also enforces this type compatibility. This
approach to generics means that no type parameters exist at run time. They are
simply a source-code mechanism.

That is all for generics. Java generics is a vast topic and requires a lot of time to
understand and use it effectively.

PAGE 214
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

THE COLLECTIONS FRAMEWORK


Java comes with a wonderful API, the Collections API. It consists of a number of
classes as well as interfaces that allows you to store and manipulate groups of data
as one unit. In computer science when you refer to an object that holds or contains
a collection of other objects it is known as a data structure. The purpose of these
data structures is to allow you to store, retrieve and manipulate objects in the
collection. They provide some very important functionality to the Java run-time
environment. It might sound simple, but some of these data structures can become
extremely complex. Fortunately for us, Java developed the Collections Framework
in such a way that much of the complexity is hidden. Some of the data structures
available are;
Maps
Sets
Lists
Trees
Hashtables, etc

As these data structures are object-oriented, the Java classes in the Collections
Framework encapsulate both the data structures as well as the algorithms associated
with these abstractions. Incidentally, these algorithms are polymorphic. This
therefore allows the same method to be used on many different implementations of
the appropriate collection interface. This will be demonstrated later.

Before the Collections Framework came into being, there were a number of other
data structures available to the developer which are located in the [Link]
package. These data structures are;
Arrays
Vector class
Enumeration interface
Stack class
Dictionary, Hashtable and Properties classes
BitSet class

Before moving on to the updates Collections Framework, let us look at some of the
historical collections. Please note that the words ‘collection’ and ‘container’ are
synonymous. Notice too that we will be using generics in all the examples.

Arrays
If you recall, an array is of a fixed size and may contain only one type. These types
may be primitive or derived complex types (objects). The only way that you may

PAGE 215
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

increase or decrease the size of an array is to create a new array, or use the
arrayCopy() method which will automatically create a new array for you. There is
no other way of changing its size. When you create an array, the compiler requires
that the size of the array be supplied. Should no values be supplied upon creation,
then the elements default to a false for type boolean, null for an array of
Objects or 0 (zero) for everything else. It is important to remember that arrays are
objects. Once an array has been created it is easy to determine the actual size of the
array (i.e. how many elements the array contains) by looking at the value contained
in the [Link] attribute. One of the strengths of the Arrays class is that it is
capable of sorting.

The way you accesses an element in an array is to place the element number of type
integer (int) in square brackets. This in reality is an offset from the start of the
array. Remember you cannot use a long data type. Also, if you exceed the bounds
of the array an ArrayIndexOutOfBoundsException is thrown. If this type of
exception is generated, whose fault is it?

Vector
The Vector class is very similar to the Arrays class, except that it will grow as
required. As a Vector instance starts to ‘run out of storage space’, it will
automatically grow. So, by using Vectors you do not need to know the exact size
before creation. Not only can a Vector instance grow as required, but it can also
store heterogeneous data types. In other words, it is not restricted to the
containment of a single data type.

When you create a Vector object, it is possible to create an empty Vector, a


Vector of specific size or a Vector of specific size as well as a capacity
increment. I would strongly advise that you use the third way of creating a Vector.
The reason for this lies in the fact that if you do not specify the capacity increment,
the default capacity increment is used. This default is the size of the original
Vector created. This means that each time the Vector needs to increase in size, it
does so by doubling itself. If your Vector is initially fairly large, then this type of
increase behavior in not very desirable. By setting the capacity increment, the
Vector instance will grow by this amount each time. A word of advice; if you
know the amount of elements that you will add, then set the size of the Vector to
that size upon initialization. The reason for this is to do with performance. The
operation to increase the size of the Vector is rather costly. So if you are able to
reduce this overhead, do so.

The Vector’s constructors look as follows;

PAGE 216
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

public [Link]();
public [Link](int startCapacity);
public [Link](int startCapacity, int capacityIncrement);

// this constructor is new from JDK1.2 onwards


public [Link](Collection<? Extends E> c);

To work with the elements of a Vector is straightforward. Adding objects to a


Vector instance may be done (in addition to the methods supplied by List) in two
ways. You may add an object to the end of a Vector instance or you may insert an
object to any desired position within the Vector instance. To add an object to the
end of a Vector instance you would make use of the method;
public synchronized void addElement(E newObject);

The size of the Vector instance will then increase its size by one after this method
has been invoked. Note that the capacity of the Vector instance is increased if its
size becomes greater than its capacity.

To add an object to a Vector instance at a certain position, you would use the
method;
public synchronized void insertElementAt(E newObject, int index);

Be aware that this method will throw an ArrayIndexOutOfBoundsException if


the index was invalid. For example, if your Vector instance is 20 elements big, and
you try to insert an element into position 24, this exception will be generated.

To change the object at a specific position, you will make use of the method;
public synchronized void setElementAt(E changingObject, int index);

To be able to access an object contained within a Vector instance, you would use
the method;
public synchronized E elementAt(int index);

The equivalent way to access an element using arrays would be to use square
brackets. For example, if you wish to access the 13 element in an array called
myArray, you would write the following code;
int value = myArray[13]; // this array contains ints

To perform a similar task using Vectors of String type, you would write the
following code;
String s = (String)[Link](13); // returning a String object

To access the first and last elements the following two methods are used;
public synchronized E firstElement();

PAGE 217
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

public synchronized E lastElement();

Incidentally, firstElement() returns the first component (the item at index 0) of


a Vector instance and will throw a NoSuchElementException if the Vector
instance has no components. In a similar manner, lastElement() returns the last
component of the vector, (i.e., the component at index size()–1) and will throw a
NoSuchElementException should the Vector instance be empty.

In the above statement I referred to the size() method. This method is useful in
that it informs you as to how many elements are present within a Vector instance.
By making reference to this method, you should never exceed the bounds of a
Vector instance.

To search for elements within a Vector instance you may make use of the
following method;
public boolean contains(Object searchTheObject);

If the object is found then the boolean value returned is true, otherwise it is false.
This method makes use of the built in search functions, which are pretty good.

It is possible to find the location of the first occurrence of an element (or Object)
within a Vector instance. To execute this, one of the following methods may be
used;
public int indexOf(Object findThisObject);
public synchronized int indexOf(Object findThisObject, int startSearchHere);

The first method will start its search at the beginning of the Vector instance. It will
return the position of the object if it is found, otherwise a –1 is returned. The
second method will also search for the first instance of the object, but the search
will start from the position dictated by startSearchHere. This method will also
return the position of the first occurrence of the required object being searched, or a
–1 if it is not contained within the Vector instance.

What happens if you want to find the last occurrence of a specific object within a
Vector instance? This can be achieved by invoking the methods;
public int lastIndexOf(Object findThisObject);
public synchronized int lastIndexOf(Object findThisObject, int startSearchHere);

The explanations of the parameters are the same as for the previously mentioned
methods. Note however, the two methods requiring a search index, (i.e.
startSearchHere parameter), will throw a IndexOutOfBoundsException if
index is less than 0, greater than or equal to the current size of the Vector instance.

PAGE 218
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

It is possible to cycle through a Vector instance in order to find an Object


contained within the Vector instance. To do this you use the elements() method
to get an Enumeration object for the Vector instance. Once you have an
Enumeration object, then you make use of two of its methods to migrate
sequentially through the Vector instance. These methods are;
public boolean hasMoreElements();
public E nextElement();

hasMoreElements() method tests to see if the Enumeration contains any more


elements. It will return true if and only if the enumeration object contains at least
one or more elements. If not, a false is returned. The nextElement() returns the
next element of the enumeration if the Enumeration object has at least one more
elements to provide. To clarify this a little, let us look at a snippet of code;
// some code here
Enumeration myEnum = [Link](); // I have an enumeration object,
// myEnum, for myVector
// after this line of code
// has run.

while([Link]()){
myObject = [Link](); // get next element
// now manipulate myObject
}
// some more code here

Now that you know how to add, search and manipulate objects contained within a
Vector instance, how do you remove elements? As you may well have guessed,
there are methods to do this for us. In essence, there are four ‘remove’ methods.
These are;
public synchronized boolean removeElement(Object removeThisObject);
public synchronized void removeElementAt(int remove);
protected void removeRange(int fromIndex, int toIndex);
public synchronized void removeAllElements();

To remove the first instance of an object from a Vector instance, you make use of
the method removeElement(). Here you pass, as an argument, the object to be
removed. If the object is successfully removed, then the method returns a true,
otherwise it will return a false.

In a similar manner, you can stipulate that you wish to remove an object from a
specific position. This is performed by invoking the removeElementAt() method.
Here you pass the position of the object you want to remove. The index must be a

PAGE 219
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

value greater than or equal to 0 and less than the current size of the Vector
instance otherwise an ArrayIndexOutOfBoundsException is thrown.

You may remove a range of objects from a Vector instance. This is done by
invoking the removeRange() method. All elements fromIndex to toIndex will
be removed. If the fromIndex and toIndex are the same value, then nothing is
removed.

To clear the whole Vector instance of objects, invoke the removeAllElements()


method. Once all the elements have been removed the size of the Vector instance
is set to 0.

Finally, to be able to control the size of a Vector instance there are a few methods
you may make use of. For instance the method;
public int capacity();

informs you as to how many elements the Vector instance can hold before it has to
increase in size.

To increase the capacity of a Vector instance invoke the method;


public synchronized void ensureCapacity(int minimumCapacity);

This ensures that the Vector instance can store at least minimumCapacity. If the
Vector instance is less than the minimumCapacity, it allocates more space.

To reduce the Vector instance capacity invoke the method;


public synchronized void trimToSize();

To just set the size of the Vector instance invoke;


public synchronized void setSize(int newSize);

Just be careful when using this last method. If you stipulate newSize to be less than
the old size of the Vector instance, then all those elements at the end of the
Vector instance will be lost. Do you think that setSize(0) has the same effect as
removeAllElements()? On the other hand, if the newSize is greater than the old
size, all the newly added elements will be set to null.

There are many more methods found in the Vector class. Please look at Java’s API
documentation. In closing this section on Vector, I have written a really simple
demo program to give you an idea of how to use them.

PAGE 220
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

import [Link];
import [Link];

public class VzapVectors{


Vector<String> myVector = new Vector<String> ();
Enumeration myEnum;

public static void main(String[] args){


VzapVectors testIt = new VzapVectors();
[Link]();
}

void run(){
[Link]("\nWelcome to the Vector Demo!\n");

// add String objects to the vector


[Link]("Position One");
[Link]("Position Two");
[Link]("Position Three");
[Link]("Position Four");

// let us now print each out element using Vector methods.


// using the standard for loop
for(int i=0; i<[Link](); i++){
[Link]("Element at " + [Link](i));
}

// let us add some more elements and change the previous ones
[Link]("Position Zero", 0);
[Link]("Position Five", 5);
[Link]("Position One Still",1);
[Link]("Position Four Still",4);

[Link]("\nLet us View the Changed List.");


// now let us use an Enumeration to view changed and added elements
myEnum = [Link]();
while([Link]()){
[Link]("Element at " + [Link]());
}

[Link]("See how I, \"myVector\", has grown and changed.");


// now let us remove some elements from myVectors
[Link]("\nLet us View the Changed List where" +
" elements have been removed.");
[Link](2);
[Link](4);

for(int i=0; i<[Link](); i++){


[Link]("Element at " + [Link](i));
}

[Link]("See how I, \"myVector\", has shrunk and changed.");


} // end of run()
} // end of TestVector Class

The output of the above code will look as follows;


Welcome to the Vector Demo!

PAGE 221
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

Element at Position One


Element at Position Two
Element at Position Three
Element at Position Four

Let us View the Changed List.


Element at Position Zero
Element at Position One Still
Element at Position Two
Element at Position Three
Element at Position Four Still
Element at Position Five
See how I, "myVector", has grown and changed.

Let us View the Changed List where elements have been removed.
Element at Position Zero
Element at Position One Still
Element at Position Three
Element at Position Four Still
See how I, "myVector", has shrunk and changed.

Stack
A Stack in Java is derived from the Vector class. In essence, this means that a
Vector is made to operate as a Stack. The methods available to you in the Vector
class are also available in the Stack class.

The operation of a stack in Java is very similar to stacking plates. The plate that is
placed at the bottom of the pile (stack) is the last one to be used. The last one
placed on the pile is the first plate to be used. This process is known as FILO or
First-In-Last-Out. The methods defined have similar names to the machine code
instructions for working with stacks.

There is only one constructor for creating an instance of Stack. This is;
public Stack();

Once you have a Stack instance you can add items to it. To perform this task you
must invoke the method;
public E push(E newItem);

Notice that the method returns an Object. This object returned is the same as that
one pushed onto the stack. You are not restricted to this method of adding items to
the Stack instance. You may also use;
public synchronized void addElement(E newObject);

If you recall, this method is defined in the Vector class, and is therefore inherited
by the Stack class. It has the same effect as push(), except that void is returned.

PAGE 222
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

Once an item has been added to a Stack instance, it is permissible to remove the
top item from the stack. To do this invoke the method;
public synchronized E pop();

The object at the top of the Stack instance is the one returned and removed. Be
aware that if the Stack is empty an EmptyStackException is thrown.

There is a method which allows you to inspect the item at the top of the stack,
without actually removing the item. This is;
public synchronized E peek();

It will throw an EmptyStackException should the Stack instance contain no


items.

To find out whether the Stack instance is empty, invoke the method;
public boolean empty();

This method will return a true if the stack is empty. For all other conditions a
false is returned.

There is one last method found in the Stack class. This method will search for an
item within a Stack instance. If it finds the item requested, it will return an integer
value of how far that object item is from the top of the stack. If there is no object
item that exactly matches the requested item, a –1 is returned by the method.
Incidentally, the top most object item on the Stack instance is 1.

All the methods defined within the Stack class are listed below;
public class Stack<E> extends Vector<E> {
public Stack();
public E push(E);
public synchronized E pop();
public synchronized E peek();
public boolean empty();
public synchronized int search(E);
}

To close this section on the Stack class, here is a small program showing how a
Stack instance may be used.

import [Link];

public class VzapStack{


String[] myArray = {"One", "Cup", "Of", "Java", "Please"};
Stack<String> myStack = new Stack<String>();

PAGE 223
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

public static void main(String[] args){


VzapStack myStackTest = new VzapStack();
[Link]();
}

void run(){
//print out what is in the array
[Link]("\nThis is what the array contains");
for(int i=0; i<[Link]; i++){
[Link](myArray[i] + " ");
}
[Link]("\n\nCopying the contents of the array to" +
"an instance of Stack");
for(int i=0;i<[Link]; i++){
[Link](myArray[i]);
}
[Link]("\nLet us see what the top element of the Stack contains.");
[Link]((String)[Link]());

[Link]("\nNow let us pop the contents off the Stack.");


while (![Link]()){
[Link]((String)[Link]() + " ");
}
[Link]();
}
}

The output generated by the above program is;


This is what the array contains
One Cup Of Java Please

Copying the contents of the array toan instance of Stack

Let us see what the top element of the Stack contains.


Please

Now let us pop the contents off the Stack.


Please Java Of Cup One

Hashtable
The Hashtable class provides key-based data storage and retrieval. It is a subclass
of the Dictionary class. I will not discuss the Dictionary class as it has been
rendered obsolete by the Map interface. Whereas Hashtables have not. You will
find that a Hashtable is often used to associate a name with an object. The object
may then be retrieved using that name. The name object is a key, which can be any
object, and the object associated with that key is known as a value. Put another
way, hash-codes are an integer value that identify an object. This hash-code is
generated in such a way that different objects will very likely have different hash
values, and therefore have different keys. A key may be associated with one value.
However, a value may have many keys.

PAGE 224
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

This key is used for lookup purposes. Its role is to help locate a specific value. The
Hashtable class uses the hash code of the key objects to perform the lookup.
Groups of keys are grouped together and placed in buckets based on their hash
code. When a Hashtable instance goes to find a key, it queries the key’s hash code
to get the correct bucket, and then searches the bucket for the correct key. Usually
the number of keys in a bucket is small compared to the number of keys in the
Hashtable, so the Hashtable performs only a fraction of the comparisons
performed in most other collections such as in a Vector.

The Hashtable class has four constructor methods. These are;


public [Link]();
public [Link](int capacity);
public [Link](int capacity, float loadFactor);
public [Link]([Link]<? extends K,? extends V> t);

The first constructor creates a Hashtable instance with a default capacity of 101
and a default load factor threshold of .75. What is this capacity and load factor?
Capacity is the number of buckets the Hashtable instance is to use and the load
factor is the ratio of the number of elements in the Hashtable instance to the
number of buckets in the table. The range of this load factor is a float value
between 0.0 and 1.0. The function of this load factor is to identify the percentage
hash table usage that causes the table to be rehashed into a larger table. For
example; if you use the default load factor of 75% (i.e. 0.75f) with a capacity of
101 elements. When the Hashtable instance is 75% full, a new, larger Hashtable
will be created. All the elements present in the ‘old’ Hashtable will have their
hash values recalculated for the new larger table. Be aware though, the smaller the
load factor (i.e. the closer to 0.0f) the faster the lookup process. This is because
there will be fewer keys per bucket, but the table will then have more buckets than
elements resulting in wastage of valuable space. However, the larger the load value
(i.e. the closer to 1.0f) the slower the look-up process, but the space wastage is
kept to a minimum as the number of buckets is closer to the number of elements. A
good load factor value is between 0.70f and 0.75f.

The second constructor allows the programmer to specify the initial capacity of a
Hashtable instance, but uses the default load factor value. An
IllegalArgumentException is thrown if the initial capacity is less than zero.

The third constructor allows a Hashtable instance to be created using specific


initial capacity and load factor values. An IllegalArgumentException is thrown
if the initial capacity is less than zero, or if the load factor is nonpositive.

PAGE 225
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

Now that you have an overview of what a hash table is, let us now look at some of
the methods contained in the Hashtable class.

To place an element in a Hashtable instance invoke the method;


public synchronized E put(K key, V value);

This method will map the specified key to the specified value in a Hashtable
instance. It is important to note that neither the key nor the value can be null. If
you are naughty and does pass a null for either of these parameters, a
NullPointerException will be thrown. Notice that this method returns an object
instance. The object returned will be the previous object associated with the key.
Should there not have been any object associated with the key, a null is returned.

If you wish to find out how many key-value pairs are stored in a Hashtable
instance then you would invoke the method;
public int size();

Should you wish to find out if the Hashtable instance contains no key-value pairs,
then you would invoke the method;
public boolean isEmpty();

If the Hashtable instance is empty then a boolean true is returned, otherwise a


false is returned.

If you want to remove a key-value pair from a Hashtable instance, you would
invoke the method;
public V remove(Object key);

The object returned is the one associated with the key. If no value is associated
with the key, a null is returned.

To return all the keys or all the values in a Hashtable instance you would invoke
the following two methods, respectively;
public synchronized Enumeration<K> keys();
public synchronized Enumeration<V> elements();

Notice that an Enumeration is returned by each of these methods.

To inquire whether a Hashtable instance contains a specific value, you would


invoke the method;
public synchronized boolean contains(Object value);

PAGE 226
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

There are other methods contained within the Hashtable class. Go and peruse the
Java

Below is some simple code to demonstrate some of the features of Hashtables.


import [Link];
import [Link];

public class VzapHashTable{


Hashtable<String,String> myHashTable = new Hashtable<String,String>();
Enumeration<String> myEnum;

public static void main(String[] args){


VzapHashTable ht = new VzapHashTable();
[Link]();
}

void run(){
// let us add key-values to a Hashtable
[Link]("Drink", "Drambuie");
[Link]("Contents", "750ml");
[Link]("Colour", "Honey");
[Link]("Power", "Hick!!! Yummie");

// let us now printout the contents of the Hashtable


[Link]("\nThe contents of the Hashtable instance are:\n" + myHashTable);

// let us now look at only the values contained in the Hashtable


// Remember, these will be returned in an Enumeration
[Link]("\nLet us view just the \"values\" in the Hashtable");
myEnum = [Link]();
while([Link]()){
[Link]([Link]());
}
// let us now look at only the keys contained in the Hashtable
// Remember, these will be returned in an Enumeration
[Link]("\nLet us view just the \"keys\" in the Hashtable");
myEnum = [Link]();
while([Link]()){
[Link]([Link]());
}
// let us now return a value that relates to a specific key in a Hashtable
[Link]("\nLet us find and view all the \"values\" in the" +
"Hashtable using the \"keys\".");
[Link]("Key = Drink : Value = " + [Link]("Drink"));
[Link]("Key = Power : Value = " + [Link]("Power"));
[Link]("Key = Contents : Value = " + [Link]("Contents"));
[Link]("Key = Colour : Value = " + [Link]("Colour"));

} // end of run()
} // end of HashTest class

The output of the above code is:


The contents of the Hashtable instance are:
{Power=Hick!!! Yummie, Drink=Drambuie, Colour=Honey, Contents=750ml}

Let us view just the "values" in the Hashtable

PAGE 227
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

Hick!!!
Yummie
Drambuie
Honey
750ml

Let us view just the "keys" in the Hashtable


Power
Drink
Colour
Contents

Let us find and view all the "values" in the Hashtable using the "keys".
Key = Drink : Value = Drambuie
Key = Power : Value = Hick!!! Yummie
Key = Contents : Value = 750ml
Key = Colour : Value = Honey

Properties
The Properties class is a specialized kind of Dictionary and is used for the
saving of properties. It is in fact a subclass of the Hashtable class. The
Properties class uses Strings for both keys and values, and is used by the System
class to store the systems properties. You will often see the statement
[Link]() that returns a Properties instance. It is axiomatic
that you use the Properties class in order to create your own set of properties.
Please be aware of one thing though; as the Properties class is a subclass of the
Hashtable class, it inherits the put() and putAll() methods. You are therefore
capable of invoking these methods from within a Properties instance. Do not do
this. The reason for this lies in the fact that the Properties class uses Strings for its
keys and values. Using the inherited put() and putAll() methods results in
entries being made in the properties list whose keys and values are not strings. It is
suggested that you should use the new method declared in the Properties class,
setProperty() instead. The method you should use when retrieving a property
with the specified key from a property list is getProperty(). So, think of the
Properties class as a Hashtable that specializes in storing strings.

The Properties class has two constructor methods. These are;


[Link]();
[Link](Properties defaults);

The empty parameter constructor creates an empty property list with no default
values. Should an empty properties list containing a set of default properties be
required, then make use of the second form of constructor. When the Properties
object is unable to locate a property in its own table, it searches the default
properties table.

PAGE 228
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

As mentioned earlier, to set properties you must use the setProperty() method
and not the inherited Hashtable methods put() and putAll() methods. The
signature for the setProperty() method is;
public synchronized Object setProperty(String key, String value);

This methods actually calls the put() method, but ensures that the property key
and value are strings.

To retrieve a property use the accessor methods;


public String getProperty(String key);
public String getProperty(String key, String defaultValues);

The first method will return a String instance corresponding to the property name
associated with key. If the key is not found in this property list, the default property
list, and its defaults, recursively, are then checked. The method returns null if the
property is not found. The second getProperty() method is identical to the first
except that the method returns the default value argument if the property is not
found.

A word of warning. If you use the put() or putAll() methods to set a property
and had then attempt to retrieve it using the getProperty() method, a
ClassCastException exception will be thrown.

It is permissible to load a Properties object from an input stream and save a


Properties object to an output stream. You would use this type of feature, for
instance, when wanting to store a user’s preferences, and then when the user logs-in
again to retrieve those preferences. In order to save the properties to a stream use;
public void save(OutputStream out, String comments);
public void store(OutputStream out, String comments);
public void store(Writer out, String comments);

Please note that the save() method has become deprecated, so always use the
store() method. Both methods are capable of throwing a ClassCastException.
However, only the store() method throws an IOException.

There are two other methods that provide a convenient way of outputting a
Properties object to PrintStream. These methods are;
public void list(PrintStream out);
public void list(PrintWriter out);

These methods are normally invoked during the development process for
debugging purposes. The data delivered is usually in a nice, friendly format.

PAGE 229
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

To read a property from an input stream use the method;


public void load(InputStream in);

Please read the Java documentation on the load() and store() methods. You
will, for example, find information on the effect various characters have when
reading or saving. For instance, when reading a property from an input stream
characters # and ! are treated as comment characters. This means that any
characters appearing on the same line after these characters are ignored, in the same
way that all characters after // in a Java source code are ignored.

There are also methods to read [loadFromXML(InputStream in)] and write [


store(Writer writer, String comments)] to streams in an XML format. Go
check out the Java API documentation on these.

To obtain information about all the property’s names (in other words, property
keys) in a Properties object, you get an Enumeration object containing all the
property names by invoking the method;
public Enumeration<?> propertyNames();

To demonstrate how to find out your System’s properties, look at the program
below. Naturally, the output displayed will be different from machine to machine.

import [Link];

public class SystemProperties{


public static void main(String[] args){
Properties mySysPops = [Link]();
[Link]([Link]);
}
}

The output on my windows machine is:


-- listing properties --
[Link]=Java(TM) SE Runtime Environment
[Link]=C:\Program Files\Java\jre1.8.0_131\bin
[Link]=25.131-b11
[Link]=Oracle Corporation
[Link]=[Link]
[Link]=;
[Link]=Java HotSpot(TM) 64-Bit Server VM
[Link]=[Link]
[Link]=
[Link]=ZA
[Link]=SUN_STANDARD
[Link]=
[Link]=Java Virtual Machine Specification
[Link]=c:\Java
[Link]=1.8.0_131-b11

PAGE 230
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

[Link]=[Link].Win32GraphicsEnvironment
[Link]=C:\Program Files\Java\jre1.8.0_131\li...
[Link]=amd64
[Link]=C:\Users\STUART~1\AppData\Local\Temp\
[Link]=

[Link]=Oracle Corporation
[Link]=
[Link]=Windows 10
[Link]=Cp1252
[Link]=C:\ProgramData\Oracle\Java\javapath;C...
[Link]=Java Platform API Specification
[Link]=52.0
[Link]=HotSpot 64-Bit Tiered Compilers
[Link]=10.0
[Link]=C:\Users\stuartfripp
[Link]=
[Link]=[Link]
[Link]=Cp1252
[Link]=1.8
[Link]=stuartfripp
[Link]=.;..;
[Link]=1.8
[Link]=64
[Link]=C:\Program Files\Java\jre1.8.0_131
[Link]=SystemProperties
[Link]=Oracle Corporation
[Link]=en
[Link]=[Link]
[Link]=mixed mode
[Link]=1.8.0_131
[Link]=C:\Program Files\Java\jre1.8.0_131\li...
[Link]=C:\Program Files\Java\jre1.8.0_131\li...
[Link]=cp437
[Link]=Oracle Corporation
[Link]=\
[Link]=[Link]
[Link]=little
[Link]=UnicodeLittle
[Link]=cp437
[Link]=windows
[Link]=amd64

BitSet
The BitSet class is used to create objects which maintain a set of bits. You are
able to perform bitwise operations on a large number of bits, as well as being able
to manipulate individual bits. As more space is required to store the bits, so the
BitSet grows to accommodate these new bits. Consider it as a Vector of bits
where a BitSet is a list of flags indicating the binary state of each element of a set
of conditions.

There are two constructors in a BitSet. These are;


public BitSet();
public BitSet(int numOfBits);

PAGE 231
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

The first constructor creates an empty BitSet object. The second constructor
creates a BitSet object of size numOfBits. The initial state of the bits are set to
false. As each bit is associated with a boolean value, a bit can only be in one of
two states; true or false. In order to set a bit, in other words assigning the bit a
true value you should invoke the method;
public void set(int bitIndex);

The argument supplied through bitIndex, must be a non-negative integer value.


This specifies the location of the bit in the BitSet object you want to set. If, by any
chance, the argument supplied is a negative integer value then an
IndexOutOfBoundsException is thrown. What is interesting about the set()
method is that if you originally created a BitSet object to contain 100 bits, and
then attempted to set bit 210, the BitSet object would grow to contain 210 bits,
and all the new bits would be set to false.

To clear a specific bit, in other words, assign a bit a false value invoke the
method;
public void clear(int bitIndex);

Just as in the set() method, the argument supplied the clear() method must be a
non-negative integer value indicating the position of the bit to clear. If this integer
value is negative then an IndexOutOfBoundsException is thrown.

To find out how many bits there are in a BitSet object you invoke the method;
public int size();

This returns an integer value of the number of bits in the BitSet object.

An interesting method is;


public int length();

What this method does is to return the ‘logical length’ of the BitSet object. In
other words it returns the index position of the ‘highest bit set plus one’. Should
there be no bits set in the BitSet object, then the value returned is zero.

To test whether a bit is true or false you invoke the method;


public boolean get(int bitIndex);

The argument supplied must be a non-negative argument representing the position


of the bit in the BitSet object to test. If the argument supplied is negative then an
IndexOutOfBoundsException is thrown. The value returned is the same as the

PAGE 232
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

state of the bit. So, if the bit at the bitIndex position is set (i.e. true), then true
is returned, otherwise the bit must be cleared (i.e. false) and false is returned.

As indicated earlier, it is possible to perform bitwise operations on BitSet objects.


These operations will manipulate the current BitSet object with another BitSet
object. What happens is that the corresponding bits in the two BitSet instances are
matched to perform the operations. For instance, the bit in position 0 of the current
BitSet is compared to the bit in position 0 of the second BitSet. The bitwise
operator methods are;
public void and(BitSet secondBitSet);
public void or(BitSet secondBitSet);
public void xor(BitSet secondBitSet);
public void andNot(BitSet secondBitSet);

The and() method performs a logical AND. The bits in the current BitSet object
are set to true, if the bit in the current BitSet instance and the second BitSet
instance are both set. Otherwise, the bit in the current BitSet is cleared. (i.e. set to
false).

The or() method performs a logical OR. The bits in the current BitSet object are
set to true if either the bit in the current BitSet object or the bit in the second
BitSet object is set (i.e. true). If neither are true then the bit in the current
BitSet object is cleared. (i.e. set to false).

The xor() method performs a logical XOR. The bits in the current BitSet object
are set to true if and only if one of the following statements holds:
• The bit in the current BitSet object initially has the value true, and the
corresponding bit in the second BitSet object has the value false.
• The bit in the current BitSet object initially has the value false, and the
corresponding bit in the second BitSet object has the value true.

The andNot() method clears all of the bits in the current BitSet object whose
corresponding bit is set in the second BitSet object.

Below is an example using BitSet class and performing some logical operations.
Read the comments in the code to see what we are doing;
import [Link];

public class BitSetTest{


BitSet bitSetOne;
BitSet bitSetTwo;
public static void main(String[] args){
BitSetTest myBST = new BitSetTest();

PAGE 233
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

[Link]();
}

// **********************
public BitSetTest(){
bitSetOne = new BitSet();
}

// **********************
public void run(){
[Link]("\nLet us see the default size and contents of bitSetOne:");
[Link]("The size in bits of bitSetOne is: " + [Link]() +
" and all bit values are: ");
displayBitSet(bitSetOne);
// notice that the default value of the bits are cleared (i.e. false).

// Let us now set every bit and then display the the BitSet
[Link]("\nSetting every bit in bitSetOne.");
for(int i = 0; i<[Link]();i++){
[Link](i);
}
[Link]("The size in bits of bitSetOne is: " + [Link]() +
" and all bit values are: ");
displayBitSet(bitSetOne);
// notice that every bit position that is set (i.e. all of them) are displayed

// Let us now replicated bitSetOne by cloning it. Then we shall display the
// new BitSet's contents.
// Then let us clear every second bit in the new BitSet. Finally, we shall
// display this new BitSet.
[Link]("\nCloning bitSetOne....The new BitSet is bitSetTwo.");
bitSetTwo = (BitSet)[Link]();
[Link]("The size in bits of bitSetTwo is: " + [Link]() +
" and all bit values are: ");
displayBitSet(bitSetTwo);
[Link]("\nClearing every second bit in bitSetTwo.");
for(int i = 0; i<[Link](); i+=2){
[Link](i);
}
[Link]("The size in bits of bitSetTwo is: " + [Link]() +
" and all bit values are: ");
displayBitSet(bitSetTwo);

// let us now logically AND bitSetOne with bitSetTwo


[Link]("\nLogically ANDing bitSetOne with bitSetTwo.");
[Link](bitSetTwo);
[Link]("Displaying the bits in bitSetOne. Notice how they have changed.");
[Link]("The size in bits of bitSetOne is: " + [Link]() +
" and all bit values are: ");
displayBitSet(bitSetOne);

// let us print out the contents of the bitSetOne using toString().


// Notice that only the bit values that are set are shown. The value
// indicated is the index of that bits position.
[Link]("\nViewing the contents of the bitSetOne using toString()." +
"Notice only the bits 'set' are displayed. ");
[Link]("The size in bits of bitSetOne is: " + [Link]() +
" and all bit values set are: " + [Link]());
}

// **********************
private void displayBitSet(BitSet bs){
[Link]('{');
for(int i=0; i<[Link]();i++){
[Link]([Link](i) + ", ");

PAGE 234
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

}
[Link]("}\n");
}
}

Running this code will produce to following output;


Let us see the default size and contents of bitSetOne:
The size in bits of bitSetOne is: 64 and all bit values are:
{false, false, false, false, false, false, false, false, false, false, false,
false, false, false, false, false, false, false, false, false, false, false,
false, false, false, false, false, false, false, false, false, false, false,
false, false, false, false, false, false, false, false, false, false, false,
false, false, false, false, false, false, false, false, false, false, false,
false, false, false, false, false, false, false, false, false, }

Setting every bit in bitSetOne.


The size in bits of bitSetOne is: 64 and all bit values are:
{true, true, true, true, true, true, true, true, true, true, true, true, true,
true, true, true, true, true, true, true, true, true, true, true, true, true,
true, true, true, true, true, true, true, true, true, true, true, true, true,
true, true, true, true, true, true, true, true, true, true, true, true, true,
true, true, true, true, true, true, true, true, true, true, true, true, }

Cloning bitSetOne....The new BitSet is bitSetTwo.


The size in bits of bitSetTwo is: 64 and all bit values are:
{true, true, true, true, true, true, true, true, true, true, true, true, true,
true, true, true, true, true, true, true, true, true, true, true, true, true,
true, true, true, true, true, true, true, true, true, true, true, true, true,
true, true, true, true, true, true, true, true, true, true, true, true, true,
true, true, true, true, true, true, true, true, true, true, true, true, }

Clearing every second bit in bitSetTwo.


The size in bits of bitSetTwo is: 64 and all bit values are:
{false, true, false, true, false, true, false, true, false, true, false, true,
false, true, false, true, false, true, false, true, false, true, false, true,
false, true, false, true, false, true, false, true, false, true, false, true,
false, true, false, true, false, true, false, true, false, true, false, true,
false, true, false, true, false, true, false, true, false, true, false, true,
false, true, false, true, }

Logically ANDing bitSetOne with bitSetTwo.


Displaying the bits in bitSetOne. Notice how they have changed.
The size in bits of bitSetOne is: 64 and all bit values are: {false, true,
false, true, false, true, false, true, false, true, false, true, false, true,
false, true, false, true, false, true, false, true, false, true, false, true,
false, true, false, true, false, true, false, true, false, true, false, true,
false, true, false, true, false, true, false, true, false, true, false, true,
false, true, false, true, false, true, false, true, false, true, false, true,
false, true, }

Viewing the contents of the bitSetOne using toString().Notice only the bits
'set' are displayed.
The size in bits of bitSetOne is: 64 and all bit values set are: {1, 3, 5, 7,
9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, 33, 35, 37, 39, 41, 43, 45, 47,
49, 51, 53, 55, 57, 59, 61, 63}

PAGE 235
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

Collections Framework
That brings us to the end of the discussion on the historical collections. Let us now
look at the Java Collections Framework (JCF). This framework was first added to
in the Java 2 platform (version 1.2) and became known as the Collection API. A lot
of work has gone into the design of this API. This Collection API has removed a lot
of non-trivial programming from the developer. All you need do is decide which
data structure will perform the best for your requirement, and then use it.

In essence, you may view a collection as a mathematical set. This is normally


taught to us at primary school where we learned about ‘set intersections’ and ‘set
unions’. Below is an example of this using Venn diagrams.

A∩ B
A B

A∩ B ∩C
A∩C B∩C

Here we have sets A, B and C. Notice that there is an intersection between A and
B, A and C, B and C, and A, B and C. Remember, members common to two or
more sets, is called an intersection of those sets. For example, the set of elements
common to both sets A and B, is called the intersection of A and B.
A set union is a set of all elements that belong to one set or the other set or to both
sets. In essence, sets are fundamental to logical thinking.

Examples of sets are:


• A set of uppercase letters ‘A’ through ‘Z’.
• A set of golf clubs {putter, sand wedge, three iron,….}
• A set of family members.
• A set of tools.
• The set of records in a database. (You’ll see this when you work with a
ResultSet in JDBC)
• The empty set { }

The basic properties of sets are as follows;


• Sets contain only one instance of each item.
• Sets may be finite or infinite.

PAGE 236
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

• Sets can define abstract concepts.

There is a special form of a set. This is called a map. A map is a set of pairs, where
one is ‘mapped’ to the other. For example, a Domain Name (DNS) is ‘mapped’ to
an Internet Protocol (IP) address. Another example is where a unique key is
mapped to a record within a database.

We are now at the point at which we may start to look at the Java Collections
Framework. You will see that the JCF is made up of a set of interfaces describing
different types of groups.

The core Collection interface takes the form of a hierarchy. This framework
hierarchy is shown here.

Collection Map

Set List SortedMap

SortedSet

As you can see, the Java Collections Framework is divided into four distinct areas.
• Collection Interface: This is the root interface of the JCF. Its real function
is to provide the methods that will be common to all the collection classes.
• Set Interface: As in mathematical sets, a Set is a collection that cannot
contain any duplicate elements.
• List Interface: This is an ordered collection. You will sometimes see this
referred to as a sequence. A List is similar to a Set, except duplicates are
allowed. A List also has the ability to allow the user to perform position-
oriented operations.
• Map Interface: As in mathematical map, a Map maps keys to values. In other
words, it is a collection of pairs. One thing to note, and this is evident in the
diagram above, there is no direct lineage between a Map Interface and a
Collection Interface.

PAGE 237
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

When working with the JCF, I recommend that although you need to implement the
interfaces, you should write code that uses the interface methods. The reason for
this is, if for any reason you want to change the underlying data structure, this is
very easily achieved without the need for altering the rest of your code. Let
polymorphism work for you.

Java provides concrete classes that implement the core collection interfaces. These
implementations occur under three categories;
• General purpose
• Wrapper
• Convenience
It is also permissible for you to create your own implementations.

As an example, the table below summarizes implementations found under the


general-purpose category. Please note the naming convention. The underlying
classes that implement the data structure include in their name, the Interface name.

Interface Implementation Historical


Set HashSet TreeSet

List ArrayList LinkedList Vector


Stack
Map HashMap TreeMap HashTable
Properties

Let us now look at these interfaces and concrete classes in some detail.

Collections Interface
As indicated earlier, the Collection interface is at the root of the Collection
hierarchy. It defines a full spectrum of methods that are used for adding, removing,
retrieving and manipulating objects from the collection. It also provides methods
that will operate on the collection itself.

The Sun team that developed the Collections Framework wanted to keep the design
simple. What they did is instead of creating multiple interfaces for optional
capabilities, the Collection interface defines all the methods an implementation
class may provide. What is important to note is that some of these methods are
optional. If you look through the API documentation you will see which methods
are optional. How does a caller know if the method is optional? The design team
decided that if a method in a collection is invoked and ‘is not present’, then an
UnsupportedOperationException is thrown. This exception, by the way, is an

PAGE 238
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

extension of the RuntimeException class, which means you do not have to place
all collection operations in a try-catch block.

Let us look at some of the methods defined in the Collection interface.

To add elements to a collection, invoke the methods;


public abstract boolean add(E obj);
public abstract boolean addAll(Collection <? Extends E> c);

The first method will add a single element to the collection, whereas the second
method will allow all objects in another collection to be added to this collection.
Notice that each of these methods will return a boolean value. If the collection has
changed, then a true is returned. If the collection has not changed, for instance, if
the collection does not allow for duplicate objects, and the collection already
contains the object, then a false is returned. It is important to remember that if the
collection does not allow for an object to be added if it already contains the object,
it is imperative that the add() method throws an exception and not return a
boolean value. There are three exceptions that may be thrown, these are;
• UnsupportedOperationException
• ClassCastException
• IllegalArgumentException

Removing objects may be achieved in four different ways;


public abstract void clear();
public abstract boolean remove(Object obj);
public abstract boolean removeAll(Collection<?> col);
public abstract boolean retainAll(Collection<?> col);

The first way of removing objects from a container, is to clear the contents from the
container. This is achieved by invoking the clear() method. Should you wish to
remove a specific object, then you would invoke the remove() method, passing the
object you want to remove as a parameter. In a very similar manner, you are able to
remove a set of objects by invoking the removeAll() method, and passing as a
parameter, the collection containing all the objects to be removed. Should you
require that all the objects in a collection be removed, except for those contained in
the collection supplied as a parameter, then invoke the retainAll() method. In
other words, this method will retain all the objects contained in the collection that is
passed as a parameter and all the other objects will be removed.

The Collection interface also supplies a number of methods to allow you to


check what the status of the collection is. These methods include;
public abstract int size();

PAGE 239
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

public abstract boolean isEmpty();


public abstract boolean contains(Object obj);
public abstract boolean containsAll(Collection<?> col);

The first method size(), returns an integer value informing you as to how many
objects are present in the container. If you want to know whether the collection is
empty invoke the isEmpty() method. Should the collection contain no objects,
then a boolean true is returned. To determine whether an object is present in a
collection invoke the contains() method, passing as a parameter the object you
are inquiring about. Finally, to determine whether a set of objects is present in a
collection a call should be made to the containsAll() method, passing as a
parameter a Collection instance containing all the objects you are inquiring
about.

In the Collection interface there are three other interesting methods. These are;
public abstract Object[] toArray();
public abstract <T> T[] toArray(T[] objArr);

The real purpose of the first two methods act as a bridge between array-based and
collection-based APIs. The first method will return an array of all the objects
contained within the container. For example;
Object[] myArray = [Link](); // where col is a Collection

The second method is slightly more useful in that you pass as a parameter the
object type you wish to return. If the array returned manages to hold all the objects,
and there is space left over in the array, then these ‘empty’ array elements are set to
null. An example using this method is;
String[] myStringArray = [Link](new String[0]);
// where col is a Collection containing strings

The third interesting method is;


public abstract Iterator iterator();

The purpose of this method is to return an Iterator over a collection. An


Iterator is very similar to an Enumeration. This Iterator interface is better
than an Enumeration in that it supplies methods that allow you to remove an
object from a collection. The methods in the Iterator interface are;
public interface Iterator {
public abstract boolean hasNext();
public abstract Object next();
public abstract void remove();
}

PAGE 240
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

The first method, hasNext() determines whether there are any more objects in the
Iterator instance. If there are, a boolean true is returned, otherwise a false is
returned. Incidentally, this method is identical in operation to the
[Link]() method. The second method, next() will
return the next object in Iterator. This method is identical in operation to the
[Link]() method. The third and final method, remove()
will remove the last object read from Iterator from the underlying collection. It
is this method that elevated the Iterator over an Enumeration. There is no safe
way of removing an object from a collection whilst traversing a collection with an
Enumeration. However, this is possible with the remove() method. One thing to
note is that the remove() method may only be called once per call to the next()
method. If you do not do this then an IllegalStateException is thrown.

Here is some interesting code from Sun;


static void filter(Collection col){
for(Iterator it = [Link](); [Link](); ){
if(!cond([Link]()))
[Link]();
}
}

Notice that this code is polymorphic. It will work for any Collection that
supports removal. This code uses an Iterator to traverse the collection, removing
any element that does not satisfy a certain condition. This is how you should
attempt to write your code.

This brings us to the end of the explanation on root interface of all collections, the
Collection interface. As it is an interface, it needs to be implemented. There are a
number of built in Java classes that implement this interface and we shall see them
later in this section where I shall also demonstrate examples using some of the
Collection methods.

AbstractCollection
This class is an abstract class which implements the Collection interface. It is
abstract as it provides implementations for all of the methods in the Collection
interface, except for the iterator() and size() methods. This class is included
so as to reduce the effort in implementing the Collection interface. Naturally, as
this class is an abstract class, it needs to be extended. If you use this class to
implement a modifiable collection, then you must override the add() method. If
you do not, an UnsupportedOperationException exception will be thrown.

PAGE 241
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

Set Interface
If you go back a few pages, to the hierarchy diagram on the Collections
Framework, you will see that the Set interface extends the Collection interface.
As discussed earlier, a Set by definition is not allowed to contain any duplicates in
the collection. The Set interface inherits all the methods from the Collection
interface and adds no other methods. This may seem a little strange, but the Set
interface places additional stipulations, beyond those inherited from the
Collection interface. For instance, it adds the restriction that no duplicate
elements are permitted in a collection. The classes that implement the Set interface
rely on the equals() method of the object added for equality. It therefore means
that Set objects may be compared meaningfully. Two Set objects are equal if they
contain the same elements. The explanation of the methods in the Set interface are
the same as those in the Collection interface. Please be aware of the added
restriction placed over the equals() and hashCode() methods in the Set
interface though.

AbstractSet
This abstract class implements the Set interface. It also extends the
AbstractCollection class. This class provides a basic framework for the Set
interface and thereby reduces the efforts you as a developer require to do in
implementing the Set interface. It is important to note that this class does not
override any of the implementations from the AbstractCollection class. All it
does is add implementations for the equals() method and hashCode() method.

Let us now look at some general purpose implementations of the Set interface.

HashSet<E>
This class implements the Set interface and extends the AbstractSet class. You
will find that this general-purpose class you will use most often when wanting to
store a duplicate free object collection. When you add elements to an array or a
linked list, you determine the order and position of each element. A HashSet does
not allow you this type of control. The HashSet organizes the elements that make it
convenient for itself. One of the advantages of a HashSet is that the process of
add(), remove(), contains() and size() is fast. This is due to the way hashing
works and how the hashCode() method ensures that objects added to the set are
evenly distributed. Let us look at this issue of a HashSet a little more.

For every element you wish to add to a HashSet, a hash code, which is an integer
value, is calculated. The computation of this hash code depends on the state of each

PAGE 242
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

object. In essence, a HashSet is an array of linked lists, where each one of the lists
is called a ‘bucket’. To locate an object in a HashSet, you first need to calculate
the object’s hash code. Then, you need to reduce this answer to modulo the total
number of buckets. The answer of this operation is the index of the bucket that
holds the element. You now insert the element into the ‘bucket’. Remember,
however that a set cannot contain duplicate elements. If there are elements already
inserted in the bucket, a ‘hash collision’ occurs. Before the element is inserted a
comparison needs to be made with all other elements in the currently indexed
bucket to ensure that there are no duplicates. This comparison does take time.
Fortunately, this process is all automatic. To reduce the chance of having to
perform numerous comparisons, ensure that the hash codes are fairly randomly
distributed, and that the number of buckets are fairly large.

As an example, assume an object has a hash code of 425, and that the number of
buckets is 101 (which is the default by the way). The ‘bucket’ index is therefore;
425 % 101 = 21

Below is a diagram depicting how to ‘view’ a HashSet.

ARRAY Linked Lists

To create an instance of a HashSet, call one of four constructor methods. These


are;
public HashSet();
public HashSet(int initialCapacity);
public HashSet(int initialCapacity, float loadFactor);
public HashSet(Collection <? extends E> col);

The first method creates a HashSet instance that is empty, has an initial capacity of
101, and has a load factor of 0.75. The capacity may be considered as buckets that

PAGE 243
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

may hold entries. Remember, this bucket count gives that number of buckets that
are used to collect objects with identical hash values. If there are too many
elements inserted into a HashSet the number of collisions increase, thereby
impacting on the time of retrieval. It is recommended that you stipulate the bucket
size to be in the region of 150% of the storage capacity, and that the number you
explicitly type in should be the closed prime number to this value. For instance, if
you are wanting to store 100 elements, the initial bucket size is 151. Where 151 is
the closed prime number of 150% of 100, which is 150. The second constructor
method creates an empty HashSet instance of an initial capacity and a load factor
of 0.75. This initial capacity is supplied as a parameter, initialCapacity. A rule
of thumb is when specifying the initial capacity, choose a value that is about two
times the size you will expect the HashSet to grow to. The third constructor
method creates an empty HashSet instance of a specified initial capacity and a
specified load factor, where both of these are supplied as a parameter. The final
constructor method will construct a HashSet instance containing all the objects in a
collection supplied as a parameter. Because iteration is linear, the choice of initial
capacity is important.

The load factor can be considered as a type of tuning parameter. It is the ratio of the
number of elements in the HashSet instance to the number of buckets in the set.
The range of this load factor is a float value between 0.0 and 1.0. The function of
this load factor is to identify the percentage hash set usage that causes the table to
be rehashed into a larger set. For example; if you use the default load factor of 75%
(i.e. 0.75f) with a capacity of 101 elements. When the HashSet instance is 75%
full, a new, larger HashSet will be created. All the elements present in the ‘old’
HashSet will have their hash values recalculated for the new larger set. Be aware
though, because iteration is linear the smaller the load factor (i.e. the closer to 0.0f)
the faster the lookup process. This is because there will be fewer keys per bucket,
but the table will then have more buckets than elements resulting in wastage of
valuable space. However, the larger the load value (i.e. the closer to 1.0f) the
slower the look-up process, but the space wastage is kept to a minimum as the
number of buckets is closer to the number of elements. A good load factor value is
between 0.70f and 0.75f.

If you looked at the hash code for two strings that are the same, you will discover
that their hash code is the same. This is because the String class derives the hash
value from the contents of the String instance. This however does not hold true, for
instance, for objects of the StringBuffer class that contain the same ‘string’. This
is because the hash code is calculated from the memory address of the
StringBuffer instance. In actual fact the StringBuffer class uses the method

PAGE 244
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

found in the Object class. This means that you have to redefine the equals()
method. This is because the equals method will attempt to see if the “code
generated from the address” is equal. Naturally it will not be, so equals() must be
re-written to check the contents for equality.

Below is a snippet of Java code that implements a HashSet. Notice how I


purposely attempt to insert duplicate strings into the set, and how they are rejected
in the final collection. Also notice that the output generated when I read the
contents back from the collection are not in the same order as those that I placed
into the set.
import [Link].*;

class HashSetTest {
public static void main(String[] args){
HashSetTest testHS = new HashSetTest();
[Link]();
}

public void run(){


Set<String> myHS = new HashSet<String>();
[Link]("One");
[Link]("cup");
[Link]("cup");
[Link]("of");
[Link]("Java");
[Link]("Java") // adding a duplicate
[Link](null);
[Link]("and");
[Link]("Drambuie");
[Link]("Drambuie"); // adding a duplicate
[Link]("please.");
displayHashSet(myHS);
}

private void displayHashSet(Set hs) {


[Link]("\nThe contents of the HashSet are listed below. It's size is:"
+ [Link]());
Iterator myIt = [Link]();
while ([Link]()){
Object ob = [Link]();
if(ob==null){
[Link]("I have found a NULL.");
}
else{
[Link]([Link]() + "\t\tWhose hashcode is: " + [Link]());
}
}
}
}

The output of this sample code looks as follows;


The contents of the HashSet are listed below. It's size is:8
I have found a NULL.
Java Whose hashcode is: 2301506
Drambuie Whose hashcode is: -771050231

PAGE 245
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

and Whose hashcode is: 96727


please. Whose hashcode is: -490575484
One Whose hashcode is: 79430
of Whose hashcode is: 3543
cup Whose hashcode is: 98878

TreeSet
When we looked at the HashSet class we said that one of its disadvantages is that
it is an unordered set. We even saw this in the HashSet example. The TreeSet
collection class is very similar to the HashSet class, except that it has the
distinction of being ordered. In order for the TreeSet class to operate correctly, the
elements added to the TreeSet must be sortable. In other words, the TreeSet
assumes that the elements that are being added have implemented the Comparable
interface or Comparator interface. It is not necessary to enter the elements into the
TreeSet class in order. The ordering is done for you automatically. When you
iterate through the TreeSet, the values are returned ordered. Because the TreeSet
class will order the elements you entered, the adding of elements to the collection is
slower than the process of entering elements into a HashSet. It is however far
superior than trying to find the correct location in a LinkedList of elements, and
inserting the element at that point. Apart from the ordering of the elements, the way
you use a TreeSet is identical as that with HashSet. You therefore need to decide
whether it is really necessary to have an ordered set. If it is, then there will be a
degradation in speed. If it is not, seriously consider using a HashSet.

As the major difference between a HashSet and a TreeSet is the ordering of


components, let us look at the issue of ordering. If you looked at the String class
you will notice that it implements the Comparable interface. This interface
contains one method, compareTo(). It imposes a total ordering on the objects of
each class that implements it. Again, looking at the String class you will notice that
it adds functionality to the compareTo() method. What it does is to compare two
strings lexicographically. The comparison is based on the Unicode value of each
character in the strings. The character sequence represented by this String object is
compared lexicographically to the character sequence represented by the argument
string. The result is a negative integer if this String object lexicographically
precedes the argument string. The result is a positive integer if this String object
lexicographically follows the argument string. The result is zero if the strings are
equal. compareTo() returns 0 exactly whereas the equals(Object) method
would return true. You therefore do not need to worry about implementing the
compareTo() interface when adding strings to a TreeSet, as it has already been
done for you. The interface looks as follows;
public interface Comparable<T>{
public int compareTo(T o);

PAGE 246
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

Should we wish to add our own objects to a TreeSet, then we will definitely have
to implement this interface. Please be aware of the fact that there is no default
implementation of the compareTo() method in the Object class. The
compareTo() method accepts one parameter, which is the object to be compared.

Let us assume that you are using an employee number, which is a positive integer
value and is unique. It is then not too difficult to perform a comparison. All we
really need to do is to subtract the two employee numbers, and get the difference
between the two. If the value returned is a negative number, then the first employee
object should be placed before the second employee object. If the answer is zero,
then it means that the two objects are identical. Finally, if the difference is a
positive number then the second object should come before the first. The code to do
this would look something like the following;
class Employees implements Comparable{
:
:
public int compareTo(T obj){
Employee secondEmployeeObj = obj;
return (employeeNumber - [Link]);
}
:
:
}

What would happen if;


• The object passed as an argument is not of the correct type?
• The employee numbers can be large and negative?

Firstly, a ClassCastException will take place if not using generics. Secondly if


the first employee number were a large positive value and the second employee
value a large negative value, the chances of getting an overflow is extremely high.
However if this were to happen, which it should not in employee numbers, as they
should not be too large and never be negative, then this code would suffice. It is
extremely limited though. What would happen if you suddenly wanted to order on
the employee age, or salary? Each class may only implement the interface once.
Fortunately, there is a solution. You use a different method for comparisons.

This method is the compare() method, and is found in the Comparator interface.
When creating a TreeSet you pass a Comparator object into the TreeSet
constructor. This interface looks as follows;
public interface Comparator<T>{
int compare(T o1, T o2);
boolean equals(Object obj);

PAGE 247
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

The compare() method compares its two arguments for order. It returns a
negative, zero, or a positive integer if the first argument is less than, equal to, or
greater than the second, respectively. For each type of comparison required create a
class that implements the interface. The object that you pass as a parameter when
creating a TreeSet, the TreeSet instance will use it whenever it needs to compare
two elements.

That brings us to the end of Sets. Let us now look at Lists.

List Interface
The List interface extends the Collections interface. A List is sometimes
referred to as a sequence, and just like Arrays, they are zero based. This means
that the first element referenced is at index zero. A List defines an ordered
Collection that will allow for duplicates. Because the elements are ordered, they
can be indexed. The position of an element in the List is important. You may
access elements in a List either through use of an Iterator or by random access
where you make use of the set() and get() methods. However, using these
methods have huge performance degradation issues. One of the disadvantages of
Arrays and Vectors lie in the removing of elements from the collection. Each
time an element is removed, all elements beyond the removed you must be moved
towards the start of the Array or Vector. In much the same manner, when an
element is added to an Array or Vector, all the elements following the position at
which the element is being inserted, must move back one position.

The real advantage of a List, is its ability to be able to perform position-oriented


operations. The methods used to perform this insertion are;
public abstract boolean add(E obj);
public abstract boolean addAll(Collection <? extends E> col);
public abstract void add(int index, E obj);
public abstract boolean addAll(int index, Collection <? extends E> col);

The removing of an element from a specific position may be achieved with the
following methods;
public abstract boolean remove(Object obj);
public abstract boolean removeAll(Collection<?> col);
public abstract boolean retainAll(Collection<?> col);
public abstract E remove(int index);

You may also change an element at a certain position.


public abstract E set(int index, E obj);

PAGE 248
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

To search for an element, the search may only begin at the beginning or end of the
List. To perform a search, invoke one of the following methods, where the
position of the required element is returned;
public abstract int indexOf(Object obj);
public abstract int lastIndexOf(Object obj);

If you know the position of an element in a List, then to return it use the method;
public abstract E get(int index);

Should it be necessary to work only with a subset of a collection, or if you want to


migrate through the entire List in an ordered manner, then make use of one of the
following methods;
public abstract ListIterator<E> listIterator();
public abstract ListIterator<E> listIterator(int index);
public abstract List<E> subList(int fromPos, int toPos);

LinkedList
A LinkedList implements the List interface. What happens in a LinkedList is
that each element is stored in a separate link, where each link makes reference to
the next link in the sequence. There are different forms of linked lists. There are
singularly linked lists and doubly linked lists. Each List must have a link or
reference to the first element in the List. This can be shown diagrammatically.
Below is an example of a double linked list.

Linked List

First

Link Link Link

Data Data Data

Next Next Next NULL

Previous NULL Previous Previous

Because LinkedLists are ordered, an interface called ListIterator which


extends the Iterator interface must be used when adding or deleting lists. Adding
a link in Java linked lists is far easier than in many other languages. Almost all the
tedious work is done for you. The only thing that you must remember is that when
you add a link into the LinkedList, the new link is added before the iterator
position. For instance, if you want to add a link, your code would look something
like the following snippet;

PAGE 249
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

LinkedList myLinkList = new LinkedList();


:
:
ListIterator myItr = [Link]();
[Link]();
[Link](Object); // where Object is an object instance that is to be
// added to the LinkedList

Graphically, the adding of this ‘link’ in the list is illustrated below.


Linked List

First

Link Link Link

Data Data Data

Next Next Next NULL

Previous NULL Previous Previous

Link

Data

Next

Previous

How do you remove a link from a LinkedList? All that is required is that the links
around the link that is being removed need to be updated. When removing a link,
the link to the left of the LinkedList iterator is then removed. But beware; if you
have just invoked the method previous(), and then the remove() method
immediately afterward, the element to the right of the LinkedList iterator is
removed. The garbage collector will then clean up the “orphaned” link as there is
no reference to it. This is illustrated below.

PAGE 250
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

Linked List

First

Link Link Link

Data Data Data

Next Next Next NULL

Previous NULL Previous Previous

What would happen if you had a number of LinkedList iterators pointing to the
same LinkedList container? Assume that one of those LinkedList iterators
removed a list. How would the other LinkedList iterators respond? Well,
LinkedList iterators have the ability to detect such changes on the collection. If a
linkedList iterator discovers that another LinkedList iterator has removed a list
from the collection, it will throw a ConcurrentModificationException. Good
programming practice would be to ensure that only one LinkedList iterator is
present for a particular LinkedList if adding and removing of Lists is to take
place. On the other hand, should you want to only read from the LinkedList then
you may assign as many references as you wish to the LinkList.

Below is some code showing how you can manipulate a LinkedList.


import [Link].*;

public class LinkedListTest{


LinkedList<String> myListOne;
LinkedList<String> myListTwo;
ListIterator<String> myListOneIterator;
ListIterator<String> myListTwoIterator;

public static void main(String[] args){


LinkedListTest linkList = new LinkedListTest();
[Link]();
}

// ****************************
void run(){
// create two instances of a LinkedList
myListOne = new LinkedList<String>();
myListTwo = new LinkedList<String>();

// Adding some links to the first LinkedList


[Link]("One");
[Link]("Cup");
[Link]("of Java");
[Link]("Please!");

PAGE 251
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

// Let us now display the contents of the first list


[Link]("\nDisplaying the contents of the first list.");
[Link](myListOne);

// Now let us add links to the second LinkedList


[Link]("Oooh, ");
[Link]("Some Drambui");
[Link]("would be nice to.");
[Link]("Thank you.");

// Let us now display the contents of the second list


[Link]("\nDisplaying the contents of the second list.");
[Link](myListTwo);

// now let us add the second list to the end of the first list
[Link](myListOne, myListTwo);
// now let us print the contents of the 'added to' list
[Link]("\nDisplaying the contents of the 'newly added to' list.")
[Link](myListTwo);

// finally let us delete the first link in our second list


deleteLink(myListTwo);
// now let us print the contents of the 'deleted from' list
[Link]("\nDisplaying the contents of the 'newly deleted from' list.");
[Link](myListTwo);
} // run()

// ****************************
// method used to display the contents of a LinkedList
void displayList(LinkedList<String> list){
myListOneIterator = [Link]();
while ([Link]()){
Object obj = [Link]();
[Link]([Link]());
}
} // end of the displayList()

// ****************************
// method to add one LinkList to another
void appendList(LinkedList<String> listOne, LinkedList<String> listTwo){
myListOneIterator = [Link]();
myListTwoIterator = [Link]();
while ([Link]()){
[Link]([Link]());
}
} // end of appendList()

// ****************************
// removing THE FIRST THREE links
void deleteLink(LinkedList<String> list){
int i = 0;
myListOneIterator = [Link]();
if([Link]() && i<3){
[Link]();
[Link]();
i++;
}
}

} // end of the class

The output generated by this code looks as follows;


Displaying the contents of the first list.

PAGE 252
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

One
Cup
of Java
Please!

Displaying the contents of the second list.


Oooh,
Some Drambui
would be nice to.
Thank you.

Displaying the contents of the 'newly added to' list.


One
Cup
of Java
Please!
Oooh,
Some Drambui
would be nice to.
Thank you.

Displaying the contents of the 'newly deleted from' list.


Cup
of Java
Please!
Oooh,
Some Drambui
would be nice to.
Thank you.

That concludes our section on LinkedLists.

ArrayLists
An ArrayList implements the List interface, and it is a resizable-array
implementation. In other words, it encapsulates a dynamically reallocated
Object[] array, and has a very similar behavior to the Vector class. You may
access the various elements in the ArrayList by means of an Iterator instance
or the get() and set() methods.

If an ArrayList is very similar to the Vector class, what are the advantages of
using the ArrayList class over the Vector class? The answer lies in the fact that
the Vector class’ methods are synchronized, whereas the ArrayList class
methods are not. So the decision of using one or the other class needs to be made
on whether two or more Thread instances will be accessing the Collection
instance at the same time. If your design is such that there will never be more than
one thread of execution accessing the elements of the collection at any one time,
then it would be advisable to implement the ArrayList class. The reason for this is
due to the fact that a lot of ‘time’ is spent on synchronization. As ArrayList
class methods are not synchronized, the speed of access is quicker than that of a

PAGE 253
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

Vector instance. Using an ArrayList is just as simple as using a Vector. Please


be aware though; when accessing the elements in a Vector instance you invoke
methods such as elementAt() and setElementAt(), whereas in an ArrayList
instance you invoke the get() and set() methods respectively.

Below is some simple code showing the adding of elements and the deleting of
elements from an ArrayList.
import [Link];
import [Link];

public class ArrayListTest{


ArrayList<String> myAL = new ArrayList<String>();
Iterator myItr;

// *********************
public static void main(String[] args){
ArrayListTest testIt = new ArrayListTest();
[Link]();
}

// *********************
private void run(){
[Link]("\nWelcome to the ArrayList Demo!\nThis is what" +
" the ArrayList Contains at startup.");

// add String objects to the vector


[Link]("Position One"); // this is actually position 0
[Link]("Position Two"); // this is actually position 1
[Link]("Position Three"); // this is actually position 2
[Link]("Position Four"); // this is actually position 3

// let us now print each out element using Vector methods.


for(int i=0; i<[Link](); i++){
[Link]("Element at " + [Link](i));
}

// let us add some more elements and change the previous ones
[Link](0,"Position Zero");
[Link](5, "Position Five");
[Link](1, "Position One Still");
[Link](4, "Position Four Still");

[Link]("\nI Have Added to the ArrayList. Let us View the Changed List.");
// now let us use an Iteration to view changed and added elements

myItr = [Link]();
while ([Link]()){
Object obj = [Link]();
[Link]("Element at " + [Link]());
}

[Link]("See how \"myAL\" has grown and changed.");


// now let us remove some elements from myALs
[Link]("\nElements Have Been Removed."+
" Let us View the Changed ArrayList where elements have been removed.");

[Link](2);
[Link](4);
for(int i=0; i<[Link](); i++){

PAGE 254
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

[Link]("Element at " + [Link](i));


}
[Link]("See how \"myAL\" has shrunk and changed.");
} // end of run()
} // end of ArrayListTest Class

The output of this program looks as follows:


Welcome to the ArrayList Demo!
This is what the ArrayList Contains at startup.
Element at Position One
Element at Position Two
Element at Position Three
Element at Position Four

I Have Added to the ArrayList. Let us View the Changed List.


Element at Position Zero
Element at Position One Still
Element at Position Two
Element at Position Three
Element at Position Four Still
Element at Position Five
See how "myAL" has grown and changed.

Elements Have Been Removed. Let us View the Changed ArrayList where elements
have been removed.
Element at Position Zero
Element at Position One Still
Element at Position Three
Element at Position Four Still
See how "myAL" has shrunk and changed.

This completes our section on Lists.

Maps
Maps are not descendents of the Collections interface. Instead, a Map interface
forms the root of all Map classes. The function of the Map interface is to describe a
mapping from keys-to-values, where none of the key values may be duplicated. In
other words there may only be one instance of a key-value pair. This is often
referred to as one-to-one mapping. You may be thinking that Maps are the same as
Sets. But this perception is incorrect, in that Maps contain both key and value pairs,
whereas a Set contains only the key.

If you want to look for an existing element in a Set instance, it is necessary to have
an exact copy of the element before you may determine whether that element is
contained within the Set or not. Often it is not feasible to have an exact copy of the
element. What is a far more realistic situation is where you have the key, and then
see if the element is contained within the collection. For instance, if you had an
item number, you may then perform a search on the Map instance to ‘find’ the
details about that item. As an example, you may have the resourceNumber for a

PAGE 255
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

video. By making use of this resourceNumber you can search a Map instance to
discover the resourceNumber/videoDetails pair. You may then extract all the
details from the stored element pertaining to the video that is associated with the
resourceNumber.

The Map Interface has three distinct sections to it. These are;
• An altering section
• A querying section
• An alternate view section

The altering section of the Map interface allows for to adding as well as deleting
key-value pairs from a Map. The methods that perform these tasks are;
public abstract Object put(K key, V value);
public abstract V remove(Object key);
public abstract void putAll(Map <? extends K, ? extends V> m);
public abstract void clear();

The put() method will add an element to the Map and associate the key and value.
If there had been a previous value mapped to the key, then this is replaced by the
new value. This previous value is returned by the put() method. Had there been
no previous key-value mapping, then a null is returned. The following exceptions
are thrown by the put() method;
• UnsupportedOperationException - if the put operation is not supported
by this Map.
• ClassCastException - if the class of the specified key or value prevents it
from being stored in this Map. This exception would be thrown if you do not
use generics.
• IllegalArgumentException - if some aspect of this key or value prevents
it from being stored in this Map.
• NullPointerException - this Map does not permit null keys or values,
and the specified key or value is null.

The remove() method will remove a value from a map that is associated with the
key passed. The method will return the previous value associated with the specified
key, or null if there was no mapping for key.

The putAll() method copies all of the key-value pairs from the specified Map to
this Map. These key-value pairs will replace any key-value pairs that this map had
for any of the keys currently in the specified map. The same exceptions that the
put() method could throw, the putAll() method may also throw.

PAGE 256
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

The clear() method will remove all key-value pairs from the Map.

The query operations are used to check the contents of the Map, and are as follows;
public abstract int size();
public abstract boolean isEmpty();
public abstract boolean containsKey(Object key);
public abstract boolean containsValue(Object value);
public abstract V get(Object key);

The size() method returns the number of key-value mappings contained in a Map
instance.

The isEmpty() returns a boolean value, indicating whether the Map instance
contains key-value pairs or not. If a Map instance does contain key-value pairs, then
a boolean false is returned, otherwise true is returned.

The containsKey() method will return a boolean value indicating whether a key
instance passed is contained as a key-value mapping in the Map instance. If it is, a
true is returned, otherwise a false is returned.

In the same light, the containsValue() method will return a boolean value
indicating whether a Map instance maps one or more keys to the specified value
passed.

The get() method returns the value to which a Map instance maps the specified
key.

The methods in the Map interface that allow you to work with key-value pairs as a
collection are;
public abstract Set<K> keySet();
public abstract Collection<V> values();
public abstract Set<[Link]<K,V>> entrySet();

The keySet() method will return a Set instance containing all the key instances in
the Map. The Set is backed by the Map, so changes to the Map are reflected in the
Set, and vice-versa. If the Map is modified while an iteration over the Set is in
progress, the results of the iteration are undefined. The Set supports element
removal, which removes the corresponding mapping from the Map, via the
[Link](), [Link](), removeAll(), retainAll() and clear()
operations. It does not support the add() or addAll() operations.

PAGE 257
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

The values() method will return a collection of values contained in a Map


instance. The collection is backed by the Map, so changes to the Map are reflected in
the collection, and vice-versa. If the Map is modified while an iteration over the
collection is in progress, the results of the iteration are undefined. The collection
supports element removal, which removes the corresponding mapping from the Map
via the [Link](), [Link](), removeAll(), retainAll() and
clear() operations. It does not support the add() or addAll() operations.

The entrySet() method returns a Set instance of the mappings (key-value pairs)
contained in this map. Each element in the returned set is a [Link]<K,V>. You
will have noticed that in the Map interface is an inner interface called the
[Link]<K,V> interface. This gives the details for each one of the key-value
entries.

The Java Collections Framework provides two general purpose Map


implementations, amongst many other types. These are the HashMap and TreeMap
classes. Both these classes have their uses. To decide upon which of the two classes
you should implement in an application depends upon your requirements. For
instance, if you want to insert, delete as well as locate elements in a Map, the best
implementation would be a HashMap. However, inserting elements in a HashMap
takes slightly longer than element insertion in a TreeMap. A TreeMap would be the
correct choice of a Map implementation if you want to traverse keys in a sorted
order.

To make sure that space is utilized as effectively as possible, it is possible to ‘tune’


your HashMap with an initial capacity and load factor. (See the sections HashSet
and HashTable for more details on this issue). HashMaps hash the key values, and
therefore require a well-defined hashCode() method implementation. A TreeMap
does not require any form of tuning, as it is always ‘balanced’. However, TreeMaps
require that the elements added to the Map must be sortable.

AbstractMap
This class is very similar to the AbstractCollection and AbstractSet class.
The purpose of this class is to ensure that the two methods, equals() and
hashCode() are overridden and that the two equal Maps return the same hash code.
Two Map instances are equal if they are;
• The same size
• Contain the same keys
• Contain the same elements that the key maps to

PAGE 258
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

By definition, the hash code for a map is the sum of the hash codes for the elements
of the Map, where each element is an implementation of the [Link]<K,V>
interface. The advantage of this is the fact that no matter what the order of the
elements in a Map instance, if the above criteria are met, then the two Map instances
will be equal.

HashMap
A HashMap stores its elements in a HashTable. It is important to remember that a
HashMap implementation is not synchronized. If multiple threads access a
HashMap instance concurrently, and at least one of the threads modifies the
HashMap instance structurally, it must be synchronized externally. (A structural
modification is any operation that adds or deletes one or more mappings (key-
value). Merely changing the value associated with a key that an instance already
contains is not a structural modification.) This is typically accomplished by
synchronizing on some object that naturally encapsulates the HashMap instance. If
no such object exists, the HashMap instance should be "wrapped" using the
[Link]() method. This is best done at creation time, to
prevent accidental unsynchronized access to the HashMap instance;
Map m = [Link](new HashMap(...))

Here is a simple example of how to use HashMaps. I am sure you will have no
problem understanding the code;

import [Link];
import [Link];

public class HashMapExample{


public static void main(String args[]){
HashMapExample hme = new HashMapExample();
[Link]();
}

private void run(){


// constructs a new empty HashMap with default initial capacity
HashMap<String, Integer> hashMap = new HashMap<String, Integer>();

/*
To specify initial capacity, use following constructor
HashMap<String, Integer> hashMap = new HashMap<String, Integer>(100);
To create HashMap from map use following constructor
HashMap<String, Integer> hashMap = new HashMap<String, Integer>(Map myMap);
IMPORTANT : you CAN NOT add primitives to the HashMap. You have to wrap it
Int one of the wrapper classes before adding.
To copy all key - value pairs from any Map to HashMap use putAll method.
*/
[Link]("One", new Integer(1)); // adding value into HashMap

PAGE 259
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

[Link]("Two", new Integer(2));


[Link]("Three", new Integer(3));

//get number of keys present in the HashMap


[Link]("HashMap contains " + [Link]() + " key value pairs.");

/*
To check whether HashMap is empty or not, use isEmpty() method.
isEmpty() returns true is HashMap is empty, otherwise false.
Finding particular value from the HashMap:
HashMap's containsValue method returns boolean depending upon
the presence of the value in given HashMap
Signature of the containsValue method is,
boolean containsValue(Object value)
*/
if([Link](new Integer(1))){
[Link]("HashMap contains 1 as value");
}else{
[Link]("HashMap does not contain 1 as value");
}

/*
Finding particular Key from the HashMap:
HashMap's containsKey method returns boolean depending upon the
Presence of the key in given HashMap Signature of the method is,
boolean containsKey(Object key)
*/

if( [Link]("One") ){
[Link]("HashMap contains One as key");
}else{
[Link]("HashMap does not contain One as value");
}

/*
Use get method of HashMap to get value mapped to particular key.
Signature of the get method is, Object get(Object key)
IMPORTANT: get method returns Object, so we need to cast it.
*/
Integer one = (Integer) [Link]("One");
[Link]("Value mapped with key \"One\" is " + one);

/*
To get all keys stored in HashMap use keySet method
Signature of the keysSet method is,Set keySet()
*/
[Link]("Retrieving all keys from the HashMap");
Iterator iterator = [Link]().iterator();
while([Link]()){
[Link]([Link]());
}

/*
To get all values stored in HashMap use entrySet() method.
Signature of the entrySet() method is, Set entrySet()
*/
[Link]("Retrieving all values from the HashMap");
iterator = [Link]().iterator();

PAGE 260
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

while([Link]()){
[Link]([Link]());
}

/*
To remove particular key - value pair from the HashMap use remove method.
Signature of remove method is,Object remove(Object key)
This method returns value that was mapped to the given key,
otherwise null if mapping not found.
*/
[Link]( [Link]("One") + " is removed from the HashMap.");
}
}

The output of when running this program will look along the following lines;
HashMap contains 3 key value pairs.
HashMap contains 1 as value
HashMap contains One as key
Value mapped with key "One" is 1
Retrieving all keys from the HashMap
One
Two
Three
Retrieving all values from the HashMap
One=1
Two=2
Three=3
1 is removed from the HashMap.

TreeMap
Most of the details of the methods contained in TreeMap are presented above. A
TreeMap stores its elements in a tree. The same discussion presented under the
section of HashMap class with respect to synchronization applies equally to the
TreeMap class.

Here is a simple example of how to use TreeMaps. I am sure you will have no
problem understanding the code;
import [Link].*;

public class TreeMapExample{


public static void main(String[] args) {
new TreeMapExample().run();
}

private void run(){


TreeMap <Integer, String>myTreeMap = new TreeMap<Integer, String>();
//Adding data to a tree map
[Link](1, "Sunday");
[Link](2, "Monday");
[Link](3, "Tuesday");
[Link](4, "Wednesday");
[Link](5, "Thursday");

PAGE 261
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

[Link](6, "Friday");
[Link](7, "Saturday");
//Retrieving all keys
[Link]("Keys in tree map: " + [Link]());
//Retrieving all values
[Link]("Values in tree map: " + [Link]());
//Retrieving the value from key with key number 5
[Link]("Key: 5 value: " + [Link](5)+ "\n");
//Retrieving the First key and its value
[Link]("First key: " + [Link]() + " Value: "
+ [Link]([Link]()) + "\n");
//Retrieving the Last key and value
[Link]("Last key: " + [Link]() + " Value: "
+ [Link]([Link]()) + "\n");
//Removing the first key and value
[Link]("Removing first key-value: "
+ [Link]([Link]()));
[Link]("Now the tree map Keys are: " + [Link]());
[Link]("Now the tree map contains: "
+ [Link]() + "\n");
//Removing the last key and value
[Link]("Removing last key-value: "
+ [Link]([Link]()));
[Link]("Now the tree map Keys are: " + [Link]());
[Link]("Now the tree map contains: " + [Link]());
}
}

The output when running this program will look along the following lines;
Keys in tree map: [1, 2, 3, 4, 5, 6, 7]
Values in tree map: [Sunday, Monday, Tuesday, Wednesday, Thursday, Friday,
Saturday]
Key: 5 value: Thursday

First key: 1 Value: Sunday

Last key: 7 Value: Saturday

Removing first key-value: Sunday


Now the tree map Keys are: [2, 3, 4, 5, 6, 7]
Now the tree map contains: [Monday, Tuesday, Wednesday, Thursday, Friday,
Saturday]

Removing last key-value: Saturday


Now the tree map Keys are: [2, 3, 4, 5, 6]
Now the tree map contains: [Monday, Tuesday, Wednesday, Thursday, Friday]

WeakHashMap
The WeakHashMap class is a very useful class. What it does is to implement the Map
interface for storing only weak references to keys. What happens if there is no more
reference to a key? This means that there is no possible way you may access the
value that is associated with the ‘lost’ key. What the WeakHashMap implementation
therefore allows is for all key-value pairs to be garbage collected when there is no
key reference outside of the WeakHashMap instance.

PAGE 262
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

Here is a simple example of using WeakHashMaps. What I have done is show you
what happens if you use a HashMap and then the same thing, but using a
WeakHashMap; It really is not too difficult to understand;

import [Link].*;

public class WeakHashMapExample {


public static void main(String[] args) {
new WeakHashMapExample().run();
}

private void run(){


Map<String, String> hashMap = new HashMap<String, String>();
String nameKey = new String("name");
[Link](nameKey, "Ndaba");
[Link]();
[Link]("Hashmap after creation :" + [Link]("name"));
nameKey = null;
[Link]();
[Link]("Hashmap after key is null :" + [Link]("name"));
Map<String, String> weakHashMap = new WeakHashMap<String, String>();
String weaknameKey = new String("name");
[Link](weaknameKey, "Stuart");
[Link]();
[Link]("WeakHashMap after creation :" + [Link]("name"));
weaknameKey = null;
[Link]();
[Link]("WeakHashMap after key is null :" + [Link]("name"));
}
}

The output when running this program will look along the following lines;
Hashmap after creation :Ndaba
Hashmap after key is null :Ndaba
WeakHashMap after creation :Stuart
WeakHashMap after key is null :null

From all the information I have presented in this section on collections, you should
now have a pretty good understanding of the historical collections and the Java
Collections Framework. In this framework we saw six implementations. However
there are a few other issues we can look at. These issues are to do with the various
algorithms provided. It is possible to perform searches, to sort and to shuffle the
elements in some of the collections. Let us look at sorting and shuffling.

Sorting and Shuffling


In order that sorting is achieved, the Comparable interface must be implemented so
that a natural sorting order may be implemented. For instance, the String and
Integer classes both implement the Comparable interface defining the natural

PAGE 263
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

sort order. Our example later on in this section will utilize this feature. If a class
does not implement the Comparable interface, then you as the developer must
implement it. There are times that the natural sort order that has been defined for
you is not what you want. In these instances you may override the class and
implement your own ordering. Lists, Maps and Sets may be sorted. The Java
Collections Framework also provides two interfaces that allow for ordering. These
are the SortedSet and SortedMap interface.

Let us look at a sort() method. The sort() method in the Collections class
sorts a collection that implements the List interface. So a code snippet would look
something like;
List<Employee> myEmployees = new LinkedList<Employee>();
[Link](myEmployees);

The code in the above sort() method assumes that the list elements implement the
Comparable interface. What it will do is to sort the specified list, myEmployees,
into ascending order, according to the natural ordering of its elements. If you want
to change this ‘natural ordering’ sort you must override this method. As an
example; below is a code snippet demonstrating how you would sort your list of
Employee instances in terms of the salaries each employee earns.

[Link](myEmployees, new Comparator<Employee>() {


public int compare(Employee a, Employee b){
double salaryDifference = [Link]() – [Link]();
if(salaryDifference < 0){
return -1;
}
if(salaryDifference > 0){
return 1;
}
return 0;
}
}
);

This code is not too taxing. Notice that we are making use of an anonymous class
and generics so there is no need for casting.

It is quite possible to implement a reverse or descending sort. To do this you should


implement the [Link]() method. This method will return a
comparator that returns [Link](a). Please be aware that the objects must
implement the Comparable interface.

If you look at the Arrays class in the JDK documentation you notice that it
implements a sort() method. It sorts the specified array of objects into ascending

PAGE 264
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

order, according to the natural ordering of its elements. All elements in the array
must implement the Comparable interface. Furthermore, all elements in the array
must be mutually comparable (that is, [Link](e2) must not throw a
ClassCastException for any elements e1 and e2 in the array). Let us look at a
complete example of how you may sort. What this code does is to sort all the
members of my family into ascending order.
import [Link].*;

public class SimpleSort{


double[] numbers;

public static void main(String[] args){


SimpleSort mySort=new SimpleSort();
[Link]();
}

// ************************************
void run(){
String[] family = {"Gillie", "Sarah", "Robert", "Jamima", "Janet",
"Alison", "Jenny", "Greg", "Timothy"};
displayUnsortedList(family);
[Link](family);
List<String> list = [Link](family);
displayList(list);
}

// ************************************
void displayUnsortedList(String[] list){
[Link]("The unsorted list looks like: ");
for(int i=0; i<[Link]; i++){
[Link](list[i]);
}
[Link]('\n');
}

// ************************************
void displayList(List<String> list){
[Link]("The list sorted looks like: ");
ListIterator<String> itr = [Link](0);
while ([Link]()){
String obj = [Link]();
if(obj == null){
[Link]("NULL");
}
else{
[Link]([Link]());
}
}
}
}

The output produced by this code is:

PAGE 265
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

The unsorted list looks like:


Gillie
Sarah
Robert
Jamima
Janet
Alison
Jenny
Greg
Timothy

The list sorted looks like:


Alison
Gillie
Greg
Jamima
Janet
Jenny
Robert
Sarah
Timothy

As mentioned earlier, the Collections class also has an algorithm that will allow
for the reverse of sorting, and that is to shuffle the collection. In order that you may
shuffle you must supply the List instance to be shuffled as well as a random
number generator. Here is an example;
import [Link].*;

public class ShuffleTest{


final int maxNumbers = 49;
public static void main(String[] args){
ShuffleTest shuffle = new ShuffleTest();
[Link]();
}

void run(){
List<Integer> lottoNumbers = new ArrayList<Integer>(maxNumbers);
// randomly generate a maximum of 'maxNumbers'
for(int i = 0; i <maxNumbers; i++){
[Link](new Integer(((int)([Link]()*100))));
}
// Now shuffle the numbers generated
[Link](lottoNumbers);
// Now assign the first six numbers to a list
List<Integer> winningCombination = [Link](0, 6);
// Now sort the list according to the natural sort order
[Link](winningCombination);
// Now print out the winning Lotto numbers
[Link](winningCombination);
}
}

For the R20 000 000.00 prize, the numbers are;


[10, 37, 68, 69, 91, 92]

PAGE 266
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

That concludes our section on look at java collections. You may not believe it, but
this is a brief introduction, and there is so much more that you can study. I would
encourage you to do so. Look at topics like Read-Only collections, Thread-safe
collections, Singleton collections and Big-O notation to name just a few. This
introduction to collections should give you a really solid foundation however.

PAGE 267
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

EVENT HANDLING
We have now got to the point in our course where we are going to start looking at
the Graphics User Interface (GUI). So far we have been using the command line.
In order for us to start programming in a GUI environment we need to understand
the concept of event driven programming. Once this is mastered we shall then start
looking at GUI programming and how we can make use of the graphical tools
available to us. In this section we shall see GUI programming in action but this
will be used to explain the concepts of event handling and hopefully provide a
slight titillation in anticipation for the section on GUI programming.

In a procedural program everything happened synchronously and was generally


predictable. However in environments such as Windows, events are unpredictable
and occur asynchronously. To be able to process various events that take place
such as the pressing of a button on the screen, accessing menus etc. a programming
model known as the event-driven programming model was developed. Java makes
use of an event model known as the delegation event model. This, by the way, was
introduced in the JDK1.1 and superceded the original inheritance event model
which had numerous deficiencies. One of the big advantages of the delegation
event model is that it is possible to separate your user interface programming from
your event handling methods. This is wonderful as it allows you to make changes
to the event handling methods without altering the user interface in any way. The
converse also applies. You may make changes to your user interface without any
changes needing to be made in your event handling methods. This makes
debugging very much easier.

The basic idea of GUI programming is;


1. Firstly, you need to declare controls. Controls are things like buttons, scrollbars,
text fields etc.
2. Once a control has been declared you then need to provide an event handler in
order to respond to any of the control’s activities. This event handler is usually
an anonymous class.
3. Once the event handler has been declared, the controls need to be added to a
container. A container is what you display on the screen and they are capable of
holding several controls in any desired pattern.

PAGE 268
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

In Java all events are object instances of predefined event classes. Now, every type
of event that occurs is represented by the combination of;
• an event class, and
• an event id.

When an event happens to a control, which is called a source, this source sends
notification of the event to event listeners. Event listeners are objects that are
registered to respond to a particular event. All the information about the event is
encapsulated in an event object. All event objects are derived ultimately from the
EventObject class found in the [Link] package.

From the above discussion we can see that event sources (such as buttons, slide
bars etc) originate or “fire” events. Sources define the events they “fire” by
registering listeners for those events. The event source sends out event objects to
all registered listeners when that event is fired. These listener objects then use the
information in the event object to determine how to react to the event generated.

In Java the abstract windows toolkit (AWT) provides eleven predefined listener
interfaces;
1. ActionListener
2. AdjustmentListener
3. ComponentListener
4. ContainerListener
5. FocusListener
6. ItemListener
7. KeyListener
8. MouseListener
9. MouseMotionListener
10. TextListener
11. WindowListener

These listener interfaces declare suitable methods for handling events. In Java for
every listener there is also an event type that a source can fire.

Let us write some very simple code to demonstrate the whole process.

PAGE 269
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

import [Link].*;
import [Link].*;

public class ButtonFrameTest{


public static void main(String[] args){
JFrame frame = new ButtonTest();
[Link](true);
}
}

// ********************************************
class ButtonPanel extends JPanel {
//declaring button variables of type JButton
private JButton yellowButton;
private JButton blueButton;
private JButton redButton;

public ButtonPanel() {
//Instantiating the JButton variables
yellowButton = new JButton("Yellow");
blueButton = new JButton("Blue");
redButton = new JButton("Red");

//Adding the buttons to the panel


add(yellowButton);
add(blueButton);
add(redButton);
}
}

// ********************************************
class ButtonTest extends JFrame{
public ButtonTest(){
//Declaring the frame
setTitle("VZAP Buttons");
setSize(300, 200);
setLocation (300,400);
Container contentPane = getContentPane();
//adding button panel to the container
[Link](new ButtonPanel());
}
}

In this above example we have created a number of buttons and added them to a
panel. Notice how we have created instances of each button to be of type JButton.
This component is defined in Java Swing package. We then add each one of the
buttons to a panel, which is a container, by using the add() method that is
inherited from the JPanel class. We also create a frame on which we place the
panel. Compile this program and run it. Its output looks as follows;

PAGE 270
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

However there will be no response when we press any of the buttons. Also when
we try and close the frame by pressing the X in the top left hand corner, the frame
goes away but the program still stays active. To terminate the program completely
we have to press the Ctrl C key combination.

To rectify this situation we need to add event handlers. Event handlers will respond
when a button (a sender) is pressed and when we want to close the frame. The first
thing we will create is a listener object that will respond each time a user presses
one of the keys. We will make the listener to be the panel on which the buttons are
populated. This will mean that each time a key is pressed, the panel will receive an
ActionEvent indicating that a button has been pressed. One of the issues we need
to address is that the panel needs to identify which one of the buttons has been
pressed.

To be able to respond to the button presses we will make use of one of the listener
interfaces namely the ActionListener interface. If you look at this interface in
the Java documentation you will see that it has only one method,
actionPerformed(). We said the panel will be the listener. This panel was
declared in the ButtonPanel class, which extends the JPanel class and will now
implement the ActionListener interface. The code is bolded below (note: only
part of the program is shown)

PAGE 271
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

import [Link].*;
import [Link].*;
import [Link].*;

class ButtonPanel extends JPanel implements ActionListener{


private JButton yellowButton;
private JButton blueButton;
private JButton redButton;

public ButtonPanel(){
:
}

public void actionPerformed(ActionEvent ae){


Object source = [Link]();
Color color = getBackground();

if(source == yellowButton)
color = [Link];
if(source == blueButton)
color = [Link];
if(source == redButton)
color = [Link];
setBackground(color);
repaint();
}
}

Our event handler will change the background color to that color displayed on the
button, when that button is pressed.

The ButtonPanel now has a method that will handle an ActionEvent. What
needs to happen now is that each button must know that when it fires an event it is
sent to the listener that is capable of handling the event. In other words each one of
the components (in this case the buttons) needs to register listeners for each event
type. The general syntax for doing this is;
[Link](theListener);

where;
• component is the actual component i.e. myButton, myApplet or as in our
example yellowButton.
• Event is the event fired i.e. MouseEvent, KeyEvent or as in our example
ActionEvent.
• theListener is the actual listener i.e. aMouseListener, aKeyListener or as in
our example the listener is the ButtonPanel class in which we are also
registering the listeners. As both are inside the same class we use the this
keyword.

PAGE 272
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

In our example, the code required to add the panel as the action listener to the
buttons is indicated in bold as follows; (note: only the relevant code is shown).
class ButtonPanel extends JPanel implements ActionListener{
private JButton yellowButton;
private JButton blueButton;
private JButton redButton;

public ButtonPanel(){
yellowButton = new JButton("Yellow");
blueButton = new JButton("Blue");
redButton = new JButton("Red");

add(yellowButton);
add(blueButton);
add(redButton);

//registering a listener for each component


[Link](this);
[Link](this);
[Link](this);
}

public void actionPerformed(ActionEvent ae){


:
}
}

By the way; it is quite a common practice in Java that the container of a component
or components is also the event listener. This is exactly what we have done above.
Once listeners are registered, the Java run time system automatically invokes the
correct method in the listener when responding to events.

So as a brief summary; Our ButtonPanel is a listener and we used the


addActionListener() method that told the component i.e. one of the JButtons
that when an event is fired it must redirect it to the listener. The listener then reacts
with the ActionEvent object.

We still have not yet quite finished our event handling. We still have to write an
event handler that will respond to the closing of the frame when the x is pressed. If
you look at our list of listener interfaces you will notice that there is one called the
WindowListener interface. If you now look at the documentation on this interface
you will notice that it contains seven methods that need to be implemented. We
therefore need to define a class that will implement this interface. We shall call this
new class myHandlerClass. It is defined as follows;

class MyHandlerClass implements WindowListener{


public void windowClosing(WindowEvent e){
[Link](0);

PAGE 273
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

}
public void windowClosed(WindowEvent e)
{}
public void windowOpened(WindowEvent e)
{}
public void windowIconified(WindowEvent e)
{}
public void windowDeiconified(WindowEvent e)
{}
public void windowActivated(WindowEvent e)
{}
public void windowDeactivated(WindowEvent e)
{}
}

There are a few very important things to remember here. Remember when we
discussed interfaces? You learned that the class that implements the interface must
declare all the methods. This we have done by providing empty statement blocks
for all the methods that we are not interested in. The only method that we supply
more functionality to is the windowClosing event. Now that we have defined this
class we may generate an instance of this class and make it a listener. This is done
as follows;
MyHandlerClass myWinHandler = new MyHandlerClass();

We then need to inform the frame of where to direct the event when we press the x
in order that the frame may close down completely.
MyHandlerClass myWinHandler = new MyHandlerClass();
addWindowListener(myWinHandler);

When we run the code and press any of the buttons, the background color will
change. If we close the window frame by pressing the x, the window shuts down
correctly and we do not need to perform the two-finger salute i.e. Ctrl C.

Following is the full listing of our code. Please notice two aspects of this code.
What I have done is to show you how you are allowed to make the container of a
component or components the event listener (this we did for the buttons), as well
as to create a separate class to be a listener. This we did for the windowClosing
event.
import [Link].*;
import [Link].*;
import [Link].*;

public class ButtonFrameTest{


public static void main(String[] args){
JFrame frame = new ButtonTest();
[Link](true);
}
}

PAGE 274
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

//**************************************************************
class ButtonPanel extends JPanel implements ActionListener{
private JButton yellowButton;
private JButton blueButton;
private JButton redButton;

public ButtonPanel (){


yellowButton = new JButton("Yellow");
blueButton = new JButton("Blue");
redButton = new JButton("Red");
add(yellowButton);
add(blueButton);
add(redButton);
[Link](this);
[Link](this);
[Link](this);
}

public void actionPerformed(ActionEvent ae){


Object source = [Link]();
Color color = getBackground();
if(source ==yellowButton)
color = [Link];
if(source ==blueButton)
color = [Link];
if(source == redButton)
color = [Link];
setBackground(color);
repaint();
}
}

//**************************************************************
class ButtonTest extends JFrame{
public ButtonTest(){
setTitle("VZAP Buttons");
setSize(300, 200);
setLocation (300,400);
MyHandlerClass myWinHandler = new MyHandlerClass();
addWindowListener(myWinHandler);

Container contentPane = getContentPane();


[Link](new ButtonPanel());
}
}

//**************************************************************
class MyHandlerClass implements WindowListener{
public void windowClosing(WindowEvent e){
[Link](0);
}
public void windowClosed(WindowEvent e) {}
public void windowOpened(WindowEvent e) {}
public void windowIconified(WindowEvent e) {}
public void windowDeiconified(WindowEvent e) {}
public void windowActivated(WindowEvent e) {}
public void windowDeactivated(WindowEvent e) {}
}

PAGE 275
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

This code of ours can be improved however. Java has assisted us a little here where
some fine fellow developed a concept called adapter classes. As in our example,
we only wanted to make use of the windowClosing() method in the
WindowListener interface, but we had to declare all the other methods with
empty bodies in our implementing class. Adapter classes come to our assistance
here. For every listener interface that has two or more methods, there is an adapter
class. What these adapter classes do is to define all the methods in the interface
with empty bodies. All we need to do is to inherit (i.e. extend) the adapter class
required and override the method or methods we are interested in. For example our
WindowListener class is implemented in the abstract WindowAdapter class
and looks as follows;
public abstract class WindowAdapter implements WindowListener{
public void windowClosing(WindowEvent e) {}
public void windowClosed(WindowEvent e) {}
public void windowOpened(WindowEvent e) {}
public void windowIconified(WindowEvent e) {}
public void windowDeiconified(WindowEvent e) {}
public void windowActivated(WindowEvent e) {}
public void windowDeactivated(WindowEvent e) {}
}

The adapter classes available to us are;


• ComponentAdapter
• MouseAdapter
• MouseMotionAdapter
• WindowAdapter
• ContainerAdapter
• FocusAdapter
• KeyAdapter

Go and study the documentation on these and use them. So our code can improve
and now looks as follows; (The changes are bolded.)
import [Link].*;
import [Link].*;
import [Link].*;

public class ButtonFrameTest{


public static void main(String[] args)
{
JFrame frame = new ButtonTest();
[Link](true);
}
}

//*****************************************************************
class ButtonPanel extends JPanel implements ActionListener{

PAGE 276
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

private JButton yellowButton;


private JButton blueButton;
private JButton redButton;

public ButtonPanel(){
yellowButton = new JButton("Yellow");
blueButton = new JButton("Blue");
redButton = new JButton("Red");

add(yellowButton);
add(blueButton);
add(redButton);

[Link](this);
[Link](this);
[Link](this);
}

public void actionPerformed(ActionEvent ae){


Object source = [Link]();
Color color = getBackground();

if(source ==yellowButton)
color = [Link];
if(source ==blueButton)
color = [Link];
if(source == redButton)
color = [Link];
setBackground(color);
repaint();
}
}

//*****************************************************************
class ButtonTest extends JFrame{
public ButtonTest(){
setTitle("VZAP Buttons");
setSize(300, 200);
setLocation (300,400);
MyHandlerClass myWinHandler = new MyHandlerClass();
addWindowListener(myWinHandler);
Container contentPane = getContentPane();
[Link](new ButtonPanel());
}
}

//*****************************************************************
class MyHandlerClass extends WindowAdapter{
public void windowClosing(WindowEvent e){
[Link](0);
}
}

This is much better. However, we can improve on this even more by making use of
the adapter class and generating an anonymous class. Just the section of code that I
have changed is shown below.

PAGE 277
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

class ButtonTest extends JFrame{


public ButtonTest(){
setTitle("VZAP Buttons");
setSize(300, 200);
setLocation (300,400);
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e){
[Link](0);
}
}
);
Container contentPane = getContentPane();
[Link](new ButtonPanel());
}
}

This is much more ‘slick’. Beware however when using anonymous classes. If the
code is going to extend over a number of lines, then it may become rather
cumbersome to understand. If the listener needs to undertake a fair amount of work
then it may be preferable to create a separate known class as we did earlier. One
other thing about adapter classes is to make sure your spelling is correct when
overriding the adapter’s methods. If the spelling is not correct the compiler will
assume the miss spelled method to be a new method and your code may never
respond to an event. So the rule of thumb is: If your event handler seems to do
nothing and you have used an adapter, then check to see that your method name
and signature exactly match the method you are wishing to override in the adapter
class.

PAGE 278
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

You should now be comfortable with event handling. So let us look at the event
hierarchy and discuss each one of the classes.

Event
Object

AWT
Event

Action Adjustment Component Item Text


Event Event Event Event Event

Container Focus Input Paint Window


Event Event Event Event Event

Key Mouse
Event Event

All events are instances of the event classes in this above hierarchy. There are no
public fields or variables for these events but each event class defines methods
necessary for accessing information describing the event. In other words, all the
event objects encapsulate information about an event which the event source then
communicates to the listeners.

The class at the top of the hierarchy is the EventObject class and this class
defines only two methods

• getSource()
• toString()

The getSource() method returns the Object that originated the event. You will
use this method a fair amount. The toString() method returns a string value
representing the event.

PAGE 279
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

Now the AWTEvent class is a subclass of the EventObject class and this class has
a method getID(). Its purpose is to return the event identified as an int value.
Now all event types are represented as predefined constants in the different event
class to which they belong. These subclasses of the AWTEvent are;
• ActionEvent
• AdjustmentEvent
• ComponentEvent
• ItemEvent
• TextEvent

In the AWT there is a distinction between what is called semantic and low-level
events. A semantic event is one that expresses what the user is doing i.e. they
correspond to user input. For example ‘the clicking of a mouse button’ etc. The
semantic events are thus;
• ActionEvent,
• AdjustmentEvent,
• ItemEvent and
• TextEvent.

Low-level events are those that make semantic events possible. For example; In the
case of the mouse click, this is a mouse down, a mouse up, mouse movement etc.
The low-level events include ComponentEvent and its subclasses. These are;
• ComponentEvent
• ContainerEvent
• FocusEvent
• InputEvent
• PaintEvent
• WindowEvent

And descending from InputEvent are;


• KeyEvent
• MouseEvent

Let us have a very brief look at each one of these events, starting with semantic
events.

PAGE 280
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

ActionEvent
This we have used through the discussion. It includes clicking a button or pressing
a function key.

AdjustmentEvent
These events occur in components, like scroll bars, that have a numeric value that
needs to incremented or decremented by the user. As a scrollbar is moved, its new
position is notified to an adjustment listener as an adjustment event. There are
methods on the AdjustmentEvent class for finding the type of adjustment event
that occurred and the extent of that adjustment.

ItemEvent
These occur in components that have implemented the ItemSelectable interface,
which includes Lists, Checkboxes and pop-up choice menus. Events are generated
when items within the component are selected or deselected by the user. There are
methods in the ItemEvent class for discovering which items are selected or
deselected.

TextEvent
These types of events occur when text is entered, edited or deleted from inside text
entry fields.

Now let us look at the low-level events.

ComponentEvent
This event indicates that a component has moved, changed size, rendered invisible,
or made visible again. The event is passed to every ComponentListener or
ComponentAdapter object, which registered to receive such events using the
component's addComponentListener method. (ComponentAdapter objects
implement the ComponentListener interface.) Each such listener object gets this
ComponentEvent when the event occurs.

ContainerEvent
A container object (such as our panel) generates this event when a component is
added to it or removed from it. The event is passed to every ContainerListener
or ContainerAdapter object, which registered to receive such events using the
component's addContainerListener method. (ContainerAdapter objects
implement the ContainerListener interface.) Each such listener object gets this
ContainerEvent when the event occurs. When a registered container listener

PAGE 281
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

receives notification that a component has been added, it can get the identity of this
new component by invoking a getChild() method call.

FocusEvent
A component has focus when it can receive keystrokes. For example in a text field,
if the cursor is visible then the text field has the focus and text may be
manipulated. When a button has focus you are able to click it by pressing the
spacebar. When the user selects another component, then previous component
loses focus. It is also possible for a component to gain focus by pressing the TAB
key. Each time the key is pressed the next component gain focus. Later in the
course we will be looking at Swing and some of its components. These
components are placed from left to right and top to bottom. This is how the TAB
key will also traverse. There are two levels of focus change events: permanent and
temporary. Permanent focus change events occur when focus is directly moved
from one component to another, such as through calls to requestFocus() or as
the user uses the TAB key to traverse components. Temporary focus change events
occur when focus is temporarily gained or lost for a component as the indirect
result of another operation, such as window deactivation or a scrollbar drag. In this
case, the original focus state will automatically be restored once that operation is
finished, or, in the case of window deactivation, when the window is reactivated.
Both permanent and temporary focus events are delivered using the
FOCUS_GAINED and FOCUS_LOST event ids. The levels may be distinguished in the
event using the isTemporary() method.

InputEvent
Input events are delivered to listeners before they are processed normally by the
source where they originated. This allows listeners and component subclasses to
"consume" the event so that the source will not process them in their default
manner. We will discuss consuming events shortly.

PaintEvent
These are special system events that aid the serialization of repaint/update events
for components.

WindowEvent
A window is active if it can receive keystrokes from the operating system. The
active window usually has a highlighted title bar. Only one window may be active
at any one time. There are a number of window event types and we saw these listed
earlier.

PAGE 282
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

KeyEvent
When a key is pressed a KEY_PRESSED KeyEvent is generated. When a key is
released a KEY_RELEASE KeyEvent is generated. The event is passed to every
KeyListener or KeyAdapter object that is registered to receive such events using
the component's addKeyListener method. (KeyAdapter objects implement the
KeyListener interface.) Each such listener object gets this KeyEvent when the
event occurs.

"Key typed" events are higher-level and generally do not depend on the platform or
keyboard layout. They are generated when a character is entered, and are the
preferred way to find out about character input. In the simplest case, a key typed
event is produced by a single key press (e.g., 'a'). Often, however, characters are
produced by series of key presses (e.g., 'shift' + 'a'), and the mapping from key
pressed events to key typed events may be many-to-one or many-to-many. Key
releases are not usually necessary to generate a key typed event, but there are some
cases where the key typed event is not generated until a key is released (e.g.,
entering ASCII sequences via the Alt-Numpad method in Windows).

No key typed events are generated for keys that don't generate characters (e.g.,
action keys, modifier keys, etc.). The getKeyChar() method always returns a
valid Unicode character or CHAR_UNDEFINED. For KEY_PRESSES and
KEY_RELEASE events, the getKeyCode() method returns the event's keyCode. For
key typed events, the getKeyCode() method always returns VK_UNDEFINED.

Virtual key codes are used to report which keyboard key has been pressed, rather
than a character generated by the combination of one or more keystrokes (like 'Z’,
which comes from ‘shift’ and ‘z’).

Let us look at this a little more closely. Let us suppose that a user types ‘Z’ by
pressing the ‘SHIFT’ key and the ‘z’ key. In Java this process will generate five
events;
1. KEY_PRESSED called for VK_SHIFT (when the ‘SHIFT’ key was pressed).
2. KEY_PRESSED called for VK_Z (when the z key was pressed).
3. KEY_TYPED called for a ‘Z’ (when the z key was actually typed).
4. KEY_RELEASED called for VK_Z (when ‘z’ was released).
5. KEY_RELEASED called for VK_SHIFT (when ‘SHIFT’ key was released).

If we did not press the ‘SHIFT’ key then the number of events generated would
have been three.

PAGE 283
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

To work with the KEY_PRESSED and KEY_RELEASED methods you first need to
check the keyCode, and if required, respond to a certain key press or key press
combination. This can be done as follows;
public void keyPressed(KeyEvent kevt){
int keyCode = [Link]();
if (keyCode == KeyEvent.VK_Z && [Link]()){
// do something
}
:
}

The key code will equal a constant that represents a key. These are defined in the
KeyEvent class. Go and peruse them in the Java documentation. There are several.
We could have used the getKeyChar() method to obtain an actual character
typed.

Please note: Not all keystrokes result in a call to keyTyped(). Only those
keystrokes that generate a Unicode character can be captured in the keyTyped()
method. You need to use the keyPressed() method to check for cursor keys and
other command keys.

MouseEvent
We responded to mouse events by using the actionPerformed event earlier. But
if you are wanting to draw with the mouse, or trap a mouse move then you need to
use the MouseEvent. The MouseEvent represents each of the following events;

MouseEvents
• a mouse button is pressed (MOUSE_PRESSED)
• a mouse button is released (MOUSE_RELEASED)
• a mouse button is clicked (pressed and released) (MOUSE_CLICKED)
• the mouse cursor enters a component (MOUSE_ENTERED)
• the mouse cursor exits a component (MOUSE_EXITED)

MouseMotionEvent
• the mouse is moved (MOUSE_MOVED)
• the mouse is dragged (MOUSE_DRAGGED)

PAGE 284
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

When a user uses a mouse and presses the mouse button, three events take place
and their listeners are called;
1. MOUSE_PRESSED.
2. MOUSE_RELEASED.
3. MOUSE_CLICKED.

It is possible to get the x and y coordinates of the mouse using the getX() and
getY() methods.

To distinguish between single, double or more clicks use the getClickCount()


method.

You can change the shape of the cursor by designing your own or using shapes
supplied by Java. This can be done using the setCursor() method.

It is also possible to distinguish between the mouse buttons being pressed by


testing the return value of getModifiers against the values BUTTON1_MASK,
BUTTON2_MASK and BUTTON3_MASK. So for example, if we want to test and see
whether the right mouse button has been pressed we can do something like the
following piece of code; (notice the bitwise AND (&) operator)
:
if([Link]() & InputEvent.BUTTON3_MASK() != 0)
// code for right click
:

To give you an idea of mouse events, the following program contains some simple
code I wrote that causes the background to change color as you move your mouse
over each of the buttons.
import [Link].*;
import [Link].*;
import [Link].*;

public class MouseButton{


public static void main(String[] args){
JFrame myFrame = new ButtonFrame();
[Link](true);
}
}

//******************************************************************
class ButtonPanel extends JPanel implements MouseListener{
private JButton button1;
private JButton button2;
public ButtonPanel(){
button1 = new JButton("Go To Red");
button2 = new JButton("Go To Green");

PAGE 285
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

add(button1);
add(button2);
[Link](this);
[Link](this);
}

public void mouseEntered(MouseEvent me){


Color colourMe = getBackground();
Object whoRU = [Link]();
if (whoRU == button1){
colourMe = [Link];
}
else if (whoRU == button2){
colourMe = [Link];
}
setBackground(colourMe);
repaint();
}

public void mouseExited(MouseEvent me){


setBackground([Link]);
repaint();
}
public void mousePressed(MouseEvent me) {}
public void mouseReleased(MouseEvent me) {}
public void mouseClicked(MouseEvent me) {}
}

//******************************************************************
class ButtonFrame extends JFrame{
public ButtonFrame(){
setTitle("Mouse Over Buttons");
setSize(200,150);
addWindowListener(new WindowAdapter(){
public void windowClosing(WindowEvent we){
[Link](0);
}
});
Container myPane = getContentPane();
[Link](new ButtonPanel());
}
}

PAGE 286
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

In closing this section on event handling let us discuss very briefly two other
aspects of event handling;
1. Multicasting.
2. Consuming.

PAGE 287
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

MULTICASTING
Multicasting allows event sources to be registered with more than one event
listener. To illustrate this we will write a program that will allow a user to open
multiple windows by pressing a “New Window” button. The user will then be able
to close all the windows by pressing the “Close All Windows” button. This will
clear all the windows. The user will again be allowed to open a number of windows
and close them if desired. To exit the program and close any opened windows the x
or “exit” button may be pressed. The screen capture below shows three windows
open apart from the main window.

Now the code to do all this looks as follows;


import [Link].*;
import [Link].*;
import [Link].*;

public class MultiCastTest{


public static void main(String[] args){
JFrame frame = new MultiCastTstFrame();
[Link](true);
}
}

//*****************************************************************
class MultiCastPanel extends JPanel implements ActionListener{
private JButton newButton;
private JButton closeButton;
private JButton exitButton;
private int counter = 0;

public MultiCastPanel(){
newButton = new JButton("New Window");
closeButton = new JButton("Close All Windows");
exitButton = new JButton("Exit");
add(newButton);
add(closeButton);

PAGE 288
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

add(exitButton);
[Link](this);
// GoodBye exitProg = new GoodBye();
// [Link](exitProg);
// a quicker way of doing the above two lines is..
[Link](new GoodBye());
}

public void actionPerformed(ActionEvent ae){


MyFrame simpleF = new MyFrame();
counter++;
[Link]("VZAP Window #" + counter);
[Link](200, 150);
[Link](60*counter, 60*counter);
[Link]();
[Link](simpleF);
}
}

//******************************************************************
class MultiCastTstFrame extends JFrame{
public MultiCastTstFrame(){
setTitle("VZAP Windows");
setSize(300, 200);
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e){
[Link](0);
}
} );
Container contentPane = getContentPane();
[Link](new MultiCastPanel());
}
}

//******************************************************************
class MyFrame extends JFrame implements ActionListener{
public void actionPerformed(ActionEvent e){
dispose(); //close ALL windows
}
}

//******************************************************************
class GoodBye implements ActionListener{
public void actionPerformed(ActionEvent ae){
[Link](0);
}
}

Cool Huh!!!

PAGE 289
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

CONSUMING
There may be times when you wish to consume an event. In other words, you want
to prevent it being processed in the default manner by the originating component.
What is important to note about consuming events is that input events for extended
components may be consumed. You invoke the consume() method resident in
InputEvent to prevent an event being processed in the default manner. A common
area where consumption takes place is where we want a text-input field to accept
only numbers. What we do is have a text input field and then simply listen to all
key events that occur and then consume all events that do not correspond to digit
keys. For example (we are creating an anonymous class);
[Link](new KeyAdapter(){
public void keyTyped(KeyEvent kEvnt){
char ch = [Link]();
if(ch < '0' || ch >'9') // a non-numeric key was pressed
[Link](); // so consume it
}
} ); // closing argument brackets

To see if an event was consumed we can use the isConsumed() method which
returns a boolean value of true if the event was consumed.

Remember that the basic framework used by all event handlers is;
• Write a class that implements the somethingListener class.
• Declare an object – i.e. MyHandler of your class.
• On your component call the addSomethingListener(MyHandler) method.

The next page offers a summary of the AWT event handling. Use it as a reference
guide.(taken from the book “Core Java”).

PAGE 290
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

Interface Methods Parameter/Accessors Events generated by:


ActionListener actionPerformed ActionEvent Button
getActionCommand List
getModifiers MenuItem
TextField
AdjustmentListener adjustmentValueChanged AdjustmentEvent Scrollbar
getAdjustable
getAdjustmentType
getValue
ItemListener itemStateChanged ItemEvent Checkbox
getItem CheckboxMenuItem
getItemSelectable Choice
getStateChange List
TextListener textValueChanged TextEvent TextComponent
ComponentListener componentMoved ComponentEvent Component
componentHidden getComponent
componentResized
componentShown
ContainerListener componentAdded ContainerEvent Container
componentRemoved getChild
getContainer
FocusListener focusGained FocusEvent Component
focusLost isTemporary
KeyListener keyPressed keyEvent Component
keyTyped getKeyChar
keyReleased getKeyCode
getKeyModifiersText
getKeyText
isActionKey
MouseListener mousePressed MouseEvent Component
mouseReleased getClickCount
mouseEntered getX
mouseExited getY
mouseClicked getPoint
translatePoint
isPopupTrigger
MouseMotionListener mouseDragged MouseEvent Component
mouseMoved
WindowListener windowClosing WindowEvent Window
windowOpened getWindow
windowIconified
windowDeiconified
windowClosed
windowActivated
windowDeactivated

PAGE 291
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

APPLETS
This section has been included for information sake in case you ever come across
this once popular Java technology. In reality, applets are not being used much
anymore, as nearly all the current Internet browsers no longer support Java due to
security concerns.

In the next section we shall be looking at Java Swing and will expand on what
applets can do graphically and with multimedia. Typically Java applets are always
graphical. Java is not just limited to the writing of stand-alone programs as we have
been doing so far on the course. It is capable of writing small programs that may be
run via the Internet and on Web browsers. This in fact is where Java first gained its
popularity. Web pages are brought to life by embedding applets written in Java.
There is one thing to note about applets though: browser support for applets are
limited. Develop your applets strictly with AWT components. This will give you a
better chance of your applets running.

Let us first look at the inheritance tree of the Java applet. It looks as follows;

Object

Component

Container

Window Panel

Frame Applet

JFrame JApplet

Just a note. If your applet does not use any of the Swing components, then you may
create an applet by extending the Applet class. However if you are going to make

PAGE 292
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

full use of the Swing components, then the applet you are creating must be a
subclass of the JApplet class. The reason for this is because the painting of the
Swing components will not be correct if you simply extend the Applet class.

Every applet you create inherits a set of default methods ( init(), start(),
stop() and destroy() )from the Applet/JApplet class. You override these
methods or behaviors in order for your applet to perform some useful activity.
These methods are shown below under the applet life cycle.

The applet life cycle.


The applet life cycle takes on the following framework;
public class MyApplet extends Applet{
public void init(){
:
}

public void start(){


:
}

public void paint(Graphics g){


:
}

public void stop(){


:
}

public void destroy(){


:
}
}

For the simplest of Java applets none of the above five methods need to be
overridden (Just like your first applet). However for any meaningful applet to be
written then at least some of the above inherited methods need to be overwritten.
Notice one thing about Java applets. They do not have a main() method like a
stand-alone program does. Its basic framework is always based on the above.

init() method
This is the very first method that is called. It is only ever called once and is used to
initialize any instance variables and set up any system resources such as buttons,
fonts, threads etc. An applet does not use a conventional constructor method to
perform initialization. The init() method suffices. However if you really wanted
to create a constructor, it is permissible. Only code that is run once and once only
should be placed in the init() method.

PAGE 293
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

start() method
Once the init() method has been called (which always happens even if you have
not overridden it) the next method that is called is the start() method. Now
unlike the init() method the start() method may be invoked as many times as
required. The start() method starts threads running etc. You may ask “Why
would you want to call the start() method more than once?” An example is when
you load a web page containing an animated applet into your browser. This applet
is started and the animation begins to run. If you then go to another web page the
applet is stopped. This is so that valuable system resources are not wasted on the
running applet. However when you return to the page containing the applet, the
start() method is once again invoked reactivating any threads that were halted.
The applet starts and the animation continues.

stop() method
The stop() method is called when you move away from a web page on which an
active applet is embedded, halting the applet. Like the start() method it can be
called numerous times. Each time a page is left and the applet is no longer the
focus of the display, the stop() method is called. It performs actions such as
halting threads etc. When this method is called and an applet has stopped, the
applet is unable to receive any events until such time as it is started again by
invoking the start() method. Just before an applet is destroyed for good, the
stop() method is called. This method should never need to be called directly
unless your applet is performing animation, calculation using threads, or some
other multimedia activity.

destroy() method
The destroy() method is called when you exit the browser. Code that resides in
this method should perform clean–up activities such as dereferencing any system
resources such as any fonts used etc. Like the init() method the destroy()
method is only ever called once. You can visualize the destroy() method as being
similar to the finalize() method for an object. Just as in a finalize() method,
you cannot determine exactly when a destroy() method will be called. So use the
destroy() method cautiously.

paint(Graphics g) method
The paint() method is inherited from the Component class. This method you will
not call. You will however override it. The function of this method is to be called
by the window system when a component needs to be redisplayed and is called
between the start() and stop() methods. Whenever the applet’s display changes
in some way the paint() method is invoked. Thus, results that involve drawing

PAGE 294
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

should be displayed from the applet’s paint() method. Generally, aspects such as
DialogBoxes should not be displayed in the paint() method.

As a summary, an applet can;


• initialize itself
• start running
• stop running
• perform some kind of clean up.

Security is an advanced feature, but there are a number of restrictions imposed on


applets. Every browser implements security policies to keep applets from
compromising system security. However, the implementation of the security
policies differs from browser to browser. Also, security policies are subject to
change. For example, if a browser is developed for use only in trusted
environments, then its security policies will likely be much more lax than those
described here.

Current browsers impose the following restrictions on any applet that is loaded
over the network:
• An applet cannot load libraries or define native methods.
• It cannot ordinarily read or write files on the host that is executing it.
• It cannot make network connections except to the host that it came from.
• It cannot start any program on the host that is executing it.
• It cannot read certain system properties.
• Windows that an applet brings up look different from windows that an
application brings up.
Each browser has a SecurityManager object that implements its security policies.
When a SecurityManager detects a violation, it throws a SecurityException.
Your applet can catch this SecurityException and react appropriately.

Now that we have a better idea of how applets are constructed, let us see how to
run and test an applet. To do this we have to add the applet to an HTML page by
using the <APPLET> tag. This is a special HTML tag developed specifically for
Java. Once this is done you then need to specify the URL of the HTML page to
your web browser. The full structure of the APPLET HTML tag is as follows;

<APPLET
CODE = classFileName
WIDTH = width_in_pixels_integerValue
HEIGHT = height_in_pixels_integerValue
[ARCHIVE = archiveFileName1 [,archiveFileNameN] ]

PAGE 295
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

[CODEBASE = applet_URL]
[VSPACE = vertical_blankMargin_in_pixels]
[HSPACE = horizontal_blankMargin_in_pixels]
[ALIGN = alignment]
[NAME = appletName]
[ALT = “ Text ”]
>
</APPLET>

Those items that have [ and ] brackets around them are optional. All the rest are
necessary. To open an APPLET tag in an HTML page the format is <APPLET and
then the relevant information, finally closing with a >. To end the <APPLET .. >
the format is </APPLET>.

One very important thing to note is that HTML tags and attribute names are not
case sensitive, but some of the arguments they take, such as the name of the class
file are.

PAGE 296
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

The meanings of the attributes are;


CODE = classFileName This attribute is required and specifies the
class file that is to be executed. This must just
contain the filename, not the path

WIDTH = width_in_pixels_integerValue This attribute is required. It specifies the


width the applet will take up in the browser.

HEIGHT = height_in_pixels_integerValue This attribute is required. It specifies the


height the applet will take up in the browser.

ARCHIVE = archiveFileName1 [,archiveFileNameN] This attribute is optional. It allows an applet to


bundle all its class files and media into one
JAR or ZIP file.

CODEBASE = applet_URL This attribute is optional. It allows you to


specify the location of applet class files. These
can be any valid location on the Internet, on a
server or on a client machine. If this attribute is
missing then all class files must be in the same
directory as the HTML file.

VSPACE = vertical_blankMargin_in_pixels This attribute is optional. It is used to specify


the vertical blank margin to leave around the
applet in the browser.

HSPACE = horizontal_blankMargin_in_pixels This attribute is optional. It is used to specify


the horizontal blank margin to leave around the
applet in the browser.

ALIGN = alignment This attribute is optional. It is used to control


where the applet appears on the browser’s
page. These can be LEFT, RIGHT, TOP,
BOTTOM, TEXTTOP, MIDDLE,
ABSMIDDLE, BASELINE, ABSBOTTOM.

NAME = appletName This attribute is optional. This is the name you


gives the applet. If there is more than one
applet on the page this provides a way for them
to refer to each other should they be wishing to
communicate with each other.

ALT = “ You need a Java aware browser to see this This attribute is optional. It is used to specify
page“ the text in the event that a browser does not
understand Java.

By the way, width and height attributes (listed in the table above) should be LESS
than 640 pixels wide and 480 pixels tall. This is due to the fact that most computers
support these dimensions as the minimum width and height.

PAGE 297
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

We shall see a number of these attributes being used as we start to look at Swing in
the next section. The MINIMUM applet HTML tag was shown at the beginning of
this book. Go and peruse it if you have forgotten. There is another tag that is very
useful. This is the PARAM tag. PARAM allows you to pass parameters from your page
to the applet. The advantage of this is that we can have one applet and pass it
different information, and thereby respond differently. For example if we have an
applet that is capable of displaying different values on a graph, all that we need to
do is to supply the applet with these values and it will display them. The PARAM
syntax is as follows;
<PARAM NAME = "parameterName" VALUE = "argumentValue" >

where;
“parameterName” is the variable name of the String class in the applet
“argumentValue” is the actual value passed as a String.

For example;
<APPLET code = "[Link]" width = 300 height = 200>
:
:
<PARAM NAME = "salary" VALUE = "1234.56">
:
:
</APPLET>

The Java code to retrieve it from within the applet is;


:
//Note that the name "salary" is case sensitive here
String str = getParameter("salary");
double earning = [Link](str);
:

Notice that the PARAM tag must appear between the <APPLET> and </APPLET> tags.

For fun, below is an applet that displays a picture of a Nyla (I took). The code
follows;

PAGE 298
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

import [Link].*;
import [Link].*;
import [Link].*;
import [Link];

public class MyView extends JApplet{


String myFileName = "[Link]";
URL myURL;
Image myImage;
ImageProducer myImageProducer;

public void init(){


Toolkit tool = [Link]();
myURL = getClass().getResource(myFileName);
try{
myImageProducer = (ImageProducer) [Link]();
}
catch (Exception e){
[Link]([Link]());
}
myImage = [Link](myImageProducer);
}

public void paint(Graphics g){


[Link](myImage, 10, 10, this);
}
}

The HTML code will look as follows;


<applet code = "[Link]" width = 370 height = 280 >
</applet>

When the HTML 4.01 standard was released it deprecated the <applet> tag and
introduced a new tag <object>. For the purpose of embedding applets, the
<object> tag is used very similarly to the <applet> tag. The major difference is

PAGE 299
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

that the attribute class in the <applet> tag becomes the classid attribute in the
<object> tag. For instance;
<object classid = "[Link]" width = 370 height = 280 >
</object>

The <object> tag is mainly used to embed ActiveX controls and other forms of
active content. Naturally there are many more attributes associated to the <object>
tag than what is shown above. There are still many browsers that are incapable of
interpreting HTML 4.01. So for those browsers there is a way of embedding the
<applet> tag in an <object> tag;
<object classid = "[Link]" width = 370 height = 280 >
<applet code = "[Link]" width = 370 height = 280 >
</applet>
</object>

Turn an application into an applet


Remember that applets are not allowed access to the client’s local files, operating
system etc. So if your program requires this functionality, you will need to rethink
it becoming an applet. To change a program into an applet, execute the following
steps;
1. Create the HTML that will invoke the applet.
2. The top-level class should extend the JApplet class instead of JFrame class.
3. Give the applet the BorderLayout that the JFrame has as its default layout
manager.
4. All the one time startup in the programs constructor method as well as in the
program’s main() method should be placed in the applets init() method.
5. All page “revisit” instructions should be placed in the applets start() method.
6. Fix any code that may not be used in the applet. i.e. Title bar text, I/O, operating
system instructions etc.
7. All “leaving page” code should be placed in the applet’s stop() method.

PAGE 300
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

JAVA I/O STREAMS AND FILES


This is one of the more difficult sections in Java. For something that is relatively
simple, Java has made it rather complicated. In C there are only a few functions
required to do effective I/O. In Java there are over 60 methods. This can be quite
daunting. Each type has its own function for reading and writing. You will also see
that in many cases one method will wrap another method as a filtering process in
order to attain the correct data.

One of the first issues you need to understand when working with I/O is: What is a
Stream? Visualize it as just that, a stream that flows from source to destination. In
reality, streams can have different sources i.e. A mountain spring, a dam etc. where
the water flows to a destination. The destination can also be different i.e. A dam, a
larger river, the sea etc. In Java the same applies. The source of data can be a
keyboard, scanner, hard disk etc. and the data flows to its destination such as a
screen, hard disk, network socket etc. A stream also allows you to tap into it as it
flows by. In Java the same applies; you can put or take data as it goes by. The
diagrams below should help to visualize all this.

The second important issue to understand is the different data formats. Data format
(sometimes called encoding) is the way your values i.e. the letter ‘A’ or ‘V’ or
1297 etc are represented on the system in terms of bits. The various different data
formats are;

PAGE 301
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

1. ASCII:
This is an 8-bit code that humans can easily read. It is known officially as the
ISO 8859_1 encoding standard.
2. UNICODE:
This is a 16-bit value. ASCII has the drawback that it can only store 256 (28)
unique characters. To be able to represent all characters worldwide, Unicode
was developed. This can store 65536 (216) unique characters. All encoding
internal to Java is based on Unicode. The first 256 characters are identical to
the ISO 8859_1 encoding standard.
3. UCS:
This is called the Universal Character Set. It comes in two forms UCS-2 and
UCS-4. UCS-2 is a 16-bit encoding whereas UCS-4 is a 32-bit encoding. The
UCS-4 is divided into a number of panes each containing 64K unique
characters. The first pane, pane 0 is basically UCS-2 and in real terms UCS-2
is essentially Unicode. So UCS-2 and Unicode tend to be used
interchangeably. So to say Java uses UCS-2 encoding internally is correct.
4. UTF:
This is the UCS Transformation Format. Its size is between one and three
bytes. So a character may be one, two or three bytes long. Basically, all
ACSII code is represented by UTF as one byte.
So all characters in the range '\u0001' to '\u007F' are represented by a single
byte. All Unicode characters below 0x7FF are represented as two bytes. The
null character '\u0000' and characters in the range '\u0080' to '\u07FF' are
represented by a pair of bytes and all other Unicode characters in the range
'\u0800' to '\uFFFF' are represented by three bytes. UTF can complicate
things a little. Its advantage however is its backward compatibility with
ASCII and its forward compatibility with Unicode.
5. binary:
This can be between one and eight bytes. The binary value of a character is
the same as that of ASCII or Unicode. Its advantage is its effective storing of
data. An int is 16-bits, a double precision floating-point number is 64-bits (8
bytes) long. Just beware however, that even though there is compatibility
between ASCII and Unicode, this data format should not be used if Unicode
or ACSII is intended.
6. object:
This is where objects become serialized and are then capable of being written
or read.

PAGE 302
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

Internally Windows uses Unicode encoding. Macintosh uses its own character set
where the first 128-characters are ASCII. Java, as already indicated uses Unicode
encoding internally. The implication of this is that whenever any I/O work is done
the I/O routines need to ensure that the native character set is translated into
Unicode. You must keep this in mind as we progress through this section. To assist
in this translation process Java has newly introduced two abstract classes;
Reader and Writer classes. These classes provide hooks (i.e. layers) for getting
between the Unicode and other character sets.

In Java, just like C, there are three standard, predefined stream objects;
1. [Link]
2. [Link]
3. [Link]
[Link] is an InputStream object that is used to read bytes from the standard
input, the keyboard. [Link] is a PrintStream object that is used to send
bytes of data to the standard output, the screen. [Link] is also a
PrintStream object and is used to report errors, usually to the screen.

Please be aware of a few things as we start to discuss I/O. The stream-based I/O
system packaged in [Link] and described in this chapter has been part of Java
since its original release and is widely used. However, beginning with version 1.4,
a second I/O system was added to Java. It is called NIO (which was originally an
acronym for New I/O). NIO is packaged in [Link] and its sub packages. NOTE
It is important not to confuse the I/O streams used by the I/O system discussed here
with the new stream API added by JDK 8. Although conceptually related, they are
two different things. Therefore, when the term ‘stream’ is used in all our
discussions, we are referring to an I/O stream.

Let us now look at reading and writing from and to streams. We shall first look at
the various ways of reading data (i.e. inputting) and then discuss writing (i.e.
outputting).

PAGE 303
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

JAVA INPUT
Reading Characters
As mentioned earlier Java I/O is layered. We read a sequence of bytes from an
input stream. In earlier versions of Java, if the input stream is a byte stream i.e. 8-
bits then we utilized the abstract class InputStream. If on the other hand we
worked with a 16-bit stream then we utilized the abstract class Reader. It is
recommended that one use the Reader class. As Reader is abstract it is
axiomatic that we will need to use one of its many subclasses. If you look at the
Reader methods, they are the same as the InputStream methods. The advantage is
that Reader methods convert the native code into Unicode. So if the character set is
ASCII or UTF, the Reader class will automatically translate to the Unicode
encoding format using the InputStreamReader class. The encoding that it uses
may be specified by name, or the platform's default encoding may be accepted.
Below is a listing of the Reader methods that get inherited by the subclasses;
public abstract class [Link] extends [Link]{
protected [Link] lock;
protected [Link]();
protected [Link]([Link]);
public abstract void close() throws [Link];
public void mark(int) throws [Link];
public boolean markSupported();
public int read() throws [Link];
public int read(char []) throws [Link];
public abstract int read(char [], int, int) throws [Link];
public boolean ready() throws [Link];
public void reset() throws [Link];
public long skip(long) throws [Link];
}

PAGE 304
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

Reading Characters from the standard input, the keyboard


The keyboard will present a byte value. So we may use the InputStream class to
read in a character. To do this we will use the [Link] class that is a subclass of
InputStream. We will invoke the read() method that will then return the byte
read from the input stream sourcing from our keyboard. I have written an example
below, (I included the finally block so you don’t forget about it);
import [Link].*;

public class ReadKeyBoard{


public static void main(String[] args){
int rdChar=0;
char ch;
try{
[Link]("Please enter characters at the Keyboard. Press CNTL-Z to Exit.");
while (rdChar != -1){
rdChar = [Link]();
ch = (char)rdChar;
[Link]("You entered: " + ch);
}
}
catch (IOException e){
[Link]("Error reading keyboard. Message :" + e);
}
finally{
[Link]("\nTerminating ReadKeyBoard program.");
}
}
}

If you now run this program, and enter; “One cup of Java and port please”
your output on the screen will look as follows;
Please enter characters at the Keyboard. Press CNTL-Z to Exit.
You entered: O
You entered: n
You entered: e
You entered:
You entered: c
You entered: u
You entered: p
You entered:
You entered: o
You entered: f
You entered:
You entered: J
You entered: a
You entered: v
You entered: a
You entered:
You entered: a
You entered: n
You entered: d
You entered:
You entered: p
You entered: o
You entered: r

PAGE 305
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

You entered: t
You entered:
You entered: p
You entered: l
You entered: e
You entered: a
You entered: s
You entered: e
You entered:
You entered:
Terminating ReadKeyBoard program.

To exit, press ctrl-Z and enter once you have run the program. If you ran this
example under windows you will see the two spaces at the end. Why are they
there? (UNIX and Macintosh would have one space). Change the line;
[Link]("You entered: " + ch);

to
[Link]("You entered: " + ch + " Whose Hexadecimal value is: " +
[Link](rdChar, 16));

Compile and run the program again. Can you work it out now?

To make sure that this code you have written above is internationalized, it would be
better to wrap the [Link] with the InputStreamReader class. What this will
do is allow for the correct character translation to take place on the host system.
(Remember this is one of the advantages of the Reader class). The code alters
slightly, as shown on the next page;

PAGE 306
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

import [Link].*;

public class ReadKeyBoardReader{


public static void main(String[] args){
int rdChar=0;
char ch;

try{
InputStreamReader charRead = new InputStreamReader([Link]);
[Link]("Please enter characters at the Keyboard. Press CNTL-Z to Exit.");
while (rdChar != -1){
rdChar = [Link]();
ch = (char)rdChar;
[Link]("You entered: " + ch + " Whose Hexadecimal value is: " +
[Link](rdChar,16));
}
}
catch (IOException e){
[Link]("Error reading keyboard. Message :" + e);
}
finally{
[Link]("\nTerminating ReadKeyBoard program.");
}
}
}

A few things to note about the examples above;


1. An EOF or End-Of-File is a –1, just as in C.
2. We used a class called Integer. This is a wrapper class around the int
primitive type. (All Java’s primitive types have their own wrapper class).
3. All the examples above can only read characters, not numeric values.

PAGE 307
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

Reading Characters from files


Earlier we listed the methods of the abstract Reader class. From this class a
number of subclasses exist that offer the Reader methods that read data from
different sources. These are:
1. BufferedReader: Read text from a character-input stream, buffering characters
so as to provide for the efficient reading of characters, arrays, and lines.
2. CharArrayReader: This class implements a character buffer that can be used as
a character-input stream.
3. FilterReader: An abstract class for reading filtered character streams.
4. InputStreamReader: An InputStreamReader is a bridge from byte streams
to character streams: It reads bytes and translates them into characters
according to a specified character encoding. The encoding that it uses may be
specified by name, or the platform's default encoding may be accepted.
5. PipedReader: Piped character-input streams.
6. StringReader: A character stream whose source is a String.
7. FileReader: This class extends the InputStreamReader class. It is a
convenience class for reading character files. The constructors of this class
assume that the default character encoding and the default byte-buffer size are
appropriate. To specify these values yourself, construct an InputStreamReader
on a FileInputStream

Of these classes listed, the ones most useful are CharArrayReader,


InputStreamReader, StringReader and FileReader. Before continuing, it is
very important that you study the Java documentation. It is just not feasible to list
all the class features here. I will present a few, you must do the rest. Having said
this, let us look at a simple example of reading characters from a file. (This code
can be better, but it gives you an idea)
import [Link].*;

public class ReadFileChar{


public static void main(String[] args){
char ch;
int in = 0;

try{
FileReader charRead = new FileReader("C:\\java\\stuprogs\\IOStreams\\[Link]");
while (in != -1){
in = [Link]();
ch = (char)in;
[Link](ch);
}
}
catch (EOFException e){
[Link]("\n\n\nWe have reached the end-of-file");
}
catch (IOException e){

PAGE 308
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

[Link]("\n\nError reading file: " + e);


}
}
}

The output on the screen for this is;


One Cup of Java, some Drambuie and Dancing Girls please.

In C we have to explicitly open() a file. In Java it is done automatically when


instantiating a stream object. In C we have to close() a file. In Java this is not
done automatically. It is imperative that once you have instantiated a stream object,
you must explicitly close() the stream. This ensures that all data sitting in the
memory buffer are flushed.

Now that we have come to the end of our discussion on reading a stream of
characters there are a few things to make note of;
1. Reading of characters is synchronous.
2. Use all classes that end in Reader. Do not use the InputStream class directly.
(Except when using [Link], [Link] or [Link])
3. Each invocation of one of an InputStreamReader's read() methods may
cause one or more bytes to be read from the underlying byte-input stream. For
top efficiency, consider wrapping an InputStreamReader within a
BufferedReader. for example,
BufferedReader in = new BufferedReader(new InputStreamReader([Link]));

PAGE 309
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

Reading Binary Data from files


When wanting to read binary data from a source we make use of the
DataInputStream class. The DataInputStream extends the
FilterInputStream class that extends the InputStream class. So the
DataInputStream class looks as follows;

public class [Link] extends [Link]


implements [Link] {
public [Link]([Link]);
public final int read(byte []) throws [Link];
public final int read(byte [], int, int) throws [Link];
public final boolean readBoolean() throws [Link];
public final byte readByte() throws [Link];
public final char readChar() throws [Link];
public final double readDouble() throws [Link];
public final float readFloat() throws [Link];
public final void readFully(byte []) throws [Link];
public final void readFully(byte [], int, int) throws [Link];
public final int readInt() throws [Link];
public final [Link] readLine() throws [Link];
public final long readLong() throws [Link];
public final short readShort() throws [Link];
public final [Link] readUTF() throws [Link];
public static final [Link] readUTF([Link])
throws [Link];
public final int readUnsignedByte() throws [Link];
public final int readUnsignedShort() throws [Link];
public final int skipBytes(int) throws [Link];
}

Each one of these methods will read the correct amount of binary data. If it comes
to an unexpected end, in other words, we instruct one of the methods to read a
certain amount of binary data, and it comes to the end-of-file before it expected to,
then an EOFException is thrown. Now what is important; an EOFException does
not indicate an end-of-file but rather “I came to the end of a file before I expected
to”. To monitor whether you have got to an end of file you look for a –1 to be
returned.

Another aspect of binary files to note is; How does the host system store its binary
data, as big endian or little endian? The Intel µprocessor instruction set demands
that the lower byte of data be stored first, then the higher byte. This is known as
little endian. On the other hand Motorola µprocessors store the high byte first, then
the lower byte. This is known as big endian. This becomes an issue when reading
binary files that were written on different systems. Now Java stores everything as
big endian. So be aware of this when reading binary files.

PAGE 310
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

In our previous example we used the standard input stream that is automatically
created for us by Java. If I really wanted to read bytes from the keyboard, I could
do so quite easily by using the DataInputStream class, where all you have to do is
to replace the line
InputStreamReader charRead = new InputStreamReader([Link]);

with
DataInputStream charRead = new DataInputStream([Link]);

That is fine. The stream is already created for us, so all we do is layer
DataInputStream on top of [Link]. How do we then read from a file? Notice
from the constructor that DataInputStream requires a stream as an argument in
order to reader data.
public [Link] ([Link]);

We therefore need to have a stream that connects to a file. To do this we simply


construct a stream with the pathname and filename we are wishing to read and like
before, layer the DataInputStream class on top of it. Remember earlier we
mentioned all subclasses of the Reader class (go back a few pages), well the
abstract InputStream class also has a number of subclasses;
For example;
1. ByteArrayInputStream: A ByteArrayInputStream contains an internal
buffer that contains bytes that may be read from the stream. An internal counter
keeps track of the next byte to be supplied by the read method.
2. FileInputStream: A FileInputStream obtains input bytes from a file in a
file system. What files are available depends on the host environment.
3. FilterInputStream: A FilterInputStream contains some other input
stream, which it uses as its basic source of data, possibly transforming the data
along the way or providing additional functionality. The class
FilterInputStream itself simply overrides all methods of InputStream with
versions that pass all requests to the contained input stream. Subclasses of
FilterInputStream may further override some of these methods and may also
provide additional methods and fields.
4. InputStream:
5. ObjectInputStream: An ObjectInputStream de-serializes primitive data and
objects previously written using an ObjectOutputStream.
ObjectOutputStream and ObjectInputStream can provide an application
with persistent storage for graphs of objects when used with a
FileOutputStream and FileInputStream respectively. ObjectInputStream
is used to recover those objects previously serialized.
6. PipedInputStream:

PAGE 311
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

7. SequenceInputStream: A SequenceInputStream represents the logical


concatenation of other input streams. It starts out with an ordered collection of
input streams and reads from the first one until the end of the file is reached,
whereupon it reads from the second one, and so on, until the end of file is
reached on the last of the contained input streams.
8. StringBufferInputStream: This class allows an application to create an input
stream in which the bytes read are supplied by the contents of a string.
Applications can also read bytes from a byte array by using a
ByteArrayInputStream. Only the lower eight bits of each character in the
string are used by this class.

Only those classes that may be useful to you at present contain an explanation.
Looking through this list we see that there is a class called FileInputStream
which will obtain bytes from a file for us. So all we do now is to create an instance
of the FileInputStream class that is attached to a file, and then to pass this
instance to the DataInputStream constructor. From there we just read the data
from the file. View the code;
import [Link].*;

public class ReadFileData{


public static void main(String[] args){
char rdChar, ch;
try{
FileInputStream inFileStream = new
FileInputStream ("c:\\java\\stuprogs\\IOStreams\\[Link]");
DataInputStream charReadFile = new DataInputStream(inFileStream);
while(true){
rdChar = [Link]();
ch = (char)rdChar;
[Link](ch);
}
} //end of try block
catch(EOFException e){
[Link]("\n\n\nWe have reached the end-of-file");
}
catch(IOException e){
[Link]("\n\nError reading file:" + e);
}
}
}

Just a point about this code. We are relying on an exception to exit the loop. Very
naughty!!

Notice how we have stipulated the file that needs to be opened. This limits the
software slightly as it means that it can only open the [Link] file.

PAGE 312
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

Incidentally, notice that I gave the file the extension of bin. This is so that I do not
get confused with text files whose extension I call txt. What you can do is make
use of command line arguments. By that I mean you pass the name of the file and
its path to the program at the command line. It is very useful to pass information
into your program when it is run. When we discussed methods earlier, we saw that
we could pass arguments to a method from the calling method. Now, in exactly the
same way the main() method within a Java program can read the arguments
passed to it by the operating system. So a command line argument is that
information that follows a program’s name on the command line of your operating
system. For example, in a DOS shell under Windows you would type;
C:\java program argument1 argument2

Here, program is the name of your Java program and argument1 and argument2
are the arguments you wish to pass to the main() method in the program

In Java there is one built-in argument. I have given it the variable name of args.

args is an array of strings which contains the command line arguments with which
the Java program was invoked. You are not limited in length. In our program
above, our main() method is declared as;
public static void main(String[] args)

where args is a String array. By the way this string array can have any name. In
C we have an argc that informs us of the number of arguments passed. In Java we
do not need this as we simply use args[x].length which will get the number of
strings in the array. Remember the first argument will be in args[0], the second in
args[1], etc. So we can make our program a little more versatile as follows;

Change the line


FileInputStream inFileStream = new FileInputStream("c:\\java\\stuprogs\\IOStreams\\[Link]");

to
FileInputStream inFileStream = new FileInputStream(args[0]);

Then at the command prompt type;


c:\java ReadDataFilePrompt filepath

To read exactly the same [Link] file we read in our earlier program then we
would type;
c:\java ReadDataFilePrompt c:\java\stuprogs\IOStreams\[Link]

PAGE 313
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

The results will be exactly the same as before. The useful thing now is that we may
read any binary file containing characters.

How would we read a file that contains integers? Well, it is just the same except
you must use the readInt() method in the DataInputStream class. As a final
example of reading a binary file peruse the following code.

import [Link].*;

public class IntReadFileDataPrompt{


public static void main(String[] args){
int rdInt;
try{
FileInputStream inFileStream = new FileInputStream(args[0]);
DataInputStream IntReadFile = new DataInputStream(inFileStream);
[Link]("Reading Integer contents of file: " + args[0]);

while(true){
rdInt = [Link]();
[Link]("Read Integer: " + rdInt);
}
}
catch(EOFException e){
[Link]("\nWe have reached the end-of-file");
}
catch(IOException e){
[Link]("\n\nError reading file: " + e);
}
}
}

What do you think would happen if I passed the binary file [Link] when I
invoke the above program from the command line?

In closing the section of reading binary files, remember;


1. In all cases you need to know the data that was written in order to read it
successfully.
2. Command line arguments can be used for reading any type of file. Just make
sure that the reading process is correct.
3. You can save floats, ints etc to a binary file. Study the methods listed at the
beginning of the binary section.

PAGE 314
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

Reading in numbers and other types from the keyboard


To read other types in from the keyboard and try and assemble numbers out of
characters is no trivial matter. This is a real bug bear in Java. Even C does it better.
You will find that many Java programmers create their own classes to perform this
function. Before we can read any value we must know in advance what type we are
reading. So to do this we need to layer instances of classes. Firstly we need to layer
the InputStreamReader on top of [Link] just as we did when we read
characters from the keyboard. Next we need to layer a BufferedReader on top of
the InputStreamReader. This is great as it allows for the text being typed in from
the keyboard to be a String when the user presses enter. Next we need to layer
[Link] on the String read in. Once that is done we then
use one of the StringTokenizer’s methods nextToken() to extract any leading
and trailing white space that may exist within the string. Once this is complete we
then use the method parseXxx() method inside the various primitive wrapper
classes to extract the value, where .Xxx in parseXxx() is the data type i.e., Long,
Float etc giving parseLong(), parseFloat() etc. Simple huh!!! So your
template needs to look something like the following;
import [Link].*;
import [Link].*;

public class ReadInAllSorts{


:
:
InputStreamReader is = new InputStreamReader([Link]);
BufferedReader br = new BufferedReader(is);

String str = [Link]();


StringTokenizer st = new StringTokenizer(str);
:
:
}

PAGE 315
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

Below is a table of the various primitive data types that you may wish to use. The
code associated with each of these primitive types that is required in order to read
each one is also shown;

Primitive Type Code to read it from [Link]


char int I = [Link](); //-1 is end-of-file
char c = (char) I;
String String s = [Link]();
boolean boolean bool = new Boolean([Link]()).booleanValue();
int int I = [Link]([Link]());
byte byte bt = [Link]([Link]());
short short st = [Link]([Link]());
long long lng =[Link]([Link]());
float float ft = new [Link]([Link]());
double double dbl = new [Link]([Link]());

To see all this in action Peter van der Linden of Sun Microsystems has written a
simple class to show all this in operation. This will be found in the software VZAP
gave you and is called EasyIn. Peruse it and use it. Incidentally we will be looking
at a new class called Scanner a little later which will allow you to read data from
an input stream.

PAGE 316
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

Working with multiple files that require the same processing


There may be times when you may have numerous files that contain data each
needing to be processed in the same way. This can be achieved in Java by grouping
all the streams together as a single SequenceInputStream. What we do is read
each stream into a buffer, then process from there. The sequence of events to
achieve this is;
1. Create a FileInputStream for each file you wish to read.
2. Group each of these FileInputStreams together as a single
SequenceInputStream.
3. Convert this stream into a reader using InputStreamReader.
4. Layer a BufferedReader on the InputStreamReader
5. Read from the BufferedReader.

Let us assume we have two files. One called [Link] which contains:
“One cup of Java and cake please.”

and a second file called [Link] which contains:


“Oh, a wee dram would be nice too.”

We want to print this out to the screen. The code to do this looks as follows;
import [Link].*;

public class FileConcatReadFile{


public static void main(String[] args){
try{
FileInputStream fileOne = new FileInputStream(args[0]);
FileInputStream fileTwo = new FileInputStream(args[1]);

SequenceInputStream fileOneTwo = new SequenceInputStream(fileOne, fileTwo);

InputStreamReader sequencedFiles = new InputStreamReader(fileOneTwo);

BufferedReader buffSequencedFiles = new BufferedReader(sequencedFiles);

[Link]("Data in the files: " + args[0]+ " and " + args[1] );

int dataIn = 0;
while((dataIn=[Link]()) != -1){
[Link]((char)dataIn);
}
}

catch (FileNotFoundException e){


[Link]("\nFile Error:" + e);
}
catch (IOException e){
[Link]("\nIO Error:" + e);
}

PAGE 317
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

}
}

To invoke the program type:


c:\java FileConcatReadFile c:\[Link] c:\[Link]

The output on the screen should look as follows;


Data in the files: c:\[Link] and c:\[Link]
One cup of Java and a cake please. Oh, a wee dram would be nice too.

That brings us to the end of reading data.

PAGE 318
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

JAVA OUTPUT
Let us now look at the way Java writes to an output stream. Character output is
performed using one of the Writer class’ subclasses. Effectively this is the
opposite of the Reader class. The classes that the subclasses will inherit are;
public abstract class [Link] extends [Link] {
protected [Link] lock;
protected [Link]();
protected [Link]([Link]);
public abstract void close() throws [Link];
public abstract void flush() throws [Link];
public void write(int) throws [Link];
public void write([Link]) throws [Link];
public void write([Link], int, int) throws [Link];
public void write(char []) throws [Link];
public abstract void write(char [], int, int) throws [Link];
}

As Writer is abstract you will deal with subclasses of Writer. There are a
number of subclasses of the Writer class that offer different destinations, these
are;
1. BufferedWriter: Write text to a character-output stream, buffering characters
so as to provide for the efficient writing of single characters, arrays, and strings.
The buffer size may be specified, or the default size may be accepted. The
default is large enough for most purposes.
2. CharArrayWriter: This class implements a character buffer that can be used
as a Writer. i.e. writes characters into an array. The buffer automatically grows
when data is written to the stream. The data can be retrieved using
toCharArray() and toString().
3. FilterWriter: abstract class for writing filtered character streams.
4. OutputStreamWriter: Write characters to an output stream, translating
characters into bytes according to a specified character encoding. Each
OutputStreamWriter incorporates its own CharToByteConverter, and is
thus a bridge from character streams to byte streams.
5. PipedWriter: Piped character-output streams.
6. PrintWriter: Print formatted representations of objects to a text-output
stream. This class implements all of the print methods found in PrintStream.
7. StringWriter: A character stream that collects its output in a string buffer,
which can then be used to construct a string. i.e. Writes characters to a string.

PAGE 319
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

Writing Characters to the standard output, the console


We have been using this frequently during the course. We have made use of the
[Link] object. Incidentally, this class contains a number of useful methods for
a program, not the system as its name implies. So to write to the console we use;
[Link]("Message");

Which issues a carriage return linefeed at the end of writing to the screen, or;
[Link]("Message");

Which does not issue a carriage return and linefeed.

Writing Characters to a file


The discussion under reading characters from a file applies equally here. Again it
is important to note the systems encoding. To write to a file, we make use of the
abstract Writer class’ subclasses (listed earlier). Out of this list the classes you
will use the most are:
CharArrayWriter, OutputStreamWriter, StringWriter and a subclass of
OutputStreamWriter known as FileWriter.

So we may use the FileWriter class to write a character stream to a file. We will
invoke the write() method which will then write the character to the file opened.
Let us look at an example;
import [Link].*;

public class CharWriteFile{


public static void main(String[] args){
try{
FileWriter outFileStream = new FileWriter(args[0]);
int dataIn = 0;
[Link]("Starting typing to write data to the file: " + args[0]);
[Link]("To Exit press: CNTL-Z");
while ((dataIn=[Link]()) != -1){
[Link]((char)dataIn);
}
[Link]();
}
catch (IOException e){
[Link]("\nIO Error:" + e);
}
}
}

Note a few things about the program. Once we have opened a stream we need to
close the file. This is performed by the [Link]() statement.
Now, if we want to write boolean data, say, a float or int value to a file as a
series of characters, we need to do some stream layering. To do this we make use

PAGE 320
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

of the PrintWriter class. So to write binary data as a series of characters you can
do the following;
import [Link].*;

public class CharWriteFileData{


public static void main(String[] args){
try{
FileWriter outFileStream = new FileWriter(args[0]);
PrintWriter outPrintStream = new PrintWriter(outFileStream);

boolean switchOnOff = true;


float pi = 3.14159f;
int counter = 1892;
double ionCount= 2134.12;

[Link]("Starting to write binary data as characters to


the file: " + args[0]);

[Link](switchOnOff);
[Link](pi);
[Link](counter);
[Link](ionCount);

[Link]();
}
catch (IOException e){
[Link]("\nIO Error:" + e);
}
}
}

Notice how we have wrapped PrintWriter stream around the FileWriter


stream. In exactly the same way that all our classes that read characters ended in
Reader, all our classes dealing with writing characters end in Writer. Now that
we are able to write binary values as characters we need to make sure that the
format of the characters written correspond to what we require. What I mean by
this is “How do I make sure that I only output to the file a floating point number
with four decimal places” etc. Java provides classes and interfaces for handling
text, dates, numbers, and messages in a manner independent of natural languages.
These are found in a package called [Link].

So let us look at the DecimalFormat class resident in this package. Do you


remember the printf() method we discussed earlier on in the course? Well
DecimalFormat is going to assist us in formatting decimal numbers in a similar
fashion. As you go through this section think if it is possible to use printf()
instead of DecimalFormat. DecimalFormat is a concrete subclass of
NumberFormat for formatting decimal numbers. This class allows for a variety of
parameters, and localization to Western, Arabic, or Indic numbers.

PAGE 321
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

Note: this class is designed for common users; for very large or small numbers, use
a format that can express exponential values.

Example: I’ll use a statically declared array of doubles. I could have entered in the
data using the EasyIn class or Scanner. Why don’t you try that? If you used the
same numbers, the output to the file will be exactly the same as that to the screen.
port [Link].*;
import [Link].*;

public class CharWriteScreenFormat{


public static void main(String[] args){
DecimalFormat charFormat = new DecimalFormat("#0.00; #0.00-");
double [] arr = {.0, 0.123, -1.1, 2.2, -3.33, 4.4444, -5, 55555, 6.666666};

for (int j=0; j<[Link]; j++) {


[Link]([Link](arr[j]));
}
}

The output will look like:


0.00
0.12
1.10-
2.20
3.33-
4.44
5.00-
55555.00
6.67

Notice the format; we have two decimal places of precision, and the negative
numbers have a ‘-’ following. I could have used ‘CR’ instead of ‘-’ in the format
specification. The ‘0.’ before the decimal point in the format string indicate that at
least one digit must be displayed. The ‘.00’ after the decimal in the format string
indicates 2 digits of precision. Here are the special characters used in the parts of
the sub pattern, with notes on their usage.

PAGE 322
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

Symbol Meaning
0 a digit
# a digit, zero shows as absent
. placeholder for decimal separator
, placeholder for grouping separator.
E separates mantissa and exponent for
exponential formats.
; separates formats.
- default negative prefix.
% multiply by 100 and show as percentage
? multiply by 1000 and show as per milli
X any other characters can be used in the
prefix or suffix
‘ used to quote special characters in a prefix
or suffix.

Let us look at some typical formats;

Format String Meaning Value Output String


##0.00 At least one digit before the 1234.567 1234.57
.256 .26
decimal point and two digits 1234.565 1234.56
after. 1234.575 1234.58
#.000 Possibly no digits before the 1234.567 1234.567
.256 .256
decimal point but three after.
,### Use thousands separator and 1234.567 1,234
.256 0
no decimal places.
0.00; 0.00CR Show negative numbers with -27.2 27.20CR
CR on the right.

In practice, irrational numbers are approximated by truncation to a required


number of decimal places. This is shown in the code and table above. There is a
slight problem in truncating when a single figure to be discarded is a 5. For
example, in the table above the number 1234.565 is exactly half way between
1234.56 and 1234.57. To write this value to the second decimal point, the accepted
convention is to round up or down to the next even last figure. This is shown in the
table above. For more details (of which there are many) on the DecimalFormat
class and the sub patterns, go and peruse the DecimalFormat class documentation.

PAGE 323
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

Writing Binary Data to files


Remember we used the DataInputStream class to read binary data? Well to write
binary data to a file we use the DataOutputStream class. The code following
should be self-explanatory. Use it to generate a file that our program written under
the section “Reading Binary Data from files” may use for testing.

import [Link].*;

public class WriteFileData{

public static void main(String[] args){


int readChar=0;
char ch;
try{
FileOutputStream outFileStream = new
FileOutputStream ("c:\\java\\stuprogs\\IOStreams\\[Link]");
DataOutputStream charWriteFile = new DataOutputStream(outFileStream);
String st = "Oh!! Hello. Please may I have one cup of java and some
Irish Mist please.";

[Link]("Starting to write the javacup file. \n\n");


[Link](st);
}
catch(IOException e){
[Link]("\nIO Error:" + e);
}
finally{
[Link]("\n\nTerminating WriteFileData program.");
}
}
}

Naturally it would be better to replace the statement;


FileOutputStream ("c:\\java\\stuprogs\\IOStreams\\[Link]");

with
FileOutputStream (args[0]);

Finding information on a file. The File class.


In java there is a useful class called File. The File class is based on (implements)
the FileOutputStream class which in turn is based on the OutputStream class
and is how it gets most of its functionality. The purpose of this class is not to
create a file, but rather to find information about a file. The File class cannot be
used to create, read from or write to files. It is a class that simply represents an
existing file or directory. Objects of this class are used by many other input/output
objects that handle the actual transferring of data. Although a File object does not
allow you to write or read its contents, it does allow you to carry out several useful
housekeeping tasks such as finding the length of a file, making a directory,

PAGE 324
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

comparing two files, changing the name of a file or even deleting it. The main
thing to remember; the File class cannot write to or read from a file.

The File class has essentially three constructor methods, as well as numerous
methods that work on files. Below are a number of examples illustrating the use of
some of these methods.

Using the isFile(), canRead() and canWrite() methods:


import [Link].*;
public class Test{
public static void main(String[ ] args){
File trial = new File("Your path and fileName go here");
if( [Link]( ) && [Link]( ) && [Link]( ) ){
[Link]("File exists and can be used");
}
else{
[Link]("File is no good for purpose intended - Application terminated");
}
}
}

Here is another similar example answering the questions; Does myDir reference a
directory? Does the file exist? Can it be read from? Can it be written to?
import [Link].*;
public class Test{
public static void main(String[ ] args){
File myDir = new File("Your path and directory goes here");
[Link](myDir+([Link]()?" is":" is not" )+" a directory.");
// Construct an object that is of the class File
File myFile = new File(myDir,"Your fileName goes here");
[Link](myFile+([Link]()?" does":" does not") + " exist");
[Link]("You can "+([Link]()?" ": "not" ) + " read from " + myFile);
[Link]("You can "+([Link]()?" " : "not" ) + " write to " + myFile);
}
}

Here is another example where you are checking the absolute path:
import [Link].*;
public class Test{
public static void main(String[ ] args){
// Construct an object of File that references a directory
File myDir = new File("Your path and directory go here");
[Link]("[Link]() is " + [Link]());
// Construct an object of File that references a file
File myFile = new File(myDir, "Your fileName goes here");
[Link]("[Link]() is " + [Link]());
}
}

PAGE 325
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

An interesting method is the list() method. It returns an array of String objects


which are the names of the files in the directory represented by the File instance
that invoked the list() method.

import [Link];
public class Test {
static String files[ ];
public static void main(String args[]){
// Get path to the directory to be listed.
// If no command line argument is supplied, programme will exit.
String path = ".";
if([Link] >= 1){ // Check for command line arguments
path = args[0];
}else {
[Link]("No command line data entered");
[Link](0);
}
// Make sure that a path exists
File f = new File(path);
if([Link]()){
[Link](path + " is a valid directory");
}else{
[Link](path + "doesn't exist or is not a directory");
[Link](0);
}
files = [Link]( );
for(int count = 0; count<[Link]; count++){
[Link](files[count]);
}
}
}

Type out this example, run it and observe the output generated. For your
edification, here is a listing of the methods the File class contains;

public class [Link] extends [Link] implements


[Link], [Link] {
public static final char separatorChar;
public static final [Link] separator;
public static final char pathSeparatorChar;
public static final [Link] pathSeparator;
static {};
public [Link]([Link],[Link]);
public [Link]([Link]);
public [Link]([Link],[Link]);
public boolean canRead();
public boolean canWrite();
public int compareTo([Link]);
public int compareTo([Link]);
public boolean createNewFile() throws [Link];
public static [Link] createTempFile([Link],
[Link]) throws [Link];
public static [Link] createTempFile([Link],
[Link], [Link]) throws [Link];
public boolean delete();

PAGE 326
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

public void deleteOnExit();


public boolean equals([Link]);
public boolean exists();
public [Link] getAbsoluteFile();
public [Link] getAbsolutePath();
public [Link] getCanonicalFile() throws [Link];
public [Link] getCanonicalPath() throws [Link];
public [Link] getName();
public [Link] getParent();
public [Link] getParentFile();
public [Link] getPath();
int getPrefixLength();
public int hashCode();
public boolean isAbsolute();
public boolean isDirectory();
public boolean isFile();
public boolean isHidden();
public long lastModified();
public long length();
public [Link] list()[];
public [Link] list([Link])[];
public [Link] listFiles()[];
public [Link] listFiles([Link])[];
public [Link] listFiles([Link])[];
public static [Link] listRoots()[];
public boolean mkdir();
public boolean mkdirs();
public boolean renameTo([Link]);
public boolean setLastModified(long);
public boolean setReadOnly();
public [Link] toString();
public [Link] toURL() throws [Link];
}

Finally, if you have been perusing the Java documentation on all the I/O classes
you may have noticed that some of the class’ constructors allow you to pass, as an
argument, a File instance that will be used to open the file for reading and/or
writing. To illustrate this here is an example using the PrintWriter classes.
import [Link];
import [Link];

public class FilePassingExample {


public static void main(String[] args) throws Exception {
try{
File fileExample = new File("c:\\java\\stuprogs\\IOStreams\\[Link]");
// better would be ..
//File fileExample = new File(args[0]);
PrintWriter outPrintStream = new PrintWriter(fileExample);
boolean switchOnOff = true;
float pi = 3.14159f;
int counter = 1892;
double ionCount= 2134.12;
[Link]("Starting to write binary data as characters to the file");
[Link](switchOnOff);
[Link](pi);
[Link](counter);

PAGE 327
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

[Link](ionCount);
[Link]();
}
catch (IOException e){
[Link]("\nIO Error:" + e);
}
}
}

I am sure you have a very good idea as to how to make use of the File class by
now. Work through this class’ Java documentation. You will find many of its
methods useful.

Scanner class
Prior to JDK5, it was a real mission to get data into a program from a stream. You
have seen this from our earlier discussion. To make it a little more convenient to
work with streams, JDK5 introduced a new class, the Scanner class. What this
class is able to do for us is that it is capable of reading the token elements of a
stream and then return them as strings or any primitive data type. There is a lot of
functionality that surrounds this class, so I really encourage you to peruse its Java
documentation. Hopefully, what we do here will give you a good foundation as
how you may make use of this wonderful utility class.

What this class’ methods [apart from its nextLine() method] will do is parse the
tokens that are found in its input stream. A token is a continuous sequence of
(usually) non-whitespace characters. In Java a whitespace character is defined by
default by the [Link]() wrapper method. Also, by default a
whitespace is recognized as the separation character (often called the ‘delimiter’)
between tokens. So for example, in the string; “One cup of Java and some
Drambuie please”, all the words are the tokens and the whitespace between them
are the ‘delimiters’. Let us use this string in an example and get a Scanner instance
to parse it;
import [Link];

public class ScannerParseTest{

public static void main(String[] args){


String str="One cup of Java and some Drambuie please";
Scanner scan=new Scanner(str);
while([Link]()){
[Link]([Link]()); //print each token on a line
}
}
}

Your output should look as follows


One

PAGE 328
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

cup
of
Java
and
some
Drambuie
please

Notice how each token was ‘extracted’. The hasNext() method checks to see if
there is a token on the input stream, and if there is it returns a true, else returns
false. If there is a token on the input stream, you get this token by invoking the
next() method on the Scanner instance. Now, what the next() method returns is
the token represented as a string, no matter what the token may consist of. If you
require one of the primitive types, then you would make use of the nextXXX()
methods, where XXX represents the datatype. For instance nextInteger(),
nextFloat(), nextBoolean(), etc. Associated with these methods are the
hasNextXXX() methods. For instance; hasNextInteger(), hasNextFloat(),
hasNextBoolean(). I am sure you can figure out how to use them. Just in case
you are not too sure here are some examples;
import [Link];

public class ScannerParseTest{

public static void main(String[] args){


String str="It is true that I would like one cup of Java and some Drambui please";
Scanner scan=new Scanner(str);
while([Link]()){ //Check if there is a token
if([Link]()){ //Check if the token is Boolean
//get boolean token
[Link]("Found a boolean value: "+[Link]());
continue; //go back to start of loop to check if there is another token
}
[Link]([Link]()); //print each token on a line
}
}
}

And here is a rather interesting example; we are reading primitive types in which
we are using four integer type methods, passing them the base value of the number
system to be applied to the token read. There are actually four ‘whole number’ i.e.
integer type, methods that are overloaded which you to pass in a radix value that
determines the counting system to be applied to the whole number token read in
from the stream. Do you understand what is happening?

import [Link];

public class ScannerParseTest{


public static void main(String[] args){
String str="123.778 1010 1010 2 72";
Scanner scan=new Scanner(str);

PAGE 329
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

[Link]("Float value: "+[Link]());


[Link]("Decimal value: "+[Link]());
[Link]("Base 2 [binary] value: "+[Link](2));
[Link]("Base 16 [hex] value: "+[Link](16));
[Link]("Base 8 [Octal] value: "+[Link](8));
}
}

The output once this program is run is;


Float value: 123.778
Decimal value: 1010
Base 2 [binary] value: 10
Base 16 [hex] value: 2
Base 8 [Octal] value: 58

As you know the keyboard is represented as a stream in Java. As you can attach a
Scanner to any stream instance, it goes without saying that it is permissible to
attach a Scanner instance to the keyboard input stream [Link]. Scanner has
a very useful method, nextLine() which reads a line of text and returns this whole
line as a string. Let us look at a simple example reading data from the keyboard
using Scanner;

import [Link];

public class ScannerKeyboardTest{


public static void main(String[] args){
[Link]("Enter some text: ");
Scanner scan=new Scanner([Link]);
String str=[Link]();
[Link]("\nYou entered: "+str);
}
}

I am sure you understand all this. For our last example, let us look at reading a text
file and parsing it with Scanner. Let us also change the default delimiter from a
whitespace character to a comma. Go ahead and create a file that contains the
following and call it [Link];
All the King’s Men, Robert Penn Warren, 250.78
The Cricket on the Hearth, Charles Dickens, 213.65
Of Mice and Men, John Steinbeck, 321.22
Things Fall Apart, Chinua Achebe, 231.64
Call me Women, Ellen Kuzwayo, 263.11

Now here is the code. Notice how we used the File class to access the [Link]
file, changed the delimiter using the useDelimiter() method and read in each
line from the file and then extracted the tokens for each of the read lines.
import [Link];

PAGE 330
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

import [Link];
import [Link];

public class ScanDelimitedFile {


public static void main(String[] args) {
ScanDelimitedFile sdf=new ScanDelimitedFile();
//rather use args[] and error checking etc
[Link]("c:\\Java\\[Link]");
}

//*******************************
private void run(String bookFile){
File file = new File(bookFile);
Scanner scan = null;
try {
scan = new Scanner (file);
while([Link]()){
String str = [Link]();
parseLine(str);
}
} catch (IOException exp) {
[Link]();
}
[Link]();
}

//*******************************
private void parseLine(String str){
String book, author, price;
Scanner sc = new Scanner(str);
[Link](",");
// Check if there is another line of input
while([Link]()){
book = [Link]();
author = [Link]();
price = [Link]();
[Link]("Book - " + book + " :Author - " + author +
" :Price - " + price);
}
[Link]();
}
}

Your output should look something along the following lines;


Book - All the King's Men :Author - Robert Penn Warren :Price - 250.78
Book - The Cricket on the Hearth :Author - Charles Dickens :Price - 213.65
Book - Of Mice and Men :Author - John Steinbeck :Price - 321.22
Book - Things Fall Apart :Author - Chinua Achebe :Price - 231.64
Book - Call me Women :Author - Ellen Kuzwayo :Price - 263.11

Flippin’ awesome and easy!!

In closing the section on I/O there are some rules to memorize to make it easier;
1. All Java I/O is done using streams.
2. There are two kinds of streams; 8-bit and 16-bit.

PAGE 331
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

3. 8-bit streams are known as InputStreams or OutputStreams.


4. 16-bit streams are known as Readers or Writers.
5. Each stream can offer just one kind of service to a file. (i.e. Character I/O,
binary I/O, I/O to a byte array).
6. To get the exact processing, you need to layer (or connect, wrap) streams
together. Passing one stream as an argument to the constructor of another does
this.
7. When performing character input, use all the classes that end in Reader (not
InputStream). Likewise when performing character output use all classes
ending in Writer (not OutputStream). This helps in internationalizing your
code.

PAGE 332
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

RANDOM FILE ACCESS AND APPENDING


One of the problems we have when opening a file and writing to it is that all the
previous contents are erased, so beware. This may not be desirable. Also, the
access has been sequential. To overcome this problem we perform random file
access. We can go to any part of the file and start reading or writing. So in order
not to erase any data in a file we may go to the end of the file and append new data
to it.

To perform random file access we make use of the class RandomAccessFile.


Instances of this class support both reading and writing to a random access file. A
random access file behaves like a large array of bytes stored in the file system.
There is a kind of cursor, or index into the implied array, called the file pointer. For
input operations, read bytes starting at the file pointer and advance the file pointer
past the bytes read. If the random access file is created in read/write mode, then
output operations are also available; output operations write bytes starting at the
file pointer and advance the file pointer past the bytes written. Output operations
that write past the current end of the implied array cause the array to be extended.
The file pointer can be read by the getFilePointer method and set by the seek
method.

It is generally true of all the reading routines in this class that if end-of-file is
reached before the desired number of bytes has been read, an EOFException
(which is a kind of IOException) is thrown. If any byte cannot be read for any
reason other than end-of-file, an IOException other than EOFException is
thrown. In particular, an IOException may be thrown if the stream has been
closed.

To allow for random reading we open the file for read access only. Passing the
letter ‘r’ to the class constructor signifies this. To allow for random reading and
writing we open the file for read/write access. Passing the letters ‘rw’ to the class
constructor signifies this.

There are a number of methods in this class. These are listed below.
public class [Link] extends [Link] implements
[Link], [Link] {
static {};
public [Link]([Link],[Link])
throws [Link];
public [Link]([Link],[Link])
throws [Link];
public native void close() throws [Link];
public final [Link] getFD() throws [Link];

PAGE 333
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

public native long getFilePointer() throws [Link];


public native long length() throws [Link];
public native int read() throws [Link];
public int read(byte []) throws [Link];
public int read(byte [], int, int) throws [Link];
public final boolean readBoolean() throws [Link];
public final byte readByte() throws [Link];
public final char readChar() throws [Link];
public final double readDouble() throws [Link];
public final float readFloat() throws [Link];
public final void readFully(byte []) throws [Link];
public final void readFully(byte [], int, int) throws [Link];
public final int readInt() throws [Link];
public final [Link] readLine() throws [Link];
public final long readLong() throws [Link];
public final short readShort() throws [Link];
public final [Link] readUTF() throws [Link];
public final int readUnsignedByte() throws [Link];
public final int readUnsignedShort() throws [Link];
public native void seek(long) throws [Link];
public native void setLength(long) throws [Link];
public int skipBytes(int) throws [Link];
public native void write(int) throws [Link];
public void write(byte []) throws [Link];
public void write(byte [], int, int) throws [Link];
public final void writeBoolean(boolean) throws [Link];
public final void writeByte(int) throws [Link];
public final void writeBytes([Link]) throws [Link];
public final void writeChar(int) throws [Link];
public final void writeChars([Link]) throws [Link];
public final void writeDouble(double) throws [Link];
public final void writeFloat(float) throws [Link];
public final void writeInt(int) throws [Link];
public final void writeLong(long) throws [Link];
public final void writeShort(int) throws [Link];
public final void writeUTF([Link]) throws [Link];
}

Let us look at an example: Assume that we have a file called [Link] with
the following in it:
"Oh hello there. May I please have one cup of Java and a Drambuie."

Assume that we want to add some text to the end of it; the code following will do
this;
import [Link].*;

public class RandomCharWriteFile{


public static void main(String[] args){
try{
RandomAccessFile outFileStream = new RandomAccessFile(args[0],"rw");

[Link]([Link]());
[Link]("Starting typing to write data to the file: " + args[0]);
[Link]("To Exit press: CNTL-Z");

PAGE 334
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

int dataIn = 0;
while ((dataIn=[Link]()) != -1){
[Link](dataIn);
}
[Link]();
}
catch (IOException e){
[Link]("\nIO Error:" + e);
}
}
}

At the command line type:


c:\java RandomCharWriteFile c:\[Link]

Then if you type in the following:


Oh!! some port would be good too. Thanks. <ctrl-z>

and then peruse the [Link] file. You will see that the file now contains;
Oh hello there. May I please have one cup of Java and a Drambuie. Oh!! some
port would be good too. Thanks.

By the way if you had studied the FileOutputStream class you would have
noticed that there is a constructor that will allow you to append data in a file. This
would be invoked as follows;
FileOutputStream outFileStream = new FileOutputStream(args[0], true);

The FileWriter class also has this facility to append. You invoke the constructor;
FileWriter outFileStream = new FileWriter(args[0], true);

PAGE 335
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

SERIALIZATION
In all our discussion on file I/O so far, we have worked with primitive data types.
What happens if we want to read and/or write objects? We cannot do what we have
been doing previously. What you need to do is to go through a process called
object serialization. What this means is; you write the state of an object to a byte
stream, and then saves it to some form of persistent data storage area, such as a
hard drive. If you then wish to restore the saved object, you need to reconstruct the
object as it is read in from the persistent data storage area. This reversing process is
known as deserialization.

Object serialization is used mainly in two areas;


1. As indicated above; The storage of an object that may be used again at a later
stage by a program,
2. To implement remote method invocation (RMI). This is where a Java object on
one machine may call and invoke a method of a Java object that resides on a
different machine.

A question arises here. What happens if the object that is to be serialized has
references to other objects, which in turn reference still more objects? The answer
is that if an object does refer to other objects, the process of serialization traverses
all references to these other objects that are referenced recursively, and writes them
all. During the process of deserialization all objects are restored.

For an object to be serialized it has to implement the Serializable interface.


This Serializable interface is rather strange in that it does not contain any
methods or instance variable declarations. It is empty!! It is defined as follows;
public interface Serializable { }

The purpose of this interface is to ensure that instances of the classes that
implement the Serializable interface may be serialized. Instances of classes that
do not implement this interface may not be serialized. Implementing the
Serializable interface is accomplished as follows;
public class MySerializableClass implements Serializable{
:
}

One important thing to note about classes that implement the Serializable
interface is that any of those classes instance variables declared as being
transient or static are not saved by the serialization process.

PAGE 336
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

The class ObjectOutputStream makes use of a default method called


defaultWriteObject() to serialize an object. In most cases this method is
adequate, but it is slow. So there is a facility for you to customize your serialization
process. To do this you must override the writeObject() method. Consult the
Java documentation. To have complete, explicit control of the serialization process
you need to implement the Externalizable interface. Again, for more on this
consult the Java documentation.

To help you understand the serialization process and how you may save an object
to a file let us look at a couple of examples. The first is a succinct example of
object serialization. The code listing consists of three classes. The first is a Person
class that encapsulates a person’s information and its code listing is below. Notice
that this class implements the Serializable interface.
package [Link];

public class Person implements [Link]{


private String firstName, lastName;
private int age;

public Person(String firstName, String lastName, int age){


[Link] = firstName;
[Link] = lastName;
[Link] = age;
}

public String getFirstName(){


return firstName;
}

public String getLastName(){


return lastName;
}

public int getAge(){


return age;
}

public String toString(){


return firstName + " " + lastName + ", " + age;
}
}

I am sure you
understand the above coding. The second class,
SerialExampleOut, creates a new Date, String, as well as a new Person
instance. If you study the documentation relating to the [Link] and the
[Link] classes you will notice that both these classes implement the
Serializable interface as does the Person class whose listing we looked at
earlier. These three objects are then saved to a file called [Link] by invoking

PAGE 337
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

the writeObject() method on the ObjectOutputStream instance objOut. The


listing for this class is as follows;
import [Link];
import [Link].*;
import [Link];

class SerialExampleOut{
public static void main(String[] args){
try{
[Link]("Opening file...");
FileOutputStream out = new FileOutputStream("c:\\[Link]");
ObjectOutputStream objOut = new ObjectOutputStream(out);

[Link]("Writing current Date...");


Date date = new Date();
[Link](date);

[Link]("Writing a String...");
String str = new String("Serialization String");
[Link](str);

[Link]("Writing a \'Person\'...");
Person per = new Person("John" , "Doe", 28);
[Link](per);

[Link]("Closing file...");
[Link]();
}
catch(IOException ioe){
[Link]("IO Error : " + [Link]() );
}
}
}

It is that simple saving objects. Running the above code produces the following
output;
Opening file...
Writing current Date...
Writing a String...
Writing a 'Person'...
Closing file...

The last listing, SerialExampleIn, illustrates how you may read objects that have
been persisted. The one important issue here is that you must read the objects in the
same order as they were written.
import [Link];
import [Link].*;
import [Link];

class SerialExampleIn {
public static void main(String[] args){

PAGE 338
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

try {
/* ***********************************************************
NB: The order in which we read the objects obviously depend
on the order in which they were written. If we do not know the
above mentioned order, it will be difficult to cast to the
correct type.

In the example below, it was not really necessary to cast, but


I put it in as an example of how it can be done.
*********************************************************** */

[Link]("Opening file...");
FileInputStream in = new FileInputStream("c:\\[Link]");
ObjectInputStream objIn = new ObjectInputStream(in);

[Link]("Reading a Date from the file...");


Date date = (Date)[Link]();
[Link](date);

[Link]("Reading a String from the file...");


String str = (String)[Link]();
[Link](str);

[Link]("Reading a \'Person\' from the file...");


Person per = (Person)[Link]();
[Link](per);

[Link]("Closing file...");
[Link]();
}
catch(IOException ioe){
[Link]("IO Error : " + [Link]() );
}
catch(ClassNotFoundException cnf){
[Link]("Class Not Found Error : " + [Link]() );
}
}
}

That essentially is how you read in objects. I am sure you agree it is not difficult at
all. Just remember, objects that need to be persisted must implement the
Serializable interface. Running this above code produces the following output
(it is axiomatic that SerialExampleOut must have been executed first);
Opening file...
Reading a Date from the file...Mon Jul 22 16:50:27 GMT+02:00 2002
Reading a String from the file...Serialization String
Reading a 'Person' from the file...John Doe, 28
Closing file...

For the second example, I have written a small transaction-processing program that
allows the storage of up to one hundred fixed length records containing an account
number, a client’s first name, last name and an amount. The account number is
used as a key as to each records position within the file. What I have done is

PAGE 339
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

created three different classes. The account information is contained in the


AccountRecord class. A user interface used (UI) to enter the data is contained in
the UserScreenRdmAccs class. The actual main program is in the TestUI class.
Please note that this is a very simple program. You can make some worthwhile
improvements to it.

The programs user interface looks as follows;

Here the user may enter the data for each client. If the user presses Cancel at this
stage the program terminates without saving any data. Before data may be saved, a
file needs to be opened to which the data may be saved. This is accomplished by
the user pressing the Save As.. button. When this button is pressed the following
screen appears;

The directory the File option box defaults to is c:\Temp. (Your Temp directory may
contain many other files than what I have here). If the file you require is in another
directory you may select it. The screen captures below show this;

PAGE 340
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

Once you have selected the required file to which you wish to save the data, the
original user interface changes slightly.

Firstly, the full path and name of the file appears in the frames title screen. A
screen capture of this is shown below (I have expanded the window so you may
see the full path)

Notice that now the Save As.. button is dimmed (disabled) and the Enter Data
button is enabled.

PAGE 341
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

The user may now enter data into the various text fields. This program assumes a
number of things. These assumptions are listed as comments in the code listing.
This code listing follows over the next few pages.

This first section of code defines the account class that will contain the clients’
account information. Notice that this class is Serializable. Therefore we may
save it to some form of non-volatile memory. Read though this code. It really is
very simple.
// This class defines the account record.
// Notice that it is Serializable. Member
// methods allow for the "setting" and "getting" of
// instance variables.

import [Link];
import [Link].*;

public class AccountRecord implements Serializable{


//Instance data of record
private int accountNo;
private String fName;
private String lName;
private double balance;

public AccountRecord(){
this ("","",0,0.0);
}

public AccountRecord(String fName, String lName, int accountNo,


double balance){
[Link]=fName;
[Link]=lName;
[Link]=accountNo;
[Link]=balance;
}

public int size(){


// size of the account record.
return 72; //int = 4 +
//String * 2 = 30 +
//double = 8

PAGE 342
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

// -----
// ans in bytes = 72
}

public int getAccountNo(){


return accountNo;
}

public void setAccountNo(int i){


accountNo = i;
}

public String getFName(){


return fName;
}

public void setFName(String str){


fName = str;
}

public String getLName(){


return lName;
}

public void setLName(String str) {


lName = str;
}

public String getFullName(){


return (fName + " " + lName);
}

public void setAccountBalance(double amount) {


balance+=amount;
}

public double getAccountBalance() {


return balance;
}

// The method we will use to write our record to


// a random access file
public void write(RandomAccessFile aFile) throws IOException {
[Link](getAccountNo());
writeName(aFile, getFName());
writeName(aFile, getLName());
[Link](getAccountBalance());
}

// The purpose of this method is to ensure that we do not write more


// than 15 characters for the lName and fName quantities.
private void writeName(RandomAccessFile aFile, String names) throws IOException {
StringBuffer myBuffer = null;

if(names != null)
myBuffer = new StringBuffer(names);
else
myBuffer = new StringBuffer(15);

PAGE 343
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

[Link](15);
[Link]([Link]());
}
} // end of class

This next section of code defines the user interface. It is through an instance of this
class that a user will enter data that will be stored in an instance of the
AccountRecord class.

// The function of this class is to provide a user interface


// for entering account information.
// We may use in a number of different programs.
//**********************************************************
// Please NOTE: I could have written more efficient coding
// below, but I am wanting to show you certain principles.
// Please ensure that your coding is more efficient.
//**********************************************************
//

import [Link].*;
import [Link].*;

public class UserScreenRdmAccs extends JPanel {


protected static String[] LabelNames = {"Account No:", "First
Name:", "Last Name:","Balance Amount:"};
protected JLabel accLbl, fNameLbl, lNameLbl, amountLbl;
protected JTextField accTxt, fNameTxt, lNameTxt, amountTxt;
protected JButton choice1, choice2, choice3;
protected JPanel myPanel, myChoicePanel;
protected int noOfTextFields = 4;
public static final int accPos = 0, fNamePos = 1, lNamePos= 2,
amountPos = 3;

// The code following could be written more compact if we used


// arrays (i.e. declared a JLabel array and JTextField array above.)
// I have not done this so as to make it a little easier
// to read. In practice make your code more efficient please.
public UserScreenRdmAccs(){
// Instantiating labels
accLbl = new JLabel(LabelNames[accPos]);
fNameLbl = new JLabel(LabelNames[fNamePos]);
lNameLbl = new JLabel(LabelNames[lNamePos]);
amountLbl = new JLabel(LabelNames[amountPos]);

// Instantiating Text Fields


accTxt = new JTextField();
fNameTxt = new JTextField();
lNameTxt = new JTextField();
amountTxt = new JTextField();
myPanel = new JPanel();
// Changing the Panel layout manager from flow layout to Grid Layout
[Link](new GridLayout(5,2));

PAGE 344
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

// adding labels and Text Fields to the Panel


[Link](accLbl);
[Link](accTxt);
[Link](fNameLbl);
[Link](fNameTxt);
[Link](lNameLbl);
[Link](lNameTxt);
[Link](amountLbl);
[Link](amountTxt);

//Instantiating buttons
choice1 = new JButton("Choice 1");
choice2 = new JButton("Choice 2");
choice3 = new JButton("Choice 3");

// Assigning buttons to a new Panel


// Using the default layout manager
myChoicePanel = new JPanel();
[Link](choice1);
[Link](choice2);
[Link](choice3);

// Changing the layout for our 'main' Panel


// to the Border Layout and adding the two
// previously created Panels to it
setLayout(new BorderLayout());
add(myPanel, [Link]);
add(myChoicePanel, [Link]);
validate();
}

public JButton getChoice1Ref(){


return choice1;
}

public JButton getChoice2Ref(){


return choice2;
}

public JButton getChoice3Ref() {


return choice3;
}

public void clearTextFields() {


[Link]("0");
[Link]("");
[Link]("");
[Link]("0.0");
}

// This method returns a string array containing


// instance data of our record
public String[] getEntries() {
String[] entries = new String[noOfTextFields];
entries[accPos] = [Link]();
entries[fNamePos] = [Link]();
entries[lNamePos] = [Link]();

PAGE 345
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

entries[amountPos] = [Link]();

return entries;
}

}// end of class

This final section of code is our actual program. i.e. It contains the main() method.

// This is a main program to write data to a random access


// file. We make use of two of our previously created classes,
// namely AccountRecord and UserScreenRdmAccs classes. This program
// assumes a lot.
// 1) It assumes that the user will enter a certain amount of correct
// data via the interface.
// 2) A random access file of 100 blank records is already created.
// 3) The user will not enter duplicate account numbers. If (s)he
// does then the data is overwritten without warning.
// 4) Whenever the user closes the application the program attempts
// to write a record containing the current information contained
// in the UI screen

import [Link].*;
import [Link].*;
import [Link].*;
import [Link].*;

public class TestUI extends JFrame {


private RandomAccessFile randomFile = null;
private UserScreenRdmAccs myUI;
private JButton myOpen, mySave, myExit;
private JFrame myFrame;

public static void main(String[] args){


new TestUI();
}

private TestUI(){
myUI = new UserScreenRdmAccs();
// Assigning text and event handler to the first button in
// the UI
myOpen = myUI.getChoice1Ref();
[Link]("Save As ..");
[Link](new ActionListener(){
public void actionPerformed(ActionEvent ae){
openFile();
}
}
);

// Assigning text and event handler to the second button in


// the UI
mySave = myUI.getChoice2Ref();
[Link]("Enter Data");
[Link](false); //disabling the button (dimming it)
[Link](new ActionListener() {
public void actionPerformed(ActionEvent ae){

PAGE 346
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

addRecord();
}
}
);

// Assigning text and event handler to the third button in


// the UI
myExit = myUI.getChoice3Ref();
[Link]("Cancel");
[Link](new ActionListener() {
public void actionPerformed(ActionEvent ae) {
if (randomFile != null) {
addRecord();
closeOpenedFile();
}else{
[Link](0);
}
} // end actionPerformed()
} // end ActionListener()
); // end addActionListener()

// Instantiating a Frame and assigning it a window event handler


myFrame = new JFrame("Testing UI");
[Link](new WindowAdapter(){
public void windowClosing(WindowEvent we){
if (randomFile != null){
addRecord();
closeOpenedFile();
}else{
[Link](0);
}
} // end windowClosing()
} // end WindowAdapter()
); // end addWindowListener()

[Link]().add(myUI, [Link]);
[Link](300, 200);
[Link](true);
}

// This method id called when you are wishing to open a file. We make
// use of the JFileChooser defaulting it to look in the c:\Temp
// directory for the file we are wishing to open.
private void openFile(){
int result;
File fileName;

JFileChooser chooseFile = new JFileChooser("c:\\Temp");

[Link](JFileChooser.FILES_ONLY);
result = [Link](null);

if (result==JFileChooser.CANCEL_OPTION)
return;

fileName = [Link]();
if (fileName == null || [Link]().equals("")){
[Link](null, "Invalid File Name",

PAGE 347
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

"Invalid File Name", JOptionPane.ERROR_MESSAGE);


}else{
try{
randomFile = new RandomAccessFile(fileName, "rw");
[Link](true);
[Link](false);
[Link]("Exit");
String newTitle = [Link]() + " ( Saving to " +
fileName + " )";
[Link](newTitle);
}
catch (IOException e){
[Link](null, "File Does Not Exist",
"Invalid File Name",JOptionPane.ERROR_MESSAGE);
[Link](1);
}
} //end else
} // end openFile()

// This method writes our data to the opened file. Notice that the
// only form of error checking I am undertaking is to ensure that the
// account number entered by the user is greater than zero yet less
// than 100. This is because we are writing to a file that contains
// 100 blank records which we are wishing to fill.
private void addRecord() {
AccountRecord newAccount = new AccountRecord();
try{
String[] valuesEntered = [Link]();
int enteredAccNo = [Link](valuesEntered[[Link]]);
if (enteredAccNo >0 && enteredAccNo < 100){
[Link](enteredAccNo);
[Link](valuesEntered[[Link]]);
[Link](valuesEntered[[Link]]);
[Link]([Link]
(valuesEntered[[Link]]));

[Link]((enteredAccNo)* [Link]());
[Link](randomFile);
}
[Link]();
}
catch (NumberFormatException e){
[Link](null, "Invalid Entry","Invalid
Number Format",JOptionPane.ERROR_MESSAGE);
}
catch (IOException e) {
closeOpenedFile();
}
}// end of addRecord()

// This method ensures that the file we opened is correctly closed


private void closeOpenedFile(){
try{
[Link]();
[Link](0);
}
catch (IOException e){
[Link](this, "Error closing File",

PAGE 348
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

"ERROR", JOptionPane.ERROR_MESSAGE);
[Link](1);
}
} // end of closeOpenedFile()
}// end of class

Earlier it was stated in the comments that the program assumed a file had already
been created that contained one hundred blank records. The program to create this
file is listed below.

import [Link];
import [Link].*;
import [Link].*;

public class CreateRandomFile{


private AccountRecord blank;
private RandomAccessFile myFile;

public static void main(String[] args){


new CreateRandomFile();
}

public CreateRandomFile(){
blank = new AccountRecord();
openFile();
}

private void openFile() {


int result;
File fileName;

JFileChooser chooseFile = new JFileChooser();

[Link](JFileChooser.FILES_ONLY);
result = [Link](null);
if(result==JFileChooser.CANCEL_OPTION){
return;
}

fileName = [Link]();
if (fileName == null || [Link]().equals("")){
[Link](null, "Invalid File Name",
"Invalid File Name", JOptionPane.ERROR_MESSAGE);
}else{
try{
myFile = new RandomAccessFile(fileName, "rw");
for(int i=0;i<100;i++)
[Link](myFile);
[Link](0);
}
catch (IOException e){
[Link](null, "File Does Not Exist",
Invalid File Name",JOptionPane.ERROR_MESSAGE);
[Link](1);
}
}

PAGE 349
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

}
}

PAGE 350
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

THE JFC AND SWING


This is an extremely large section of Java. There are no fewer than 300 classes
used to build the graphical user interfaces (GUI’s) that users demand. What I shall
attempt to do is to teach you the components that have their equivalent
counterparts in the abstract window toolkit (AWT). Even though it is permissible
and possible to build GUI environments using the AWT, Sun Microsystems
recommend that programmers migrate across to using the Swing GUI components.
The reason for this is that the AWT has many platform idiosyncrasies when porting
an application across the various platforms. Swing is an attempt to overcome these
problems. Having said this though, some of the AWT is still widely used especially
in the areas of layout control and printing. There are other areas in which the swing
GUI components are far better than their AWT counterparts, for instance;

• Swing buttons and labels can display images instead of, or in addition to, text.
• You can easily add or change the borders drawn around most Swing
components. For example, it is easy to put a box around the outside of a
container or label.
• You can easily change the behavior or appearance of a Swing component by
either invoking methods on it or creating a subclass of it.
• Swing components don't have to be rectangular. Buttons, for example, can be
round.
• Swing lets you specify which look and feel your program's GUI uses. By
contrast, AWT components always have the look and feel of the native
platform.

The Java foundation classes (JFC) are classes designed specifically for enterprise-
ready software. This is an advanced topic and will be left for advanced courses. A
lot of the knowledge you have built up over the course will be called into play in
this section. For instance you must fully understand event handing as well as how
to program event handlers in order to create an interactive user environment.

What we are going to look at in a fair amount of detail, are the controls that
generate events. Because of the vastness of Swing and the limitation of time on the
course, only the basics will be presented here. I encourage you to make a huge
effort in doing extra studying and reading to grasp this fascinating and visually
rewarding aspect of Java. Swing components can be used in stand-alone programs
as well as in Java applets. Throughout this section you will use both environments
in order that you may begin to feel comfortable using both. Whenever you use

PAGE 351
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

Swing components you must include the following line, which results in the main
Swing package being imported;
import [Link].*;

You will also find that most programs using swing will need the two main AWT
packages to be imported;
import [Link].*;
import [Link].*;

Let us briefly look at the structure of a Swing component. A Swing component can
be a button, a scrollbar, a text field etc. Now every component has three
characteristics;
1. Contents. This is the content of the component. i.e. The text in a text box,
whether the button is pressed or not.
2. Appearance. This is the components size, shape color etc.
3. Behavior. This is how the component will respond to an event i.e. how will a
button will respond when it is pressed.

Before you can use a Swing component it must be added to a container. Every
single program must contain at least one top-level container. Commonly used top-
level containers are instances of frames (JFrame), dialogs (JDialog) for stand-
alone programs and JApplet for applets.

Next there are the intermediate containers. Their only purpose is to simplify the
positioning of the components such as buttons and labels. Intermediate Swing
containers are panels (JPanel), panes (JScrollPane) and tabbed panes
(JTabbedPane). Some of the intermediate containers play a more visible,
interactive role in a program's GUI such as panes.

Finally there are the atomic components such as buttons and labels. These
components do not hold other Swing components, but are self-sufficient entities
that present bits of information to the user. Often, atomic components also get input
from the user. The Swing API provides many atomic components, including combo
boxes (JComboBox), text fields (JTextField), and tables (JTable).

It is important to remember that even the simplest Swing program has multiple
levels in its containment hierarchy. The root of the containment hierarchy is always
a top-level container. The top-level container provides a place for its descendent
Swing components to paint themselves.

PAGE 352
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

So even the simplest of applications will have a containment hierarchy something


like the following;

JFrame root - top level

other layers

Add components to
this. Default layout
Content Pane
manager is the
border layout.

JPanel

Atomic Component Atomic Component Atomic Component


i.e. JTextField i.e. JList i.e. JButton

Every top-level container indirectly contains an intermediate container known as a


content pane. This content pane contains all the visible and non-visible
components, with the exception of the menu bar. This is part of the top-level
container. This root also has a JGlassPane, which layers over everything and
allows you to intercept mouse events and even to draw over the whole container
without getting distracted by the components within it. There is also a JLayered
pane that manages the menu bar and content pane. Below is a diagram that will
hopefully make the discussion clearer.

PAGE 353
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

JFrame JApplet JDialog

"Has a"

"Has a" JLayeredPane

JMenuBar
JRootPane

JContentPane
JGlassPane

To add a component to a container, you use one of the various forms of the add()
method.

The syntax for adding a component to a container in a stand-alone application is as


follows;
:
:
JFrame myFrame = new JFrame();
:
[Link]().add(aComponentOrSomething);
:

PAGE 354
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

The syntax for adding a component to a container in a JApplet panel is as follows;


public void init(){
:
[Link]().add(aComponentOrSomething);
:
}

What you will do frequently is to add components to a container such as a panel


(JPanel) and then add this to the top-level container such as JFrame or JApplet.

To effectively use Java’s GUI capabilities to the utmost it is up to you to fully


understand the Component, Container and JComponent classes. Go and study
these classes in the Java documentation.

Java uses layout managers to arrange GUI (Graphics User Interface) components
on a container. Each container object has a layout manager associated with it. This
associated layout manager is that containers default layout manager. Should one
not wish to use the default layout manager, it is a simple task of specifying which
layout manager you would like to associate with the container. This is done by
invoking the setLayout() method in the container class. You will see examples of
this as we migrate through the section on Swing.

Java has a number of layout managers. There is the FlowLayout, BorderLayout,


GridLayout, BoxLayout, CardLayout, GridBagLayout a custom layout manager
and absolute positioning. There is not room to fully discuss all these types of
managers, so I encourage you to look at the Java documentation and study these
classes. What I will do is very briefly discuss the first three layout managers.

FlowLayout
This is the simplest of layout managers and is the default layout manager for the
JPanel container. In this layout manager components are laid out from the upper
left corner and from left to right. When the edge of the container is reached then the
components are sent to the next line, once again being placed from left to right.

To add components to a container managed by FlowLayout, you could use one of


the add() methods. The order in which the components appear is determined by
the order of the add() calls. You will see this in the code to come when we start
discussing some of the swing components.

The class FlowLayout allows you to customise, at construction time, how the
components will appear on the container. These can be;

PAGE 355
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

[Link] (the default)


[Link]
[Link]

The alignment of the components can also be changed by calling the


setAlignment() method of FlowLayout with one of the same alignment
constants. You may also customise the space between each of the components
horizontally and vertically. This is accomplished by invoking the methods;
void setHgap(int hgap) // Sets the horizontal gap between
// components.
void setVgap(int vgap) // Sets the vertical gap between
// components.

For more on this layout manager go and study the Java documentation.

An example of the FlowLayout manager in operation.

PAGE 356
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

BorderLayout
BorderLayout is the default layout manager for every content pane (i.e. a
JFrame). What the BorderLayout manager does is to allow for components to be
laid in a container in five different regions. The components are resized and
arranged to fit into these areas. A graphical representation is shown below;

As can be seen from the above diagram each region is identified by constant:
NORTH, SOUTH, EAST, WEST, and CENTER. When adding a component to a container
with a border layout, you make use of one of these five constants. You can either
add a component directly to these areas, or add components to a JPanel and then
add the JPanel to one of the regions. You will see this when we look at swing’s
radio buttons. You will see that the radio buttons and label are contained within a
JPanel which are then placed in one of the regions. The images on the other hand,
we place directly into one of the regions. This is what most programmers use when
prototyping; they use a combination of JPanels and the BorderLayout manager.
Below is a snippet from our demonstration program on radio buttons, which you
will see later, demonstrating the use of the BorderLayout manager;
setLayout(new BorderLayout());
add(labelPanel, [Link]);
add(radioPanel, [Link]);
add(picture, [Link]);
add(picture2, [Link]);
setBorder([Link](1,20,20,20));

Notice the last line above. This code applies a blank border (an EmptyBorder)
around the five regions generated by BorderLayout(). The parameters are top,
left, bottom, right and indicate the pixel thickness of the blank border at these
locations. For instance the top of the blank border is one pixel thick whereas all the

PAGE 357
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

other blank borders are twenty pixels thick. Using various techniques such as
borders etc make the user interface much more aesthetically pleasing.

There are times when you would like to leave a small amount of space between the
container that holds your components and the window that contains it. To do this
you need to invoke getInsets() method. This method returns an Insets object.
You pass the top, left, bottom, right values as follows;
// overriding getInsets
public Insets getInsets(){
return new Insets(10,10,10,10);
}

GridLayout
GridLayout lays out its components in a grid. Each component is given the same
size and is positioned left-to-right, top-to-bottom.

The code to generate the above GridLayout is shown below;

PAGE 358
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

import [Link].*;
import [Link].*;

public class GridLayoutDemo extends JFrame{


public static void main(String[] args){
int rows = 4, cols = 4;

JFrame myFrame = new JFrame("GridLayout Demo");


GridLayout myGrid = new GridLayout(rows,cols);

[Link]().setLayout(myGrid);
[Link](new Font("SansSerif", [Link], 24));

for(int i = 0; i <rows; i++)


for(int j = 0; j < cols; j++){
int k = i*cols + j;
if (k>0)
[Link]().add(new Button(" " + k));
}
[Link]();
[Link](true);
}
}

A few aspects to note about this code. Notice how I have changed the default
layout manager of the JFrame from being the BorderLayout manager to the
GridLayout manager. Each button is placed from left to right, top to bottom.

I would really encourage you to go and study the layout managers discussed above
and the others that were simply mentioned. By understanding the strengths and
weaknesses of each, will allow you to develop powerful, professional looking GUI
interfaces.

Below is the code that adds a label (which is an atomic component) to a panel, and
then adds the panel to the content pane, which I have called MyFrame;

import [Link].*;
import [Link].*;

public class SimpleContainer{


public static void main(String[] args){
JPanel myPanel = new JPanel();
JFrame myFrame = new JFrame("VZAP Frames");
JLabel myLabel = new JLabel("One cup of Java and some Irish Mist please.");

[Link](myLabel);
[Link]().add(myPanel);
[Link](); // this automatically sizes the frame. We could use
// setSize(x, y);
[Link](true); // We need to make the frame (top level
// container visible. By default it is not

PAGE 359
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

// visible.
}
}

The output looks like this;

The line bolded adds the container (that has the label) to the top-level container
myFrame. Please note that this is an extremely simple example and is here to
convey a concept. There should be at least some code to handle window closing.

Almost the whole of windows programming is learning about controls. Virtually all
the components are subclasses of the abstract class JComponent. This
JComponent class is the superclass that holds the common information about on-
screen control and provides higher level features common to each control. There is
a lot in this class and it would be a good idea to peruse the Java documentation.
The behavior and appearance of each specific control is one level down from the
JComponent class. So remember, components correspond to “things that interact
with the user” and containers are the “backdrops to put them on”

Let us now start looking at some atomic components. We shall begin simply, then
as we move on, our example programs will become a little more functional. It is
important that you study the documentation on each one of these components. It is
just not sensible to add all the methods, constants etc to this document.

PAGE 360
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

Labels
JLabel
An instance of JLabel is one of the simplest of Java components. It allows you to
display either text, an image (a GIF or JPEG file), or both. You can specify where in
the label's display area the label's contents should be i.e. LEFT, RIGHT or CENTER
aligned. You can also determine the vertical alignment. By default, labels are
vertically centered in their display area. By default, text-only labels are leading
edge aligned and image-only labels are horizontally centered.

Labels are unable to generate events. You are however allowed to set the text in the
label using the setText() method, as well as receive text using the getText()
method. Let us now look at a program that will produce the following output;

The coding follows. Notice how I have included some window event handling,
which you should know by now.
import [Link].*;
import [Link].*;
import [Link].*;

public class LabelTest {


static public void main(String[] args){
// lets get the image we want
ImageIcon myImageIcon = new ImageIcon("[Link]");

//Now let us create the label and add the image to it


JLabel myLabel = new JLabel("More Java but NO more Port Please",
myImageIcon, [Link]);

//Let us now create a frame


JFrame myFrame = new JFrame("My First Label with an Image. ");

//Now add the event listener


MyHandlerClass myWinHandler = new MyHandlerClass();
[Link](myWinHandler);

//Now add the label with picture to the frame i.e. top-level container
[Link]().add(myLabel);

//let us now automatically size the frame


[Link]();
[Link](true);
}

PAGE 361
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

// Our event handling class to handle window closure


class MyHandlerClass extends WindowAdapter{
public void windowClosing(WindowEvent e){
[Link](0);
}
}

Notice that we rely on myFrame being set automatically to its correct size. This is
done by invoking the pack() method. By default, all frames are not visible. We
therefore need to make them visible by invoking the setVisible() method
passing it an argument value of true. Work through this code and understand it as
it forms the basis for the rest of this section on Swing.

PAGE 362
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

Buttons
JButton
We have seen this control already, especially when we were looking at event
handling. To demonstrate a few more features of the JButton class the code below
allows one to either press the button or press the Alt-I (or ALT-i) key
combination called a mnemonic key combination in order to increment a counter.
Try it, it does work. Notice too that I have added an icon to the button. The unusual
code I have placed in bold. The output of this code looks as follows after pressing
ALT-I (and ALT-i) as well as pressing the button;

It is also possible to disable a button (i.e. gray it) by using the


setEnabled(false) method and then re-enabling it by using the
setEnabled(true) method. I have not shown the one line of code to do this but
the results are shown in the screen capture below. I am sure you can work it out. If
the button is disabled you will not be able to increment the count by either using
the mouse or the mnemonic key stoke. The only way to restart counting is to re-
enable the button.

Button is disabled.
That is why it is
grayed.

import [Link].*;
import [Link].*;
import [Link].*;

public class MyCounter{


public static void main(String[] args){
myFrameSetup();
}

public static void myFrameSetup(){


JFrame myFrame = new JFrame("Counting (Use Mouse or ALT-I key)");
MyIconButton myICB = new MyIconButton();

[Link]().add(myICB);
[Link]();
[Link](true);

WindowListener myWinListener = new WindowAdapter(){

PAGE 363
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

public void windowClosing(WindowEvent e){


[Link](0);
}
};
[Link](myWinListener);
}
}

//******************************************************************************
class MyIconButton extends JPanel{
private int counter = 0;
private static String countLabel = "The count is now: ";

public MyIconButton(){
//let us get the image
ImageIcon myImage = new ImageIcon("[Link]");

//let us create the button and a key event for ALT-I


JButton myCountButton = new JButton("Press me to count", myImage);
[Link](KeyEvent.VK_I);

//let us create a label that cannot be overridden. I add some space to the end here so
//when we call pack() the frame will size slightly larger in order that the large count
//values will be displayed. Experiment by removing the space and see what I mean
final JLabel myLabel = new JLabel(countLabel + counter + " ");

//let us add the button and label to the panel


add(myCountButton);
add(myLabel);

//write an event handler


[Link](new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
counter++;
[Link](countLabel + counter);
}
}
);
}
}

Notice how I have divided up the program into classes and methods. This is what
you must also attempt to do.

PAGE 364
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

Tool Tips
JToolTip
This is so easy to implement that you have no excuse not to use it. Tool tips is
declared in the JComponent class and is inherited by most Swing components. Its
function is to provide the user with tips when the mouse pointer moves over a
component and remains there a few moments. When the mouse moves away, or the
mouse is stationary for a while, it then disappears. For each component you can
assign a tool tip. In our example we are just assigning one to the only component,
the button.

This pops up when


the mouse moves
over the button.

The code is below and the single line that adds the tool tip to the button is
highlighted.
import [Link].*;
import [Link].*;
import [Link].*;

public class MyToolTip{


public static void main(String[] args){
myFrameSetup();
}

public static void myFrameSetup(){


JFrame myFrame = new JFrame("Tool Tips.");
MyButton myB = new MyButton();

[Link]().add(myB);
[Link](220,80);
[Link](true);

WindowListener myWinListener = new WindowAdapter()


{
public void windowClosing(WindowEvent e)
{
[Link](0);
}
};
[Link](myWinListener);
}
}

//*******************************************************************
class MyButton extends JPanel{
public MyButton(){
JButton myButton = new JButton("Press me Exit");

PAGE 365
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

//add a tool tip to the button


[Link]("Have a cup of Java");

//add button to the panel


add(myButton);

//write an event handler


[Link](new ActionListener(){
public void actionPerformed(ActionEvent e){
[Link](0);
}
}
);
}
}

PAGE 366
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

Check Boxes
JCheckBox
All the characteristics mentioned under the JButton section also apply to the check
box. You can also specify images to be in a check box. A check box is an atomic
component that represents a boolean choice. In other words a check box may be in
one of two states, selected or not selected. These are useful as they allow a user to
select what they want. Below is a fun example of using check boxes. The .GIF
files I got from Sun. I also made reference to their demo as it really does give you a
feel of the usefulness of check boxes. By selecting various check boxes you can
“build” your own cartoon character. Below are a few screen captures. The code
follows and the code relevant to check boxes is highlighted. It is straight forward;

import [Link].*;
import [Link].*;
import [Link].*;

public class CheckBoxCartoon extends JPanel{


JCheckBox chinButton;
JCheckBox glassesButton;
JCheckBox hairButton;
JCheckBox teethButton;

StringBuffer choices;
JLabel pictureLabel;

public CheckBoxCartoon(){
// Create the check boxes
chinButton = new JCheckBox("Chin");
[Link](false);

glassesButton = new JCheckBox("Glasses");


[Link](false);

hairButton = new JCheckBox("Hair");


[Link](false);

teethButton = new JCheckBox("Teeth");


[Link](false);

// Register a listener for the check boxes.


CheckBoxListener myListener = new CheckBoxListener();
[Link](myListener);

PAGE 367
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

[Link](myListener);
[Link](myListener);
[Link](myListener);

// Indicates what's on the geek.


choices = new StringBuffer("----");

// Set up the picture label


pictureLabel = new JLabel(new ImageIcon( "geek-" + [Link]()+ ".gif"));
[Link]([Link]());

// Put the check boxes in a column in a panel


JPanel checkPanel = new JPanel();
[Link](new GridLayout(0, 1));
[Link](chinButton);
[Link](glassesButton);
[Link](hairButton);
[Link](teethButton);

setLayout(new BorderLayout());
add(checkPanel, [Link]);
add(pictureLabel, [Link]);
setBorder([Link](20,20,20,20));
}

//************************************************************************
/** Listens to the check boxes. */
class CheckBoxListener implements ItemListener {
public void itemStateChanged(ItemEvent e) {
int index = 0;
char c = '-';
Object source = [Link]();

if (source == chinButton){
index = 0;
c = 'c';
}
else if (source == glassesButton){
index = 1;
c = 'g';
}
else if (source == hairButton) {
index = 2;
c = 'h';
}
else if (source == teethButton) {
index = 3;
c = 't';
}
if ([Link]() == [Link])
c = '-';

[Link](index, c);
[Link](new ImageIcon( "geek-" + [Link]()+ ".gif"));
[Link]([Link]());
}
}

public static void main(String s[]){


JFrame frame = new JFrame("Cartoon Builder");

PAGE 368
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

[Link](new WindowAdapter() {
public void windowClosing(WindowEvent e) {
[Link](0);
}
});

[Link](new CheckBoxCartoon());
[Link]();
[Link](true);
}
}

You should have noticed that there is a GridLayout class. This is used to layout
the components on a container. We shall discuss this later in this section. Can you
work out the code above? Notice how we “build” the name of the .GIF file using an
instance of StringBuffer. Notice too that all the check boxes are initially set
unchecked.

PAGE 369
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

Radio Button.
JRadioButton
Radio buttons are very much like check boxes. Radio buttons got their name from
the channel select buttons on the old car radios. Only one of these buttons were
able to be depressed at any time. The same applies to their software equivalent
where only one of the buttons is allowed to be selected at one time. This is where
they differ from check boxes where any number of the boxes may be selected at
any one time. What you need to do to ensure that only one button is selected, is to
group any number of radio buttons together in a CheckBoxGroup object. When you
add the buttons to the CheckBoxGroup the actual methods in the CheckBoxGroup
class will ensure that only one button at any one time is selected.

In the code I have written below there is much we can learn, not only about radio
buttons but also about fonts, grid layouts etc. I shall very briefly discuss them. A
screen snap shot of the program follows;

You will see that in this example there are two radio button groups. The one group
will allow a user to select what liqueur would go well with the cup of Java that is
about to be consumed. The other radio button group allows the user to select what
morsel will complement the whole experience. I know that I have not allowed for
the possibility of a user not wanting any of the possible selection, “..but in my wine
and cigar lounge I have never had anyone say no!..”. The code is listed below;

PAGE 370
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

import [Link].*;
import [Link].*;
import [Link].*;
import [Link].*;

public class JavaRadioButton extends JPanel {


static JFrame frame;

static String portString = "Port";


static String dramString = "Drambui";
static String irishString = "Irishmist";

static String pieString = "Pie";


static String donutString = "Donut";
static String cakeString = "cake";

JRadioButton portButton;
JRadioButton dramButton;
JRadioButton irishButton;
JRadioButton pieButton;
JRadioButton donutButton;
JRadioButton cakeButton;

JLabel picture, picture2;

Border raisedbevel;

public static void main(String s[]) {


frame = new JFrame("Hmm, What should I have?");
[Link](new WindowAdapter() {
public void windowClosing(WindowEvent e) {
[Link](0);
}
});

[Link]().add(new JavaRadioButton(), [Link]);


[Link]();
[Link](true);
}

public JavaRadioButton() {
// Create the radio buttons.
portButton = new JRadioButton(portString);
[Link](KeyEvent.VK_P);
[Link](portString);
[Link](true);

dramButton = new JRadioButton(dramString);


[Link](KeyEvent.VK_D);
[Link](dramString);

irishButton = new JRadioButton(irishString);


[Link](KeyEvent.VK_I);
[Link](irishString);

pieButton = new JRadioButton(pieString);


[Link](KeyEvent.VK_E);
[Link](pieString);
[Link](true);

donutButton = new JRadioButton(donutString);


[Link](KeyEvent.VK_O);
[Link](donutString);

cakeButton = new JRadioButton(cakeString);


[Link](KeyEvent.VK_C);
[Link](cakeString);

// Group the radio buttons.


ButtonGroup group = new ButtonGroup();
[Link](portButton);
[Link](dramButton);

PAGE 371
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

[Link](irishButton);

ButtonGroup group2 = new ButtonGroup();


[Link](pieButton);
[Link](donutButton);
[Link](cakeButton);

// Register a listener for the radio buttons.


RadioListener myListener = new RadioListener();
[Link](myListener);
[Link](myListener);
[Link](myListener);
[Link](myListener);
[Link](myListener);
[Link](myListener);

// Set up the picture label


picture = new JLabel(new ImageIcon(portString + ".gif"));
picture2 = new JLabel(new ImageIcon(pieString + ".gif"));

// The preferred size is hard-coded to be the width of the


// widest image and the height of the tallest image.
// A real program would compute this.
[Link](new Dimension(100, 100));
[Link](new Dimension(100, 100));

JPanel labelPanel = new JPanel();


JLabel myLabel = new JLabel("Please select what you would like with your cup of Java");
Font f = new Font("SansSerif", [Link], 16);
[Link](f);
[Link]([Link]);
raisedbevel = [Link]();
[Link](raisedbevel);
[Link](myLabel);

// Put the radio buttons in a column in a panel


JPanel radioPanel = new JPanel();
[Link](new GridLayout(0, 1));
[Link](portButton);
[Link](dramButton);
[Link](irishButton);
[Link](pieButton);
[Link](donutButton);
[Link](cakeButton);

setLayout(new BorderLayout());
add(labelPanel, [Link]);
add(radioPanel, [Link]);
add(picture, [Link]);
add(picture2, [Link]);
setBorder([Link](1,20,20,20));
}

/** Listens to the radio buttons. */


class RadioListener implements ActionListener{
public void actionPerformed(ActionEvent e){
Object source = [Link]();
if ((source == portButton) || (source==dramButton) || (source==irishButton)) {
[Link](new ImageIcon("" + [Link]() + ".gif"));
}
else if (source == pieButton || source==donutButton || source==cakeButton) {
[Link](new ImageIcon("" + [Link]() + ".gif"));
}
}
}
}

Let us now look a little at this code. Firstly we assign to a constant a string that we
shall use when declaring the radio buttons and what the text next to them, on the
screen should be. The code to do this is;

PAGE 372
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

static String portString = "Port";


static String dramString = "Drambui";
static String irishString = "Irishmist";

static String pieString = "Pie";


static String donutString = "Donut";
static String cakeString = "cake";

This is good practice. If we needed to change what appears on the screen, we need
only do it here. For instance, if we only have Apple Pies then we could change
“Pie” to “ApplePie”, recompile and the next time the program is run this change is
visible. However, in our program this string is ALSO used to construct the name of
the .GIF file that we want to retrieve. So if you change this string, make sure that
other aspects of your code is not impacted upon, as ours is. Next we actually
declare the radio button variables. This you should know by now.

We than create instances of radio buttons. The code below just shows the creation
of the port radio button.
portButton = new JRadioButton(portString);
[Link](KeyEvent.VK_P);
[Link](portString);
[Link](true);

Notice that each one of the radio buttons also have been assigned a short cut key.
This is not difficult to implement. You use the same method used for other
components. We then set the command name for the action event fired by this
button. By default, this action command is set to match the label of the radio
button. A string is used to set the button's action command. If the string is null
then the action command is set to match the label of the button.

By default, radio buttons are not selected. So you should explicitly set one per radio
group as being active. This we did in our code by making the port button active in
the one radio button group and the pie button active in the other radio button group.

To assign each button to a radio button group we first have to create a new radio
button group. Once this is done we then assign the required buttons to this group.
The code to do this follows. I am only showing the creation of the one group.
ButtonGroup group = new ButtonGroup();
[Link](portButton);
[Link](dramButton);
[Link](irishButton);

We then assign the event handler that will handle any event generated by the radio
buttons. This you should understand by now;
RadioListener myListener = new RadioListener();

PAGE 373
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

[Link](myListener);
[Link](myListener);
[Link](myListener);
[Link](myListener);
[Link](myListener);
[Link](myListener);

Remember earlier we used a label that contained a picture? Well we do the same in
this code. What we do is to get the string we created right at the beginning of the
program and we then append “.GIF” to the end of it. We then retrieve the image
using ImageIcon() and then pass the picture to the JLabel we called picture
and picture2. We assign a default picture that corresponds to the two radio
buttons that we explicitly enabled. This is so that we ensure that the program is
starting in a known state. The code is shown below.
picture = new JLabel(new ImageIcon(portString + ".gif"));
picture2 = new JLabel(new ImageIcon(pieString + ".gif"));

Notice that had we changed the pieString at the beginning of our code to
“ApplePie” and there was no image called [Link] then no image would
have been displayed. We then set a default size for the display area of the picture. If
the picture is too big for the display area then it would be clipped.

The code to do this is;


[Link](new Dimension(100, 100));
[Link](new Dimension(100, 100));

As the comment in the code says, this type of aspect in a program is normally
calculated real time. We next add the components to a panel so that they may be
displayed in a container. You know how to do this now.
JPanel radioPanel = new JPanel();
[Link](new GridLayout(0, 1));
[Link](portButton);
[Link](dramButton);
[Link](irishButton);
[Link](pieButton);
[Link](donutButton);
[Link](cakeButton);

Remember from our brief discussion on layout managers earlier, we said that when
adding a component to a container with a border layout, you make use one of the
five constants NORTH, SOUTH, EAST, WEST, and CENTER. You can either add a
component directly to these areas, or add components to a JPanel and then add the
panel to one of the regions. In our example we have done both. Our radio buttons
and label are contained within a JPanel which are then placed in one of the
regions. The images on the other hand we place directly into one of the regions.
Our code that uses the BorderLayout manager is;

PAGE 374
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

setLayout(new BorderLayout());
add(labelPanel, [Link]);
add(radioPanel, [Link]);
add(picture, [Link]);
add(picture2, [Link]);
setBorder([Link](1,20,20,20));

Notice the last line above. This code applies a blank border (an EmptyBorder)
around the five regions generated by BorderLayout(). The parameters are top,
left, bottom, right and indicate the pixel thickness of the blank border at these
locations. For instance the top of the blank border is one pixel thick whereas all the
other blank borders are twenty pixels thick.

Finally in our code we have our event handler. You should understand all the code
in it from our earlier discussion on event handlers. Notice how we once again build
the filename for the .GIF images and then place them into the correct
BorderLayout() region.

class RadioListener implements ActionListener{


public void actionPerformed(ActionEvent e){
Object source = [Link]();
if ((source == portButton) || (source==dramButton) || (source==irishButton)){
[Link](new ImageIcon("" + [Link]() + ".gif"));
}
else if (source == pieButton || source==donutButton || source==cakeButton){
[Link](new ImageIcon("" + [Link]() + ".gif"));
}
}
}

There are a few lines of code we have not discussed, these are;
import [Link].*;
:
Border raisedbevel;
:
Font f = new Font("SansSerif", [Link], 16);
[Link](f);
[Link]([Link]);
raisedbevel = [Link]();
[Link](raisedbevel);

They are to do with the font being displayed in the label and the border around the
label. Go and study the Font class. I am sure that you can understand the Font
code. We shall discuss the border code in a following section.

PAGE 375
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

Text Boxes and Layouts


JTextComponent
This is an area on the screen in which text is able to be displayed and may be
enabled for a user to enter a line or more of text. The hierarchy of the text
components looks as follows;

JTextComponent

JTextField JTextArea JEditorPane

JPasswordField JTextPane

Text Controls Plain Text Areas Styled Text Areas

The text controls, JTextField and JPasswordField, are areas on the screen that
will allow a user to enter or edit only one line of text. They are used to receive only
a small amount of text from the user such as passwords, user name etc.

The plain text area, JTextArea, is an area on the screen that can display and edit
multiple lines of text. This text area can display any font, but all the text will be in
that font. This type of text area is used to allow a user to enter or display any length
of unformatted help information.

The last form of text areas, styled text areas, JEditorPane and JTextPane, is
capable of displaying and editing text which contains any number of different fonts.
It is also possible to embed images and even embed components.

As this is an introductory course in Java I shall only demonstrate text controls,


JTextField and JPasswordField, and plain text areas, JTextArea. Generally,
styled text areas require a lot more up-front programming. Having said this, the
code below is relatively complex in that I am using GridBagLayout manager. The
rest of the code is straightforward. I included the GridBagLayout into the code as
an appetizer to show you what you are capable of doing in controlling the look of a
UI. Discussion of GridBagLayout would be best left for a more advanced course.
Suffice to say that a very shallow explanation on using GridBagLayout follows
after the code listing. I encourage you to peruse what is in the code, hopefully

PAGE 376
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

encouraging you to delve a little deeper in studying it on your own. Below are snap
shots of the program in operation;

The code to achieve all this is;


import [Link].*;
import [Link].*;
import [Link].*; //for layout managers
import [Link].*; //for action and window events

public class myTextDemo extends JPanel {


static JFrame myFrame;

protected static final String textString = "textString";


protected static final String pswdString = "pswdString";

JTextField myTextField;
JPasswordField myPassField;
JTextArea myTextArea;
JLabel myLabel;
JLabel myPassLabel;
protected JLabel myActionLabel;

public static void main(String[] args) {


myFrame = new JFrame("Oh what lovely text.");

[Link]().add(new myTextDemo(), [Link]);


[Link]();
[Link](true);

[Link](new WindowAdapter() {
public void windowClosing(WindowEvent e) {
[Link](0);
}
});
}

public myTextDemo(){
//setting up the label and text field
myLabel = new JLabel("Enter your name");
myTextField = new JTextField(10);
[Link](textString);

PAGE 377
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

//setting up the password label and password field


myPassLabel = new JLabel("Enter your password");
myPassField = new JPasswordField(10);
[Link](pswdString);

//setting up the editable text area specifying its font


//and word wrapping policy.
myTextArea = new JTextArea("Modify this great poem:\n\nRoses are Red,\nViolets
are Blue,\nOne cup of Java\nand some Chivers to.");
[Link](new Font("Roman", [Link], 14));
[Link](true);
[Link](true);

//setting up a scroll bar to be attached to the text area.


//Also setting up the border style
JScrollPane areaScrollPane = new JScrollPane(myTextArea);
[Link](JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
[Link](new Dimension(200, 200));
[Link]([Link](
[Link](
[Link]("PlainText"),
[Link](5,5,5,5)),
[Link]()));

TextListener myTL = new TextListener();


[Link](myTL);
[Link](myTL);

myActionLabel = new JLabel("Type Text and then press RETURN in a field");


[Link]([Link](10,0,0,0));

JPanel myPanel = new JPanel();

//I am using a different layout manager here called GridBagLayout


//It is the most complex of all the layout managers. Peruse what
//I have here and then study other material on it. It can be quite heavy
GridBagLayout myGridLayout = new GridBagLayout();
GridBagConstraints c = new GridBagConstraints();

[Link](myGridLayout);

JLabel[] labels = {myLabel, myPassLabel};


JTextField[] fields = {myTextField, myPassField};

addLabelTextRows(labels, fields, myGridLayout, myPanel);

[Link] = [Link];
[Link] = [Link];
[Link] = 1.0;

[Link](myActionLabel,c);

[Link](myActionLabel);
[Link]([Link](
[Link]("Text Fields"),
[Link](5,5,5,5)));

setLayout(new BorderLayout());
add(myPanel, [Link]);
add(myActionLabel, [Link]);
add(areaScrollPane, [Link]);

PAGE 378
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

private void addLabelTextRows(JLabel[] labels,


JTextField[] textFields,
GridBagLayout gridbag,
Container container){
GridBagConstraints c = new GridBagConstraints();
[Link] = [Link];
int numLabels = [Link];
for (int i = 0; i < numLabels; i++){
[Link] = [Link];
[Link] = [Link];
[Link] = 0.0;
[Link](labels[i], c);
[Link](labels[i]);

[Link] = [Link];
[Link] = [Link];
[Link] = 1.0;
[Link](textFields[i], c);
[Link](textFields[i]);
}
}

//************************************************************************
class TextListener implements ActionListener{
public void actionPerformed(ActionEvent e){
if ([Link]().equals(textString)){
JTextField source = (JTextField)[Link]();
[Link]("Your Name is \"" + [Link]() +"\"");
}
else{
JPasswordField source = (JPasswordField)[Link]();
[Link]("Your password is \"" +
new String([Link]()) +"\"");
}
}
}
}

The GridBagLayout manager allows you to specify the position of your controls
more exactly then any of the other types of Layout managers. In the code above we
create a new GridBagLayout manager as follows;
GridBagLayout myGridLayout = new GridBagLayout();

To control the way you wish to arrange your controls within myGridLayout (which
is an instance of GridBagLayout) you make use of an instance of the class
GridBagConstraints. We created an instance of GridBagConstraints in our
code as follows;
GridBagConstraints c = new GridBagConstraints();

We then assigned our instance of GridBagLayout to our JPanel, myPanel. This is


done as follows;
[Link](myGridLayout);

PAGE 379
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

Those are basically the steps required to generate a GridBagLayout. The next
important step is to begin specifying exactly how you wants your controls to be
placed or “constrained” within your instance of GridBagLayout. The laying out of
components work with the relative “weights” of controls in the x and y position. So
for example, all buttons that have the same width will then have the same x weight.
To specify these weights, you make use of two methods found in the
GridBagConstraints class, weightx() and weighty(). The code that lays out
all the components is found in the member method addLabelTextRows() of the
myTextDemo class. It is listed below;

private void addLabelTextRows(JLabel[] labels,


JTextField[] textFields,
GridBagLayout gridbag,
Container container){
GridBagConstraints c = new GridBagConstraints();
[Link] = [Link];
int numLabels = [Link];

for (int i = 0; i < numLabels; i++){


[Link] = [Link];
[Link] = [Link];
[Link] = 0.0;
[Link](labels[i], c);
[Link](labels[i]);

[Link] = [Link];
[Link] = [Link];
[Link] = 1.0;
[Link](textFields[i], c);
[Link](textFields[i]);
}
}

Remember one thing however. These text fields return Strings from the input. If
we are wanting a user to enter a number we need to convert these strings into the
number required. For example if you are wanting the user to enter an integer, your
code needs to convert this string “number” into an integer. Remember the primitive
data types wrapper classes? Well, we make use of them. To perform this
conversion your code would look something like the following;
int myNum = [Link]([Link]().trim());

There may still be a problem here (by the way). What happens if you request a user
to enter an integer value but the user decides to enter some alpha characters? You
will then receive a run-time error after the above statement attempts to execute. We
need to do some form of input validation. Again, effective input validation is rather
complex. If you ever start using visual Java tools you will generally find excellent
classes that will provide you with this input validation functionality.

PAGE 380
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

PAGE 381
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

List Boxes
JListBox
A List Box is very similar to check boxes and radio buttons. The difference is that
all the items are contained inside a single box. A user may make a selection of an
item by clicking on a highlighted item. It is also possible for the user to make
multiple selections. This is the default. To determine whether a user may make a
single or multiple selection, you use an instance of the ListSelectionModel to
manage the selection. The constants this class defines are SINGLE_SELECTION,
SINGLE_INTERVAL_SELECTION and MULTIPLE_INTERVAL_SELECTION. One thing
to note is that a list box does not scroll automatically, you must program this
functionality in. In the example below, the scroll bars appear as you resize the
window. When the user selects an item, there are numerous events that occur. For
example; mouse clicking, mouse dragging, deselection of an old item, etc. Now all
these events that we may not really be interested in can be processed by a method
called isAdjusting(). You will see this in the code below. This method returns
a true if the selection is not yet final. If you are not interested in these transitional
events then you need to wait until the event you are waiting for results in this
method returning a false. Peruse the code below to see an example of how I am
using this method to process the event I am interested in
(getValueIsAdjusting()).

The code in this program can be improved by, in that, instead of hard coding the
names of the .JPG files into the code, you could use a resource file containing the
file names. When the program starts, then the image list in the resource file should
be held in an instance of the Vector class. I would strongly recommend that you
attempt to do this. A Vector class is very similar to an array. The difference is that
the size of an array may not change once it has been set, whereas vectors are array
like objects that can grow and shrink automatically without the need to write any

PAGE 382
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

code. This therefore implies that you may add to or delete .JPG file names from the
resource file, and the changes will automatically appear in the program. Go on,
attempt it.

The code to generate the above program is as follows. Note: The new event listener
found in the [Link] package. I have also included in this code the
split screen feature. You should be able to work out what is happening here as well
as be able to understand it.
import [Link].*;
import [Link].*;
import [Link].*;
import [Link].*;

public class SplitFrameList implements ListSelectionListener


{
private JLabel myPicture;
private JList myList;
private JSplitPane mySplitPane;
private String[] myPics = {"Cape1", "Cape2", "Cape3", "Cape4",
"Cape5", "Cape6","Cape7", "Cape8",
"Cape9","Paarl1","TheBest", "Sarah1",
"Sarah2","Sarah3","Eeek","Robbie1",
"Robbie2"
};

public static void main (String[] args){


JFrame myFrame = new JFrame("The Wonderful Cape");

[Link](new WindowAdapter()
{
public void windowClosing(WindowEvent e)
{
[Link](0);
}
});

SplitFrameList showPics = new SplitFrameList();

[Link]().add([Link]());
[Link]();
[Link](true);
}

public SplitFrameList(){
myList = new JList(myPics);
[Link](ListSelectionModel.SINGLE_SELECTION);
[Link](0);
[Link](this);

JScrollPane myListScrollPane = new JScrollPane(myList);

ImageIcon myImage = new ImageIcon("myImages\\" + "Cape1" + ".JPG");


myPicture = new JLabel(myImage);

PAGE 383
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

[Link](new Dimension([Link](),
[Link]()));

JScrollPane myPictureScrollPane = new JScrollPane(myPicture);

mySplitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT,


myListScrollPane, myPictureScrollPane);
[Link](true);
[Link](100);

Dimension minSize = new Dimension(100, 50);


[Link](minSize);
[Link](minSize);

[Link](new Dimension(620, 400));


}

public void valueChanged(ListSelectionEvent e){


if ([Link]())
return;

JList mySource = (JList)[Link]();


int index = [Link]();
ImageIcon newPic = new ImageIcon("myImages\\" +
(String)myPics[index] + ".JPG");
[Link](newPic);
[Link]();
}

public JSplitPane getSplitPane(){


return mySplitPane;
}
}

PAGE 384
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

Combo Boxes
JComboBox
A combo box is very similar to a list box. It is different in that firstly it is a drop
down list, and secondly if the combo box has been set to “editable” it means that
the user does not have to select an item from the drop down list, but may also enter
data into the box. Hence the name “Combo Box”. The code below is almost the
same as that for the List Box example, except that I have now written it for a
Combo Box. A snap shot of the program in operation is shown below. The
discussion under List Boxes with regards to making use of a resource file applies

By pressing on the
Down arrow in this
box, a list appears
below it. The user
may then make the
required selection.

equally here.

Here is the code:

import [Link].*;
import [Link].*;
import [Link].*;
import [Link].*;

public class SplitFrameCombo extends JPanel{


private JLabel myPicture;
private JComboBox myComboBox;
private JSplitPane mySplitPane;
private String[] myPics = {"Cape1", "Cape2", "Cape3", "Cape4","Cape5",
"Cape6","Cape7", "Cape8", "Cape9","Paarl1",
"TheBest","Sarah1","Sarah2","Sarah3","Eeek",
"Robbie1","Robbie2"};

public static void main (String[] args){


JFrame myFrame = new JFrame("The Wonderful Cape");

[Link](new WindowAdapter(){
public void windowClosing(WindowEvent e){
[Link](0);

PAGE 385
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

}
});

SplitFrameCombo showPics = new SplitFrameCombo();

[Link]().add([Link]());
[Link]();
[Link](true);
}

public SplitFrameCombo(){
myComboBox = new JComboBox(myPics);
[Link](0);
[Link](true); //I have made the box editable
[Link](new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
JComboBox mySource = (JComboBox)[Link]();
int index = [Link]();
ImageIcon newPic = new ImageIcon("myImages\\" +
(String)myPics[index] + ".JPG");
[Link](newPic);
[Link]();
}
});

JPanel myPanel = new JPanel();


[Link](myComboBox);

ImageIcon myImage = new ImageIcon("myImages\\" + "Cape1" + ".JPG");


myPicture = new JLabel(myImage);
[Link](new Dimension([Link](),
[Link]()));

JScrollPane myPictureScrollPane = new JScrollPane(myPicture);

mySplitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, myPanel,


myPictureScrollPane);
[Link](true);
[Link](150);

Dimension minSize = new Dimension(100, 50);


[Link](minSize);

[Link](new Dimension(640, 420));


}

public JSplitPane getSplitPane(){


return mySplitPane;
}
}

PAGE 386
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

Menus and Dialog Boxes


JMenuBar, JMenu, JMenuItem
When we looked at combo boxes, lists, radio buttons tool bars etc we saw how they
are capable of saving space in the UI. This is also true of a menu. Menus are unique
in that it is not necessary to use a layout manager to place menus. What you do is to
have a menu bar. This is at the top of the window, and it contains the names of the
pull-down menus the user may access. All the user needs to do is to click on the
menu name required and this results in a drop down menu appearing. This drop
down menu contains menu items that a user may select or the name of a sub menu
that the user may select. If you study the inheritance hierarchy of the menu related
items, you will quickly discover that menus and menu items are in essence, buttons.
One of the wonderful aspects of using menus is that when you press on one of these
‘buttons’ the menu items are automatically displayed. Remember when we spoke
about check boxes and radio buttons we said that these may be included into a
menu. The constructor methods to do this are JCheckBoxMenuItem() and
JRadioButtonMenuItem(). Go and check out the documentation supplied on the
accompanying CD. It is also possible to add icons to the menu items. Fortunately
building menus is pretty straightforward. Note there is a new event interface that is
defined in the [Link] package and is the MenuListener interface. It
consists of three methods by the way. These are menuSelected(),
menuDeselected() and menuCancelled(). In the code below I have included all
the basic aspects of menus. These include nested menus, disabled menu items (This
is similar to when we disabled button under the discussion on buttons), check
boxes, radio buttons, iconed menu items keyboard short cuts and on one of the
menu items, a dialog box appears when pressed. I have also shown in the code how
to respond to an item that has been selected. In most cases a dialog box will appear.
This code therefore gives you a framework around which you may build a fully-
fledged windows program.

Dialog boxes are similar to tool tips except that they are windows. Every dialog
box is dependent on a frame. This therefore means that whenever a frame is
destroyed, so are all the dependent dialog boxes. Dialog boxes, like most windows,
may be modal or non-modal. A modal dialog box will not allow a user to interact
with any other window within an application until such time as the user closes the
modal window (or dialog box). On the other hand a non-modal or modeless
window is one where a user may migrate to other windows that are open within the
program. You will see that in the program below that I have made use of the Swing
JOptionPane class which has a number of simple dialog boxes.

PAGE 387
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

The message type that these dialog boxes may be;


• ERROR_MESSAGE
• INFORMATION_MESSAGE
• WARNING_MESSAGE
• QUESTION_MESSAGE
• PLAIN_MESSAGE

I use some of them in the program. There are also dialog boxes that allow you to
receive a response from a user either by confirming an option or selecting an option
or even inputting a response. For example for the showConfirmationDialog the
return value may be;
• OK_OPTION
• CANCEL_OPTION
• YES_OPTION
• NO_OPTION
• CLOSED_OPTION

You may think this to be rather complex. It is not. I really do encourage you to
enter the code below and play with it. There is so much you can learn from it.
While you do this, make continual reference to the Java documentation.

This code therefore should provide you with an idea of many of the menu features
you can include into your code as well as how to respond to events generated from
the menu items. Youi should also have a good idea of how to use dialog boxes. The
only drawback of menu programming is that it is tedious. I therefore encourage you
to design a class that will implement effective menu implementation.

Below are a few snap shots of the program in operation.

PAGE 388
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

The code to do all this super stuff is;


import [Link].*;
import [Link].*;
import [Link].*;
import [Link].*;

public class MenuDemo extends JFrame implements ActionListener, MenuListener {


JTextArea output;
JScrollPane scrollPane;

public static void main(String[] args){


MenuDemo window = new MenuDemo();

[Link]("Oh, What a Wonderful Menu Variety");


[Link](450, 260);
[Link](true);
}

public MenuDemo(){
JMenuBar menuBar;
JMenu menu, menu1, menu2, menu3, submenu;
JMenuItem menuItem;
JCheckBoxMenuItem checkBoxMenuItem;
JRadioButtonMenuItem radioButtonMenuItem;

addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
[Link](0);
}
});

//Add regular components to the window, using the default BorderLayout.


Container contentPane = getContentPane();
output = new JTextArea(5, 30);
[Link](false);
scrollPane = new JScrollPane(output);
[Link](scrollPane, [Link]);

//Create the menu bar.


menuBar = new JMenuBar();
setJMenuBar(menuBar);

//Build the first menu.


menu = new JMenu("JustText");
[Link](KeyEvent.VK_J);
[Link](menu);

//a group of JMenuItems


menuItem = new JMenuItem("Look we can just have text", KeyEvent.VK_L);

//We have added a short cut key here. By pressing ALT 1 the above menu item will
//be accessed. In some of the examples I'll use the standard windows short cut keys.
[Link]([Link](KeyEvent.VK_1, ActionEvent.ALT_MASK));
[Link](this);
[Link](menuItem);

menuItem = new JMenuItem("New..", KeyEvent.VK_N);

PAGE 389
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

[Link]([Link](KeyEvent.VK_N, ActionEvent.CTRL_MASK));
[Link](this);
[Link](menuItem);

menuItem = new JMenuItem("Open..", KeyEvent.VK_O);


[Link]([Link](KeyEvent.VK_O, ActionEvent.CTRL_MASK));
[Link](this);
[Link](menuItem);

[Link]();

menuItem = new JMenuItem("Exit", KeyEvent.VK_E);


[Link]([Link](KeyEvent.VK_E, ActionEvent.ALT_MASK));
[Link](this);
[Link](menuItem);

//*************************************************************************************
//Build the second menu.
menu1 = new JMenu("IconText");
[Link](KeyEvent.VK_I);
[Link](this);
[Link](menu1);

menuItem = new JMenuItem("Java Lab",new ImageIcon("[Link]"));


[Link](KeyEvent.VK_J);
[Link](this);
[Link](menuItem);

menuItem = new JMenuItem("Earth",new ImageIcon("[Link]"));


[Link](KeyEvent.VK_E);
[Link](this);
[Link](menuItem);

[Link]();

menuItem = new JMenuItem("Report",new ImageIcon("[Link]"));


[Link](KeyEvent.VK_O);
[Link](this);
[Link](menuItem);

//*************************************************************************************
//Build the third and submenu menu.
menu2 = new JMenu("OtherStuff");
[Link](KeyEvent.VK_S);
[Link](menu2);

//a group of radio button menu items


ButtonGroup group = new ButtonGroup();

radioButtonMenuItem = new JRadioButtonMenuItem("Wee Dram");


[Link](true);
[Link](KeyEvent.VK_W);
[Link](radioButtonMenuItem);
[Link](radioButtonMenuItem);

radioButtonMenuItem = new JRadioButtonMenuItem("Irish Mist");


[Link](KeyEvent.VK_I);
[Link](radioButtonMenuItem);
[Link](radioButtonMenuItem);

//a group of check box menu items


[Link]();
checkBoxMenuItem = new JCheckBoxMenuItem("Outside/Inside");
[Link](KeyEvent.VK_O);
[Link](checkBoxMenuItem);

checkBoxMenuItem = new JCheckBoxMenuItem("Sea View");


[Link](KeyEvent.VK_S);
[Link](checkBoxMenuItem);

[Link]();

menuItem = new JMenuItem("Im Disabled",new ImageIcon("[Link]"));

PAGE 390
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

[Link](KeyEvent.VK_L);
[Link](false);
[Link](menuItem);

//a submenu
[Link]();
submenu = new JMenu("Submenu");
[Link](KeyEvent.VK_U);

menuItem = new JMenuItem("Welcome",new ImageIcon("[Link]"));


[Link]([Link](KeyEvent.VK_W, ActionEvent.ALT_MASK));
[Link](this);
[Link](menuItem);

[Link]();

menuItem = new JMenuItem("Colour");


[Link](KeyEvent.VK_C);
[Link](this);
[Link](menuItem);

[Link](submenu);

//******************************************************************************************
//Build the fourth menu.
menu3 = new JMenu("About");
[Link](KeyEvent.VK_A);

menuItem = new JMenuItem("About", KeyEvent.VK_A);


[Link]([Link](KeyEvent.VK_A, ActionEvent.ALT_MASK));
[Link](this);
[Link](menuItem);

[Link](menu3);

//*************************************************************************************
//Notice the use of a dialog box showMessageDialog
private void showAboutBox(){
Icon myIcon = new ImageIcon("[Link]");
JLabel myLabel = new JLabel("This is so COOL and Explosive.
Written by: Stuart Fripp. 2018.", myIcon, [Link]);
[Link](null, myLabel, "This is a PLAIN MESSAGE Dialog Box.",
JOptionPane.PLAIN_MESSAGE);
}

//Notice the use of a dialog box showMessageDialog


private void showItemSelected(String txt){
JLabel myLabel = new JLabel("You Pressed the \"" +(String)txt + "\" Button.", [Link]);
[Link](null, myLabel, "This is an INFORMATION Dialog Box.",
JOptionPane.INFORMATION_MESSAGE);
}

//Notice the use of a dialog box showConfirmDialog


private void showSelectionBox(){
int reallyExit;
JLabel myLabel = new JLabel("Are you really sure you want to exit?", [Link]);
reallyExit = [Link](null, myLabel, "This is a CONFIRM Dialog Box.",
JOptionPane.OK_CANCEL_OPTION, JOptionPane.WARNING_MESSAGE);
if (reallyExit == JOptionPane.OK_OPTION)
[Link](0);
}

//******************************************************************************************
// The event handlers. These are simple just showing Message boxes. But naturally,
// depending upon what your program is doing one may call other methods or objects.

public void actionPerformed(ActionEvent e){


if ([Link]() instanceof JMenuItem){
String button = new String([Link]());
if ([Link]("Exit"))

PAGE 391
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

showSelectionBox();
else if ([Link]("About"))
showAboutBox();
else
showItemSelected(button);
}
}

//I have not written any code for these. I just included them for the sake of edification.
public void menuSelected(MenuEvent e){}

public void menuDeselected(MenuEvent e){}

public void menuCanceled(MenuEvent e){}


}

PAGE 392
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

Tabbed Panes
JTabbedPane
These are also really easy to use and the code should be self-explanatory. With the
JTabbedPane class, you can have several components (usually panels as shown in
the code below) which share the same space. The user chooses which component
to view by selecting the tab corresponding to the desired component. If you want
similar functionality without the tab interface, you might want to use a card layout
instead of a tabbed pane.

To create a tabbed pane, you simply instantiate JTabbedPane, create the


components you wish to display, and then add the components to the tabbed pane
using the addTab() method. A tab can have a tool tip, and it can display both text
and an image. In the code below I have added this to show you. You can change
the tab position to be at the left, right, or bottom of the tabbed pane. Note that no
event-handling code is necessary. The JTabbedPane object takes care of mouse
events for you. Some of the screen snap shots showing this program running are
shown below;

This is the tool tip


in operation.

The code, which really is not difficult, is shown below. You should be able to work
out what is happening and how to use tabbed panes from this. Again, go and peruse
the JTabbedPane class for details on these and other methods.

PAGE 393
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

import [Link].*;
import [Link].*;
import [Link].*;

public class MyTabs extends JPanel {


public static void main(String[] args) {
JFrame myFrame = new JFrame("Ouch, I have a \"Tab-Pane\" just here.");
[Link](new WindowAdapter() {
public void windowClosing(WindowEvent e){
[Link](0);
}
});

[Link]().add(new MyTabs(),[Link]);
[Link](400, 125);
[Link](true);
}

public MyTabs() {
JTabbedPane tabbedPane = new JTabbedPane();

ImageIcon myPic = new ImageIcon("[Link]");


Component panel1 = makeTextPanel("This is an image of a flask.", myPic);
[Link]("One", myPic, panel1, "I am Tab One");
[Link](0);

ImageIcon myPic1 = new ImageIcon("[Link]");


Component panel2 = makeTextPanel("Uhm, Good day", myPic1);
[Link]("Two", myPic1, panel2, "I am Tab Two");

ImageIcon myPic2 = new ImageIcon("[Link]");


Component panel3 = makeTextPanel("Ode to a Nightingale", myPic2);
[Link]("Three", myPic2, panel3, "I am Tab Three");

ImageIcon myPic3 = new ImageIcon("[Link]");


Component panel4 = makeTextPanel("One of the planets in our solar system
is Earth", myPic3);
[Link]("Four", myPic3, panel4, "I am Tab Four");

//Add the tabbed pane to this panel.


setLayout(new GridLayout(1, 1));
add(tabbedPane);
}

//This member method creates a panel and places a label in it.


//The completed object is then returned.
protected Component makeTextPanel(String text, ImageIcon pic) {
JPanel myPanel = new JPanel(false);
JLabel myLabel = new JLabel(text, pic, [Link]);
[Link](new GridLayout(1, 1));
[Link](myLabel);
return myPanel;
}
}

PAGE 394
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

Borders
I found some code written by Sun Microsystems that demonstrates the different
borders using tabbed panes so effectively that I have included it into this
document. So this code belongs to Sun Microsystems. In the code you will see that
Sun makes use of tabbed panes. The different borders you can produce are shown
below;

These are simple borders. You have already seen the raised bevel border in the
code I wrote for the section on radio buttons. These are easy to generate.

This screen snap shot above is an example of matte borders. What is important
when using matte borders is that you need to specify the number of pixels it
occupies at the top, left, bottom, and right of a component. Then you need to
specify either a color or an icon for the matte border to draw. Be careful of the type
of icon you are using, in that it may be clipped resulting in the border looking
awful.

PAGE 395
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

This next screen shot above shows borders that have an associated title. Finally, the
screen shot below shows borders that are compound. With compound borders you
can combine any two borders, which can themselves become compound borders.

As you can see there are many different border styles you may use. They are not
difficult to implement yet they provide for a most pleasing UI. If you find that
none of these borders are of use to you, you are capable of building up your own
border by creating a subclass of the AbstractBorder class. Go and study the API
documentation on this to see how it is done.

In addition to the border interface, the border package does contain classes that
implement many of the above borders. In the code you will see these implemented
i.e. LineBorder, EtchedBorder, BevelBorder, EmptyBorder, MatteBorder,
TiledBorder and CompoundBorder. There is also an additional border not used in

PAGE 396
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

the code below and this is the SoftBevelBorder. This produces a beveled border
with soft edges. So go and study the Border API.
import [Link].*;
import [Link].*;
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];

public class BorderDemo extends JFrame {


public static void main(String[] args) {
JFrame frame = new BorderDemo();
[Link](new WindowAdapter() {
public void windowClosing(WindowEvent e) {
[Link](0);
}
});

[Link]();
[Link](true);
}

public BorderDemo() {
super ("BorderDemo");
Border blackline, etched, raisedbevel, loweredbevel, empty;

//A border that puts 10 extra pixels at the sides and


//bottom of each pane.
Border paneEdge = [Link](0,10,10,10);

blackline = [Link]([Link]);
etched = [Link]();
raisedbevel = [Link]();
loweredbevel = [Link]();
empty = [Link]();

//First pane: simple borders


JPanel simpleBorders = new JPanel();
[Link](paneEdge);
[Link](new BoxLayout(simpleBorders,BoxLayout.Y_AXIS));
addCompForBorder(blackline, "line border",simpleBorders);
addCompForBorder(etched, "etched border",simpleBorders);
addCompForBorder(raisedbevel, "raised bevel border",simpleBorders);
addCompForBorder(loweredbevel, "lowered bevel border",simpleBorders);
addCompForBorder(empty, "empty border",simpleBorders);
//Second pane: matte borders
JPanel matteBorders = new JPanel();
[Link](paneEdge);
[Link](new BoxLayout(matteBorders,BoxLayout.Y_AXIS));

PAGE 397
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

//XXX: We *should* size the component so that the


//XXX: icons tile OK. Without that, the icons are
//XXX: likely to be cut off and look bad.
ImageIcon icon = new ImageIcon("[Link]"); //20x22
Border border = [Link](-1, -1, -1, -1, icon);
addCompForBorder(border,"matte border (-1,-1,-1,-1,icon)",matteBorders);
border = [Link](1, 5, 1, 1, [Link]);
addCompForBorder(border,"matte border (1,5,1,1,[Link])",matteBorders);
border = [Link](0, 20, 0, 0, icon);
addCompForBorder(border,"matte border (0,20,0,0,icon)",matteBorders);

//Third pane: titled borders


JPanel titledBorders = new JPanel();
[Link](paneEdge);
[Link](new BoxLayout(titledBorders,BoxLayout.Y_AXIS));
TitledBorder titled;

titled = [Link]("title");
addCompForBorder(titled, "default titled border"
+ " (default just., default pos.)",
titledBorders);

titled = [Link](blackline, "title");


addCompForTitledBorder(titled, "titled line border"
+ " (centered, default pos.)",
[Link],
TitledBorder.DEFAULT_POSITION,
titledBorders);

titled = [Link](etched, "title");


addCompForTitledBorder(titled,"titled etched border"
+ " (right just., default pos.)",
[Link],
TitledBorder.DEFAULT_POSITION,
titledBorders);

titled = [Link](loweredbevel, "title");


addCompForTitledBorder(titled,"titled lowered bevel border"
+ " (default just., above top)",
TitledBorder.DEFAULT_JUSTIFICATION,
TitledBorder.ABOVE_TOP,
titledBorders);

titled = [Link](empty, "title");


addCompForTitledBorder(titled, "titled empty border"
+ " (default just., bottom)",
TitledBorder.DEFAULT_JUSTIFICATION,
[Link],
titledBorders);

//Fourth pane: compound borders


JPanel compoundBorders = new JPanel();
[Link](paneEdge);
[Link](new BoxLayout(compoundBorders,BoxLayout.Y_AXIS));
Border redline = [Link]([Link]);

PAGE 398
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

Border compound;
compound = [Link](raisedbevel, loweredbevel);
addCompForBorder(compound, "compound border (two bevels)",compoundBorders);

compound = [Link](redline, compound);


addCompForBorder(compound, "compound border (add a red outline)",
compoundBorders);

titled = [Link](compound, "title",


[Link],
TitledBorder.BELOW_BOTTOM);
addCompForBorder(titled, "titled compound border"
" (centered, below bottom)",
compoundBorders);

JTabbedPane tabbedPane = new JTabbedPane();


[Link]("Simple", null, simpleBorders, null);
[Link]("Matte", null, matteBorders, null);
[Link]("Titled", null, titledBorders, null);
[Link]("Compound", null, compoundBorders, null);
[Link](0);

getContentPane().add(tabbedPane, [Link]);
}

void addCompForTitledBorder(TitledBorder border,


String description,
int justification,
int position,
Container container) {
[Link](justification);
[Link](position);
addCompForBorder(border, description,container);
}

void addCompForBorder(Border border,


String description,
Container container){
JPanel comp = new JPanel(false);
JLabel label = new JLabel(description, [Link]);
[Link](new GridLayout(1, 1));
[Link](label);
[Link](border);

[Link]([Link](new Dimension(0, 10)));


[Link](comp);
}
}

PAGE 399
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

TESTING AND DEBUGGING JAVA CODE


As a developer, one process you need to master is that of testing your software.
You will know by now you have created many errors that the Java compiler has
caught, and these are relatively easy to correct. Often we think that if our program
compiles, all is well. However, when you run your program, all chaos ensues. You
need to test for these errors. Martin Fowler has suggested that the most important
criterion for software design is testability.

Software is tested to uncover errors that were made inadvertently as it was designed
and constructed. But how do you conduct the tests? Should you develop a formal
plan for your tests? Should you test the entire program as a whole or run tests only
on a small part of it? Should you rerun tests you’ve already conducted as you add
new components to a large system? When should you involve the customer?

Testing often accounts for more project effort than any other software engineering
action. If it is conducted haphazardly, time is wasted, unnecessary effort is
expended, and even worse, errors sneak through undetected. So you need to
establish a systematic strategy for testing your software. Testing begins “in the
small” and progresses “to the large.” By this I mean that early testing focuses on a
single component or a small group of related components and applies tests to
uncover errors in the data and processing logic that have been encapsulated by the
component(s). After components are tested they must be integrated until the
complete system is constructed. At this point, a series of high-order tests are
executed to uncover errors in meeting customer requirements. As errors are
uncovered, they must be diagnosed and corrected using a process that is called
debugging.

As an aside: System testing is a series of different tests whose primary purpose is to


fully exercise the computer-based system. Although each test has a different
purpose, all work to verify that system elements have been properly integrated and
perform allocated functions. There are a number of tests you may perform. These
include;

• Recovery Testing: Many systems must recover from faults, with little or no
down time. Recovery testing is a system test that forces the software to fail
in a variety of ways and verifies that recovery is properly performed.
• Security Testing: Computer systems that manages sensitive information or
causes actions that can improperly harm (or benefit) individuals is a target
for improper or illegal penetration. Penetration spans a broad range of

PAGE 400
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

activities: hackers who attempt to penetrate systems for sport, disgruntled


employees who attempt to penetrate for revenge, dishonest individuals who
attempt to penetrate for illicit personal gain. Security testing attempts to
verify that protection mechanisms built into a system will, in fact, protect it
from improper penetration. To quote Beizer “The system’s security must, of
course, be tested for invulnerability from frontal attack – but must also be
tested for invulnerability from flank or rear attack.” During security testing,
the tester plays the role(s) of the individual who desires to penetrate the
system. Anything goes! The tester may attempt to acquire passwords through
external clerical means; may attack the system with custom software
designed to break down any defenses that have been constructed; may
overwhelm the system, thereby denying service to others; may purposely
cause system errors, hoping to penetrate during recovery; may browse
through insecure data, hoping to find the key to system entry.
• Stress Testing: the tester who performs stress testing should be asking the
question: “How high can I crank this up before it fails?” Stress testing
executes a system in a manner that demands resources in abnormal quantity,
frequency, or volume. For example; generate ten interrupts per second, when
one or two is the average rate or test input data rates increasing them by an
order of magnitude to determine how input functions will respond. You can
also test for maximum memory or even generate tests that cause excessive
hunting for disk-resident data. Essentially, attempt to break the program. A
variation of stress testing is a technique called sensitivity testing.
• Performance Testing: This is often coupled with stress testing and usually
require both hardware and software instrumentation. It is often necessary to
measure resource utilization (e.g., processor cycles) in an exacting fashion.
External instrumentation can monitor execution intervals, log events (e.g.,
interrupts) as they occur, and sample machine states on a regular basis. By
instrumenting a system, the tester can uncover situations that lead to
degradation and possible system failure.

Let us look at basic testing of your code. Testing requires that the developer discard
preconceived notions of the “correctness” of software just developed and then work
hard to design test cases to “break” the software. Beizer [Bei90] describes this
situation effectively when he states:
“There’s a myth that if we were really good at programming, there would be no
bugs to catch. If only we could really concentrate, if only everyone used structured
programming, top-down design, . . . then there would be no bugs. So goes the myth.
There are bugs, the myth says, because we are bad at what we do; and if we are
bad at it, we should feel guilty about it. Therefore, testing and test case design is an
admission of failure, which instills a goodly dose of guilt. And the tedium of testing

PAGE 401
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

is just punishment for our errors. Punishment for what? For being human? Guilt
for what? For failing to achieve inhuman perfection? For not distinguishing
between what another programmer thinks and what he says? For failing to be
telepathic? For not solving human communications problems that have been kicked
around . . . for forty centuries?”

Should testing instill guilt? Is testing really destructive? The answer to these
questions is “No!”

Testing is complex. There are numerous techniques. There is external view testing
called black-box testing as well as internal view testing termed white-box testing.
We will not go into all this. We shall discuss some techniques you can use as an
entry level developer.

Using [Link]()
This is VERY simple testing and should not be used as your main test strategy.
You can end up with hundreds of [Link] statements in your code. Having
said this, this strategy can be useful. Here is a simple example showing you the
technique;
public class SoutTesting {
public static void main(String[] args) {
int value = 45;
if(value <= 50){
[Link]("Underweight");
}
[Link]("value is "+value);
}
}

Example outputs running this example;


Underweight
value is 45

Assertions
Next, let us look at a feature that was added in JDK1.4, and that is - Assertions.

So what is an assertion? An assertion is a statement in Java that enables you to test


your assumptions about your program. It is mainly used for testing purposes during
development. Each assertion contains a boolean expression that you believe will
be true when the assertion executes. By verifying that the boolean expression is
indeed true, the assertion confirms your assumptions about the behavior of your
program, increasing your confidence that the program is free of errors. If it fails,
the JVM throws an error named AssertionError.

PAGE 402
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

The assertion statement has two forms. The first is;


assert expression1;

Where expression1 is a boolean expression. When the system runs the assertion,
it evaluates expression1 and if it is false throws an AssertionError with no
details.

The second form is;


assert expression1 : expression2 ;

Where expression1 is a boolean expression and expression2 is an expression


that has a value. Use this second version of the assert statement to provide a
detailed message for the AssertionError. What happens if the expression fails,
(i.e. evaluates to false)? Well, the system passes the value of expression2 to the
appropriate AssertionError constructor, communicating the reason for the
assertion failure.

Let us look at a simple example by modifying our previous example and using the
second form of assertion testing;
class AssertTest{
public static void main( String args[] ){
int value = 45;
assert value >= 50 : " Underweight";
[Link]("The value is "+value);
}
}

Go ahead and compile and then run this code. The output on your console will be:
The value is 45

But where is the assertion test? By default assertions are disabled. To enable
assertions in the runtime use the –ea flag. So, to run the program with assertions
enabled, type the following;
java –ea AssertTest

Your output should now display;


Exception in thread "main" [Link]: Underweight
at [Link]([Link])

Notice that your test ran, and the error message is displayed as the assertion was
false. Had it been true, then no exception would have been thrown. To disable
assertions, use the –da flag. This is one of the advantages of using assertions, as

PAGE 403
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

opposed to [Link] form of testing, you are able to turn assertion testing on
and off.

I encourage you to use assertions under the following circumstances;


• To make sure that an unreachable looking code is actually unreachable.
• To make sure that assumptions written in comments are right (we are using
the first form in this example).
if((x & 1) == 1){
:
}
else{// x must be even
assert (x % 2 == 0);
}
• To make sure that default switch case is not reached.
• To check an object’s state.
• To check conditions at the beginning of a method.
• After method invocation.

Assertions are mainly used to check logically impossible situations. For example,
they can be used to check the state a code expects before it starts running or state
after it finishes running. Unlike normal exception/error handling, assertions are
generally disabled at run-time.

There are conditions that exist where you should not use assertions for testing,
these include;
• Assertions should not be used to replace error messages
• Assertions should not be used to check arguments in the public methods as
they may be provided by user. Error handling should be used to handle errors
provided by user.
• Assertions should not be used on command line arguments.

Remember, assertions will only execute it they are enabled. Do not forget to disable
them before you deploy your application.

JUnit testing
JUnit is a framework that was started by Kent Beck and Erich Gamma in late 1995.
And is now the de facto standard for unit testing in Java. The JUnit defines three
discrete goals for the framework. It helps you;
• Write useful tests.
• Create tests that retain their value over time.
• Lower the cost of writing tests by reusing code.

PAGE 404
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

In order to use JUnit to write your application tests, you need to add the JUnit JAR
files to your project’s compilation classpath and to your execution classpath. These
files, [Link] and [Link], should be in your course ‘software
pack’. We will be using JUnit 4.

JUnit has many features that make it easy to write and run tests. These features
include, amongst others;
• Separate test class instances and class loaders for each unit test to avoid side
effects.
• JUnit annotations to provide resource initialization and reclamation methods:
@Before, @BeforeClass, @After, and @AfterClass.
• A variety of assertions to make it easy to check the results of your tests.
• Integration with popular tools like Ant and Maven, and popular IDEs like
Eclipse, NetBeans and IntelliJ and JGrasp.

Just to whet your appetite, let us look at a very simple example. First, create your
own Calculate class. There is nothing fancy here.

public class Calculate {


public int sum(int var1, int var2) {
[Link]("Adding values: " + var1 + " + " + var2);
return (var1 + var2);
}
}

Now, create a test class that will test the Calculate class.

import static [Link];


import [Link];

public class CalculateTest {


Calculate calculation = new Calculate();
int sumAns = [Link](2, 5);
int expectedSum = 7;

@Test
public void testSum() {
[Link]("@Test sum(): " + sumAns + " = " + expectedSum);
assertEquals(expectedSum, sumAns);
}
}

Compile both files and then run the test by typing the following at the command
line;
java [Link] CalculateTest

Hopefully you will see something like the following appear on your console;

PAGE 405
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

JUnit version 4.12


Adding values: 2 + 5
.@Test sum(): 7 = 7

time: 0

OK (1 test)

Congratulations, you have run your first JUnit test.

Let us explain this test you have just executed. In the CalculateTest class notice
that you created an instance of the Calculate class, and then ran the sum()
method on the instance, which returned a value that is assigned to a variable
sumAns. You also assigned a literal to another variable expectedSum.

Next, notice how method testSum has been annotated with the @Test annotation.
Doing this marks the method as being a test unit method. Note: it is recommended
that any methods that are test methods should conform to the following pattern;
testXXX(). However, this is not a requirement and you may name them anything
you like. The only requirement is the @Test annotation. Incidentally, you should
also use the ‘Test’ suffix at the end of your test classes names i.e. XxxTest, for
example CalculateTest.

Looking at the test method that has been annotated with the @Test annotation; the
first line of this method prints the actual sum calculated and the expected value to
the console. The next line is the important one, and is the line JUnit is responsible
for. To check the result of the test, you call an assertEquals method, which is
imported. In our example, we pass the assertEquals() two arguments; The first
is the value you are expecting from the calculation, in our case 7 found in
expectedSum, the second is the actual value calculated and assigned to sumAns.
Now, should the actual value not equal the expected value, JUnit throws an
unchecked exception resulting in the test failing. In our example, the expected and
the actual value are the same, so the test passed. Go and change the expected value
in the test class and run it again to see what happens.

Now that you have a smattering of understanding of how to use JUnit, let us delve a
little deeper.

As you saw from the earlier example, you created a test unit (CalculateTest) and
then ran this test from the command line using the
[Link] program. A better way is to actually create your
own test runner which you use to execute your tests. So, generally you create your

PAGE 406
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

classes, then a test class and finally a runner that will invoke the tests. So let us
look at your first test runner. Here is a simple example;
import [Link];
import [Link];
import [Link];

public class VzapTestRunner {


public static void main(String[] args) {
Result result = [Link]([Link]);
for (Failure failure : [Link]()) {
[Link]([Link]());
}
[Link]([Link]());
}
}

Go ahead and compile this ‘runner’ and then run it:


java VzapTestRunner

The output generated is almost exactly the same as your original example.
Adding values: 2 + 5
@Test sum(): 7 = 7
true

The line that runs the tests is:


Result result = [Link]([Link]);

We then test the result of the test over the lines following this line, verifying
whether the tests passed or failed.

So, your process should be;


1. Write your classes.
2. Write a Test class to test these classes.
3. Write a Runner class to invoke the tests.

Annotations in JUnit
As you saw during the course, Java uses annotation. So does JUnit. JUnit uses
annotations to mark methods as test methods and to configure them. In essence
these annotations provide the JUnit framework with the following information;
• which methods are going to run before and after the test methods,
• which methods run before and after all the methods, and
• which methods or classes will be ignored during the test execution.

The following table gives an overview of the most important annotations in JUnit
for the 4.x and 5.x versions. All these annotations can be used on methods.

PAGE 407
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

import [Link].* Import statement for all JUnit 4 annotations.


@Test Identifies a method as a test method.
@Before Executed before each test. It is used to prepare the
test environment (e.g., read input data, initialize
the class).
@After Executed after each test. It is used to clean up the
test environment (e.g., delete temporary data,
restore defaults). It can also save memory by
cleaning up expensive memory structures.
@BeforeClass Executed once, before the start of all tests. It is
used to perform time intensive activities, for
example, to connect to a database. Methods
marked with this annotation need to be defined
as static to work with JUnit.
@AfterClass Executed once, after all tests have been finished. It
is used to perform clean-up activities, for example,
to disconnect from a database. Methods annotated
with this annotation need to be defined as static to
work with JUnit.
@Ignore or @Ignore("Why disabled") Marks that the test should be disabled. This is
useful when the underlying code has been changed
and the test case has not yet been adapted. Or if the
execution time of this test is too long to be
included. It is best practice to provide the optional
description, why the test is disabled.
@Test (expected = [Link]) Fails if the method does not throw the named
exception.
@Test(timeout=100) Fails if the method takes longer than 100
milliseconds.
@Test Identifies a method as a test method.
@Before Executed before each test. It is used to prepare the
test environment (e.g., read input data, initialize
the class).
@After Executed after each test. It is used to clean up the
test environment (e.g., delete temporary data,
restore defaults). It can also save memory by
cleaning up expensive memory structures.
@BeforeClass Executed once, before the start of all tests. It is
used to perform time intensive activities, for
example, to connect to a database. Methods
marked with this annotation need to be defined
as static to work with JUnit.

Just to help you with these annotations, let us write a simple example showing you
some of the annotations mentioned in the table above;

PAGE 408
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

public class AnnotationsTest {


private ArrayList<String> testList;

@BeforeClass
public static void onceExecutedBeforeAll() {
[Link]("@BeforeClass: onceExecutedBeforeAll");
}

@Before
public void executedBeforeEach() {
testList = new ArrayList<String>();
[Link]("@Before: executedBeforeEach");
}

@AfterClass
public static void onceExecutedAfterAll() {
[Link]("@AfterClass: onceExecutedAfterAll");
}

@After
public void executedAfterEach() {
[Link]();
[Link]("@After: executedAfterEach");
}

@Test
public void EmptyCollection() {
assertTrue([Link]());
[Link]("@Test: EmptyArrayList");
}

@Test
public void OneItemCollection() {
[Link]("oneItem");
assertEquals(1, [Link]());
[Link]("@Test: OneItemArrayList");
}

@Ignore
public void executionIgnored() {
[Link]("@Ignore: This execution is ignored");
}
}

I have not written a ‘runner’ to run this test, so I will use the default runner. Invoke
this in the same way you did in an earlier example, as follows;
java [Link] AnnotationsTest

You should see something along the following lines on your console;
JUnit version 4.12
@BeforeClass: onceExecutedBeforeAll
@Before: executedBeforeEach
@Test: EmptyArrayList
@After: executedAfterEach
@Before: executedBeforeEach

PAGE 409
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

@Test: OneItemArrayList
@After: executedAfterEach
@AfterClass: onceExecutedAfterAll

time: 0.015

OK (2 tests)

There are times when you may not want a particular test to run, but you still want
all the other tests to run in the test case. To do this you make use of the @Ignore
annotation, in a similar way we saw in the previous example where we ‘ignored’ a
method. So to prevent a test from running by ignoring it you do the following;
@Ignore
@Test
public void testMethodFoo() {
:
}

JUnit provides a handy option of a timeout test. If a test case takes more time than
the specified number of milliseconds, then JUnit will automatically mark it as
failed. The timeout parameter is used along with @Test annotation. Let us see the
@Test(timeout) in action by modifying our class and force it to be slow as to
generate an error;
import static [Link];
import [Link];

public class CalculateTest {


Calculate calculation = new Calculate();
int sumAns = [Link](2, 5);
int expectedSum = 7;

@Test(timeout=1000)
public void testSum() {
[Link]("@Test sum(): " + sumAns + " = " + expectedSum);
assertEquals(expectedSum, sumAns);
try{
[Link](1500);
}catch(Exception ex){}
}
}

Compile this class, then call its runner as follows;


java VzapTestRunner

Your output should look as follows;


Adding values: 2 + 5
@Test sum(): 7 = 7
testSum(CalculateTest): test timed out after 1000 milliseconds
false

PAGE 410
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

Notice how the test failed as it was taking longer than 1000 milliseconds.

Assertion in JUnit
JUnit provides static methods to test for certain conditions via the Assert class.
These assert statements typically start with assert. They allow you to specify the
error message, the expected and the actual result. An assertion method compares
the actual value returned by a test to the expected value. It throws an
AssertionException if the comparison fails. Parameters in [] brackets are
optional and of type String.
fail([message]) Let the method fail. Might be used to
check that a certain part of the code is
not reached or to have a failing test
before the test code is implemented. The
message parameter is optional.
assertTrue([message,] boolean condition) Checks that the boolean condition is
true.
assertFalse([message,] boolean condition) Checks that the boolean condition is
false.
assertEquals([message,] expected, actual) Tests that two values are the same. Note:
for arrays the reference is checked not
the content of the arrays.
assertEquals([message,] expected, actual, tolerance) Test that float or double values match.
The tolerance is the number of decimals
which must be the same.
assertNull([message,] object) Checks that the object is null.
assertNotNull([message,] object) Checks that the object is not null.
assertSame([message,] expected, actual) Checks that both variables refer to the
same object.
assertNotSame([message,] expected, actual) Checks that both variables refer to
different objects.

Here is a simple test using some of the assertions found in the list above. Type out
the code listed below. Compile and run. Take note of the output. Then make
changes to generate errors. This should give you a good idea as to how each JUnit
assertion works. Here is the code;
import static [Link].*;
import [Link];

public class AssertionsTest {

@Test
public void test() {
String s1 = new String("vzap");
String s2 = new String("vzap");
String s3 = "noodle";
String s4 = "noodle";

PAGE 411
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

String obj5 = null;


int var1 = 1;
int var2 = 2;
int[] arr1 = { 1, 2, 3 };
int[] arr2 = { 1, 2, 3 };

//********************
assertEquals(s1, s2); //check that two objects are equal
assertSame(s3, s4); //check if two object references reference the same object
assertNotSame(s2, s4); //check if two object references DO NOT reference
//the same object
assertNotNull(s1); //check if a reference is not null
assertNull(obj5); //check if a reference IS null
assertTrue(var1 < var2); //check for a true condition
assertFalse(var1 > var2); //check for a false condition
assertArrayEquals(arr1, arr2); //check if two arrays are equal
}

}}

As I have not written a runner, invoke the test as follows;


java [Link] AssertionsTest

JUnit provides an option of tracing the exception handling of code. You can test
whether the code throws a desired exception or not. The expected parameter is used
along with @Test annotation. Let us see @Test(expected) in action where we
modify our CalculateTest class by adding a new method. Notice how you are
now using @Ignore to ‘switch off a test’.

import static [Link];


import [Link];
import [Link];

public class CalculateTest {


Calculate calculation = new Calculate();
int sumAns = [Link](2, 5);
int expectedSum = 7;

@Ignore
@Test
public void testSum() {
[Link]("@Test sum(): " + sumAns + " = " + expectedSum);
assertEquals(expectedSum, sumAns);
}

@Test(expected = [Link])
public void testException() {
int failHere=100/0;
[Link]("Should not get here");
}
}

As I have not written a runner, invoke the test as follows;


java [Link] AssertionsTest

PAGE 412
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

You should see that the test passed as the code does indeed throw an
ArithmeticException.

Suite testing in JUnit


A test suite is a collection of test cases from different classes that can be run
together using @RunWith and @Suite annotations. This is very useful. When a
class is annotated with @RunWith, JUnit will invoke the class in which is annotated
so as to run the tests, instead of using a separate runner, be it the built in one or
your own. To demonstrate how a test suit is created, let us use the two test classes
you have already created, namely: CalculateTest and AssertionsTest.

Running a test suite executes all test classes in that suite, in the order specified. By
the way, a test suite can also contain other test suites.

In our example code notice that it contains our two tests. Should you want to
include another test class, you can add it to the @[Link] statement.
Here is the code;
import [Link];
import [Link];

@RunWith([Link])
@[Link]({ [Link], [Link] })

public class SuitTest {


}

Run the suite by using the default runner;


java [Link] SuitTest

Simple, Huh!!

Of course you can write your own test suite runner. Here is an example;
import [Link].*;

public class SuitTest {


public static void main(String[] a) {
// add the test's in the suite
TestSuite suite = new TestSuite([Link], [Link]);
TestResult result = new TestResult();
[Link](result);
[Link]("Number of test cases = " + [Link]());
}
}

PAGE 413
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

To run your own suite runner, in our case SuitTest, type the following at the
command line;
java SuiteTest

To manipulate the test suite you make use of the [Link] class.
This class contains a number of tests you may invoke, as well as a number of utility
methods. The most common methods used are;
void addTest(Test test) Adds a test to the suite.
void addTestSuite(Class<? extends TestCase> testClass) Adds the tests from the given class to
the suite.
int countTestCases() Counts the number of test cases that will
be run by this test.
String getName() Returns the name of the suite.
void run(TestResult result) Runs the tests and collects their result in
a TestResult.
void setName(String name) Sets the name of the suite.
Test testAt(int index) Returns the test at the given index.
int testCount() Returns the number of tests in this suite.
static Test warning(String message) Returns a test, which will fail and log a
warning message

Parameterized testing in JUnit


JUnit 4 introduced a new feature called parameterized tests. This type of testing
allows you to run the same test over and over again using different values. There
are five steps you need to follow to create a parameterized test. These steps are:
1. Annotate your test class with @RunWith([Link]).
2. Create a public static method annotated with @Parameters which
returns a Collection (such as an Array) of objects as test data set.
3. Create a public constructor that takes in what is equivalent to one "row" of
test data.
4. Create an instance variable for each "column" of test data.
5. Create your test case(s) using the instance variables as the source of the test
data.

To see this in action, let us once again modify our CalculateTest class. Migrate
through the code carefully. I am sure you will understand it with no problem.
import static [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];

PAGE 414
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

import [Link];
import [Link];

@RunWith([Link])
public class CalculateTest {
private int expected;
private int first;
private int second;

public CalculateTest(int expectedResult, int firstNumber, int secondNumber){


[Link] = expectedResult;
[Link] = firstNumber;
[Link] = secondNumber;
}

@Before
public void fooMethod() {
[Link]("\nJust adding this for fun to show it is run before each test");
}

@Parameters
public static Collection addedNumbers() {
// For each entry, notice that;
// The first element is the expected value, second is the first value to add
// and the third element is the second value to add. This is the same as the
// constructor's parameter list.
return [Link](new Integer[][] { {3,1,2}, {5,2,3}, {7,3,4}, {9,4,5} });
}

@Test
public void sum() {
Calculate add = new Calculate();
[Link]("Addition with parameters : " + first + " and " + second);
assertEquals(expected, [Link](first, second));
}
}

Compile and run your example as follows;


java VzapTestRunner

If you really want to run your test using the default, built in runner then do this;
java [Link] CalculateTest

Your output should look similar to this;


Just adding this for fun to show it is run before each test
Addition with parameters : 1 and 2
Adding values: 1 + 2

Just adding this for fun to show it is run before each test
Addition with parameters : 2 and 3
Adding values: 2 + 3

Just adding this for fun to show it is run before each test
Addition with parameters : 3 and 4
Adding values: 3 + 4

Just adding this for fun to show it is run before each test
Addition with parameters : 4 and 5

PAGE 415
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

Adding values: 4 + 5
true

Notice how the method @Before is invoked by the JUnit framework before each
test and test case will is invoked once for each row of data in the returned
collection.

There are other features in JUnit 4, which we will not discuss that include rules and
categories. Rules allow for the redefinition of the behavior of each test method in a
test class. For this purpose, @Rule annotation should be used to mark public fields
of a test class. Categories allow you to group certain kinds of tests together and
even include or exclude groups (categories). For example, you can separate slow
tests from fast tests. To assign a test case or a method a category the @Category
annotation is provided. I encourage you to go and study these additional JUnit 4
feature when you have a chance.

This introduction to JUnit should give you a very good starting point to build your
own tests.

If you are using JGrasp, you can add JUnit testing to it. It really is very simple;
• In JGrasp, click on Tools menu -> JUnit -> Configure
• For ‘JUnit Home’, click on Browse and choose where [Link] and
[Link] are stored. Once located click ‘Choose’, then click OK,
as shown below;

JUnit is configured and you are ready to write unit tests in JGrasp.

PAGE 416
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

Debugging using JDB


We often refer to the term debugging, which occurs as a consequence of successful
testing. That is, when a test case uncovers an error, debugging is the process that
results in the removal of the error. Although debugging can and should be an
orderly process, it is still very much an art. As a software engineer, you are often
confronted with a “symptomatic” indication of a software problem as you evaluate
the results of a test. That is, the external manifestation of the error and its internal
cause may have no obvious relationship to one another. The poorly understood
mental process that connects a symptom to a cause is debugging.

Shneiderman states the following about debugging:


“Debugging is one of the more frustrating parts of programming. It has elements of
problem solving or brain teasers, coupled with the annoying recognition that you
have made a mistake. Heightened anxiety and the unwillingness to accept the
possibility of errors increases the task difficulty. Fortunately, there is a great sigh
of relief and a lessening of tension when the bug is ultimately . . . corrected.”

Let us look at the using Java’s debugger [jdb] to debug a program. Java’s debugger
comes as part of the Sun's Java Development Kit. JDB is very simple to use,
lightweight and being a command-line tool, is very fast. By the way it is
similar to gbd used in C. There are a number of common JDB commands you
will use when debugging your code, these are;

step
next
cont
stop in/at
clear
step up
up/down
where
print/dump

To show you how to use this debugger, let us write a very simple test program.
public class JDBTest{
private int var1;
private int var2;

public JDBTest(int var1, int var2){


this.var1=var1;
this.var2=var2;
}

PAGE 417
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

public static void main(String[] args){


JDBTest ourjdb=new JDBTest(1,2);
[Link]("In main.. and about to call foo1");
ourjdb.foo1();
ourjdb.foo2(3, 4);
ourjdb.foo3(4, 5);
ourjdb.foo4();
ourjdb.foo5();
}

public void foo1(){


[Link]("I am in foo1...");
[Link]("I am still in foo1...");
[Link]("Yes, I am still in foo1...");
}

public int foo2(int a, int b){


return a + b;
}

public JDBTest foo3(int varX, int varY){


JDBTest obj = new JDBTest(varX, varY);
[Link]();
return obj;
}

public void foo4(){


[Link]("I am in foo4 ");
}

public void foo5(){


JDBTest objA = new JDBTest(5, 6);
synchronized(objA){
[Link]("I am in foo5 and accessing objA's fields: var1=" +
objA.var1 + ", var2=" + objA.var2);
}
}

private void reset() {


var1 = 0;
var2 = 0;
}

Now, if you are wanting to debug your program, you need to compile it and tell the
compiler to add debugging information to the generated class file. You do this as
follows;
java –g [Link]

Notice the –g option. You must include this. Next, we need to connect the debugger
to the Java Virtual Machine (JVM). There are a number of ways of doing this. I
will illustrate the simplest way.

PAGE 418
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

To establish the connection between the JDB and the JVM, open your command
line and type in;
jdb JDBTest

What is happening here? You are launching the debugger with the class you are
testing, in our case JDBTest. The debugger will also launch the JVM. Here is a
screen capture illustrating the process;

At this point, the JVM is not yet started. You need to invoke the run command at
the JDB prompt for the JVM to be started. Typing in the command, you will see
your program execute through to its completion. In order to debug your code you
need to establish break points, which will result in your code stopping execution at
a particular point.

To set a breakpoint at a particular line number type:


stop at <class name>.<line no>

or to set a breakpoint on a particular method or variable type:


stop in <class name>.< method name | variable name>

To illustrate this, let us set a break point in the main method before running the
program. So, using the command:
stop in [Link]

Now that you have set a break point, you can run your program. It will launch the
JVM and execute until it reaches the breakpoint you have just set. So, invoking the
run command results in the following;

PAGE 419
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

Notice, the JDB allowed the JVM to run. Execution stopped at the breakpoint
position you set, namely the first line in the main() method. What is important to
note is that this line is the line that is about to be executed. Also observe that the
JDB prompt has now changed from > to main[1] indicating that you are currently
debugging the main Java thread.

There are a number of commands you can issue now (see the table earlier). Let us
look at one of them. To see the source code around the breakpoint use the list
command;

The line that is going to be executed is marked by =>. Also, we see 4 lines of
source before and 5 after the current line. Incidentally, the JDB will be able to show
the source when list command is given, only if the source of the class is in the
current working directory.

Now if you want to actually execute the line (i.e. to step), but not run to the end of
the program then issue the next command at the prompt;

PAGE 420
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

The next command allows one line in your source to be executed, and then stops. If
the line has a method call, that call will be completed too. To enter a method when
it is called, you need to use the step command. If you have been following along,
then type next once again, which will execute the next line. Now, the new line that
is about to be executed is a call to the foo1() method. To trace into this method,
invoke the step command. If you type next it will execute the complete method,
so make sure you type step;

You have now entered the method foo1(), and paused at its first line. You can step
through the method’s code by once again using the next command. What if, at any
point within this method foo1() you do not want to execute each line of code by
invoking next, but would like to run it all and then go back to the caller (main() in
our case)? Well, what you do is issue the step up command;

Notice in this above screen capture we invoked the debugger’s set up command.
The debugger ran each line within method to its end. It exited the method and then
paused at the next line within the calling method. In our example we have paused at
line 15 within the main() method and are waiting to run method foo2(). As you
already know, if you want to just run this method, you invoke the next command.

PAGE 421
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

However if you want to step into this method and run each statement within it, you
would invoke the step command.

It is interesting to note that it is possible to step through the actual byte code of
your program. This is beyond the scope of this course, so I will not demonstrate it
suffice to say that it is possible.

Another interesting debugger command is where.

What this command does is tell you what the current call stack is. Look at the
screen capture above. When we first typed the command we see that the program
counter is pointing to line 15 in the main() method. Next, execute the step
command so that you enter the foo2() method. Once you have done this, invoke
the where command again. Notice, this time we see, from the stack trace, that we
are in the method foo2() pausing at line 28, which was called from within the
main() method. How do you execute all the statements within foo2()? Yup, by
using the step up command. Go ahead and do this. You should be back in the
main() method. Now work out how to step into the foo3() method. Hint:[next,
step]

Now that you are in foo3(), you should be paused on line 32,
JDBTest obj = new JDBTest(varX, vary);

Execute this line [next]. At this point, an instance of JDBTest is created and a
reference to it is held in the variable obj. Let us learn a new command that will
allow us to examine this instance. This is achieved by using the print command.
Type in the command print and the object instance you want to observe. For our
example: print obj

PAGE 422
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

We can even look at this particular object’s instance variables using the same
command. Type in print obj.var1 then print obj.var2. You should see the
values held by these instance variables displayed. This is illustrated below;

Interesting to note: We see that, printing obj.var1 and obj.var2 shows their
values, but do not see them when obj itself is printed. However, there is a
command you can use to see the full details of an instance. This is the dump
command. So, enter this command together with the object instance you wanting to
‘dump’. For our example type; dump obj. You should see something along the
following lines;

It is all very well being able to see what values are in an object instance, but how
do you see the values of all local variables, including the arguments passed into a
method? You make use of the locals command. So, go ahead and type locals.
You should see something similar to this;

PAGE 423
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

If you want to see where in the code a particular field is being accessed or
modified, you use watch command:

You can now let the program continue execution and will be able to see if the field,
in our case JDBTest.var1 is being modified. But before doing so, let us look at
another command, monitor. This command takes on another command as an
argument and executes this latter command whenever the program is stopped. The
points at which execution is stopped are:
• When a breakpoint is hit.
• When a field access/modification watch-point is hit.
• When next, step or step up commands are invoked.
• When a method is entered/exited while tracing of methods is ON.

To demonstrate this, assign the list command as an argument to the monitor


command. Once you have done this you need to continue running the program, as it
has halted by invoking the cont command. So your sequence of commands after
you entered the watch command earlier is;
monitor list
cont

Your screen should look something like the following;

PAGE 424
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

‘Frikkin awesomeness!!’. The cont command causes the program to execute until
a breakpoint or watch-point is hit, or if a method is entered or exited while method
tracing is on. In our example, we hit the watch-point for the field JDBTest.var1,
which we had set earlier. Execution stopped just when JDBTest.var1 is about to
be modified. Also, since we set the list command in monitor we see that as soon
as the program stops as a result of hitting the watch-point for JDBTest.var1 the
list command is automatically executed listing the source statement where
JDBTest.var1 is being modified. In our example JDBTest.var1 is being set to 0.
Incidentally, if no command is passed to monitor, then the list of currently set
commands under monitor along with their 'monitor number' is displayed. This is
illustrated below;

As we just typed in the command monitor it printed out all the currently set
commands associated with monitor. In our instance it is only one, namely list.

Once you have set a command in monitor, it is possible to remove that command
should you no longer require it. To do this use the instruction unmonitor together
with the ‘monitor number’ of the command you want to remove. So, in our
example if you want to remove the list command from the monitor you would
type in;
unmonitor 1

PAGE 425
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

Where 1 is the ‘monitor number’ that was assigned to the list command when it
was originally set. Below is a screen capture of us removing the list command
from monitor;

In the same fashion, you are able to remove any break point you may have set. The
chances are you do not remember all the break points you may have set, so to view
each of them you make use of the clear command. This is illustrated below;

You have only set one. To remove this break point, or any other for that matter, you
once again use the clear command but this time passing it the actual break point
you want to remove. So in our example you would type the following;
clear [Link]

Here is the screen capture illustrating the process;

Your breakpoint has now been removed.

Should you want to remove any watches, use the unwatch command, like so;
unwatch JDBTest.var1

You may have had enough working in the JDB, so to exit it you simply use the
exit or quit commands.

You should now have a really good idea as to how to use the Java debugger to
assist in debugging all your code. Do not underestimate the power of this utility.
Make use of it.

PAGE 426
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

Some of you may like to use some advanced features of Java’s debugger, so I will
very briefly discuss some of them below.

As mentioned earlier, you are currently debugging the main Java thread running in
the JVM. To see all the thread groups and threads executing in the JVM at the
moment, you invoke the threadgroups and threads commands in the JDB. First
let us look at all the thread groups running;

You will see that in our example there are two thread groups in existence. These
are system and main. The numbers next to them is their id which has been
allocated to each of them. Let us list all the individual threads that are running in
these groups. Go ahead and type threads;

Here, we see that the thread group system has four threads, namely Reference
Handler, Finalizer, Signal Dispatcher and Attach Listener. The first two
are in waiting state, whereas the Signal Dispatcher and Attach Listener are
in a running state. The thread group main has only one thread, namely main,
which is also in running state. Incidentally, this main thread is the one we have
been debugging in all our examples.

Another thing we can do is list all the classes that have been loaded in the JVM. To
do this we use the classes command. Here is a partial screen shot of our example
as there are so many loaded;

PAGE 427
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

To see more details about a particular class, you use the class command together
with the fully qualified class name you want to look at. For example;
class [Link]

In our screen capture above, notice we are looking at our class JDBTest and the
class [Link]. I think the output is self-explanatory.

To see more internals of a particular class, use the methods and fields commands
together with the fully qualified class name. Let us look at all our methods in our
class, which is currently loaded in the JVM. To do this type:
methods JDBTest

Here is the screen capture after issuing this command;

PAGE 428
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

Notice, all the methods we defined are listed together with those methods inherited
from any super classes. Observe; the listing displays the method’s complete
signature.

Let us now look at all the fields defined within our class i.e. the class’ member
variables. To do this type;
fields JDBTest

Awesomeness!! Our member fields are listed.

Another really neat advanced feature is being able to trace the entry and exiting of a
method call. To do this you would invoke the following command sequence;
trace methods
cont

Here is a screen capture illustrating the process;

PAGE 429
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

Invoke cont again;

I think you get the point. Carry on a doing this a few times and notice that the
execution stops whenever you enter or exit a method. The full sequence is
illustrated below;

PAGE 430
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

Once you have set a trace, you can also ‘unset’ it. To do this invoke the command;
untrace methods

Go ahead and do this.

To see the information regarding the monitor associated with an object, use the
lock command passing the object instance name;
lock obj

To see all monitors owned by the current thread and what monitors, if any, it is
waiting for use the threadlocks command:

To see the stacks of all threads, use the where all command;

That concludes our discussion on the Java debugger. All that you have done here
should give you are very good grounding in using this utility during development.

PAGE 431
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

CONCLUSION
Java is an extremely huge topic. Look at Swing for instance. Single books have
been written on this topic. The concepts and techniques I have taught you on this
course should provide you with enough knowledge and ammunition to write really
good applets and programs. It is now up to you to go and study this Java field
further in order to gain maximum benefit. Other advanced topics that you should
now go and learn (naturally after fully understanding the content of this
introductory course) are stand-alone topics such as;

2D Graphics
IDL
Internationalization
JavaBeans
Java Native Interface
JDBC Database Access
Reflection
RMI
Security
Servlets
Web services
Java FX
Sound
and so much more…….

PAGE 432
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

JAVA LANGUAGE KEYWORD DEFINITIONS


abstract
This is the type modifier keyword that is only used with classes and
interfaces. It is used to mark a class or interface as a generic model with the
sole purpose to be extended by a subclass. C programmers have no similar
construct.

boolean
A basic data type that represents only one of two values: true or false. Both
true and false are also keywords. The boolean data type uses only 1 bit of
storage. The boolean type in Java eliminates the need for the common C and
C++ practice of using #define to allow true and false to stand for not-0 and 0,
respectively.

break
A control flow keyword used to exit from a do, for, or while loop that
bypasses the normal loop condition. It can also be used to exit from a switch
statement. In nested loops, the break always terminates the innermost loop.

byte
A basic data type that represents a single byte as an 8-bit signed value.

byvalue
Reserved for future use.

char
A basic data type used to declare character variables. A Java character is
different from an ASCII character. Java uses the UNICODE character set,
which is a 16-bit unsigned value. Java is very explicit about the size of all
types. This aids portability, as there are no differences between the size of
basic data types on different platforms. This also makes the sizeof() macro
obsolete.

case
A control flow keyword that is part of the “switch” expression. The case
keyword is used to designate a single value (or “case”) out of many in the
entire switch expression. Also see switch.

PAGE 433
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

catch
A control flow keyword that is part of the Java exception model. Exceptions
are a mechanism for error-handling and when used properly can significantly
increase an application’s robustness. The model is based on the idea that
error conditions can be recognized by both the application and the system
and an appropriate exception is “thrown.” The application has the ability to
handle such “exceptions conditions” by using the catch keyword and
providing an error handler. The catch keyword is always followed by the
exception to catch and the block of code that is the exceptions handler. The
catch keyword and the error handler are often strung together in a series to
handle multiple types of exception conditions.

class
A declaration keyword that declares a new user-defined type. Implements the
central concept of object-oriented programming—encapsulation.

continue
A control flow keyword used to bypass the body of a loop and return to the
loop’s test condition.

const
Reserved for future use.

default
A control flow keyword that is part of the “switch” statement. See case. The
default keyword is used to designate the “default case” to execute in no other
“case” as appropriate. See also the switch keyword.

do
A control flow keyword used in a loop expression. The do is specifically
used when the loop should be executed once before the loop condition is
tested.

double
A basic data type used to declare double variables. A Java double is 64 bits
and conforms to IEEE 754.

else
A control flow keyword that is part of the “if” expression. See if. The else
keyword designates a block of code to be executed when the if condition
evaluates as false.

float

PAGE 434
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

A basic data type for declaring float variables. A float is 32 bit and conforms
to IEEE 754.

extends
A declaration keyword that declares that a class is derived from a superclass
and therefore “extends” the superclass.

false
A boolean value that represents “not true.”

final
A method and type modifier keyword that is similar to the const keyword but
much broader in scope. The final keyword can be applied to classes,
methods, and variables. It marks a class as never having subclasses (never
been extended), a method as never being overridden, and a variable as
having a constant value.

finally
A control flow keyword that is part of the Java exception model. The finally
keyword ensures that a block of code is run whether or not an exception
occurs. In fact, the finally code is executed even if there is a return in the try
block.

for
A control flow keyword that is used in a loop expression. The for loop is the
most common type of loop and is most often used when the exact number of
iterations is either a constant or a simple expression. The for loop allows for
automatic initialization and incrementation of a counter variable.

if
A control flow keyword used to perform a branch or decision point. The else
keyword may be used as part of the if expression.

instanceof
An operator that returns true if the class is an instance of a specifier class
type.

interface
A declaration keyword that creates an abstract class that defines a high-level
behavior via a set of methods that multiple classes can implement.

implements

PAGE 435
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

A declaration keyword that declares that a class will implement the class or
interface that follows.

import
A keyword that imports a package.

int
A basic data type for declaring integer variables. A Java integer is a 32-bit
signed value. A basic data type used to declare long integer variables. A Java
long is a 64-bit signed value.

native
A method modifier that signifies that the method is implemented in a
platform-dependent language (like C) and not Java. This capability is
important for several reasons.
1. Performance. You have the ability to code performance-sensitive areas of
your Java application in platform-dependent code that is both compiled and
optimized for your specific processor.
2. Reuse. The ability to reuse existing platform-dependent utilities and
libraries. This is especially useful for the large volume of C and C++ utility
programs and libraries available.

null
A value that denotes “no instantiated object” or “no object.”

package
A declaration keyword that creates a new namespace for all classes within
the package. The package also permits the default access specifier the
friendly sharing of class data members among all classes within the package.

private
An access modifier keyword for both types and methods. A key component
of classes with the purpose of allowing class data to be protected. The private
keyword limits access to a variable or method that follows it to only the
methods within the class.

protected
An access modifier keyword for both types and methods. The protected
keyword is similar to the private keyword except that it allows access to the
data and methods from its subclasses. The package command changes the
meaning of the protected keyword.

PAGE 436
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

public
An access modifier keyword for both types and methods. The public
keyword makes classes identical to structures (essentially allowing access to
both the methods and data externally).

return
A control flow expression used to pass execution from a called function back
to the calling function. The return keyword can optionally be used to return a
value back to the calling function.

short
A basic data type used to declare short integer variables. A Java short is a 16-
bit signed value.

static
Since Java is a pure object-oriented language, the static keyword has a
restricted meaning. The static keyword can be applied to either class data
variables or class methods. In both cases, it means that those methods or
variables apply to the entire class and not just instances of the class.

super
An uninstantiated object (equivalent to a pointer) to the parent class or
superclass.

switch
A control flow keyword used to implement the multi-way decision that tests
whether an expression matches one of the following “cases.” See also the
case and default keywords. Each case must be a constant integer value.

synchronized
A method modifier keyword that ensures that the use of a method will be
synchronized between multiple threads (if multiple threads exist). In essence,
it means that this function can only be run one thread at a time. The Java
language has built-in support for threads. Threads are similar to processes. A
process is typically a running program. The difference between a process and
a thread is that each process is provided with its own memory space and
processor state (like registers and stack), whereby threads share the memory
and processor state of the spawning process. The benefit of threads is a
measure of asynchronicity and simultaneous execution. A good example of
the utility of threads would be a fileserver (or any server for that matter). A
server is a program consisting of many procedures that are activated by client
programs. There are usually many clients making requests of a single server.

PAGE 437
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

In a nonthreaded server, the client requests are queued up and processed


sequentially. In a threaded server, the server spawns a new thread for each
request, which provides a quicker response time to most users. Second, the
threaded server is always read to perform a new action and is thereby never
stuck in a low-priority job when a high-priority job comes along. Threading
is also ideal for graphical user interfaces where you spawn threads for key
functionality and therefore keep the application always responsive to the
user.

this
An uninstantiated object (pointer) to the current object.

threadsafe
A type modifier that indicates that a variable will not be changed by some
other thread while one thread is using it. This allows the compiler to perform
some optimizations like the caching of instance variables in machine
registers.

throw
A control flow keyword that is part of the Java exception model. The throw
keyword is used to throw an exception.

throws
The throws keyword is part of the Java exception model. The throws
keyword is added to the method prototype if the method throws any
exceptions. Just as strict type checking extended the function prototype, the
throws keyword extends the function prototype to the Java exception model.

transient
A type modifier used with persistent objects.

true
A boolean value that represents true.

try
A control flow keyword that is part of the Java exception model. The try
keyword wraps or surrounds a block of code that we want to “try” and that
may throw an exception. The throws keyword lets developers know what the
method will throw by examining its prototype.

PAGE 438
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

void
A basic data type used to designate methods or functions that have no return
type and return no value.

while
A control flow keyword used to implement a loop that continues “while” an
expression is true. When the expression evaluates to false, the loop is
terminated.

PAGE 439
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

GLOSSARY OF TERMS
.au File
AUdio File. A standardized format popularized by SUN for storing audio
data.

.avi file
Audio Video Interleave format file. An AVI file normally contains a series of
graphical images and associated audio that can be played as a movie.

.class File
See also .javafile. The bytecode result of running the Java compiler on a
.java file.

.dll file
Dynamic Link Library. A code library that can be linked to an applicationat
run time rather than statically at compile time.

.gif file
Graphics Interchange Format file.

.html, .htm file


HyperText Markup Language file.

.jar file
A Java Archive format file. See also JAR.

.java file
Java language source file. A .java file normally contains Java language
commands.

.jpg file
Joint Photographic Exports Group file. A file containing a graphics image.

.mpg or .mpeg file


Motion Picture Experts Group.

.midi file
Musical Instrument Digital Interface. A file containing audio data.

PAGE 440
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

.so file
Shared Object library. Similar to a Windows Dynamic Link Library.

.wav file
Waveform file. A file containing waveform audio data.

ACL
Access Control List.

ActiveX
A term used to describe a set of technologies based on Microsoft COM. See
also COM, DCOM, and OLE.

Adapters
A set of classes that implement specific EventListener interfaces and are
used as a basis to extend from.

applet
A small Java program not meant to be run on its own but rather embedded in
a HTML document.

appletviewer
A JDK application that allows developers to execute applets without using a
browser.

Application
A Java program that can be run on its own. See applet.

Asynchronous
Not synchronous.

Attribute
A variable contained within a class.

Authentication
The processes of validating a user login. Normally done through a
username/password combination.

PAGE 441
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

Authorization
The process of granting or denying access to resources based on a username
or other security token.

AWT
Abstract Windows Toolkit.

Bound Property
A property that fires an event whenever it is modified.

Breakpoint
A location in a program where execution can be stopped during debugging.

Builder Tool
A visual application for assembling Java Beans into an application.

CBC
Cipher Block Chaining. The process of encrypting a block of data by feeding
back into the algorithm the previously encrypted or decrypted block of text.

CDE
Common Desktop Environment.

CFB Cipher Feedback Mode.


An encryption/decryption technique using the CBC technique and a bit
vector to encrypt or decrypt a block of text.

CGI Common Gateway Interface.


An interface implemented in HTTP servers that allows access to server
resources.

Cipher
An object or algorithm capable of encryption or decryption.

CLASSPATH
An environment variable that defines where to look for Java .class files.

Client
Within RMI, a process that initiates a remote communication. Within CORBA,
a program that obtains an object reference from an ORB.

PAGE 442
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

COM
Common Object Model. See also DCOM.

Compiler
A tool for turning raw code into an executable or compiled image format.
Javac is such a tool.

Component
Components are the building blocks of GUI-based applications and are
normally derived from the Component class.

Confidentiality
The process of hiding data from external view.

Constrained Property
A property that fires an event whenever it is modified. Constrained property
modifications can be vetoed by any of the event listeners.

Constructor
A Java method that is called when an object is created.

Containers
Components that are used to store other components. An example of a Java
container is the Panel (JPanel) class.

Containment
Security containment is the process whereby applications are only allowed to
perform certain functions.

CORBA
Common Object Request Broker Architecture. CORBA is a standard
architecture for describing distributing objects over the Net. CORBA objects
can be written in Java, C, C++, or other languages.

CPP
Cryptography Package Provider.

PAGE 443
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

Customizer
An AWT panel that allows users to perform more complex modification of a
Bean.

DCE
Distributed Computing Environment.

DCOM
The Distributed Common Object Model.

Deadlock
The process whereby one application, thread, or process is stopped from ever
completing its task due to another application, thread, or process holding
forever some system resource that the first requires. Deadlock can be
summed up in the following simple example, whereby Thread A requires a
resource held by Thread B, which requires a resource held by Thread C,
which in turn requires a resource held by Thread A.

Debugger
A tool for testing and examining code and variable states for the purpose of
finding and fixing bugs. See also jdb.

Decrypt
The process of taking cipher text, a key, and a cipher and decrypting the text
such that the result is the original stream of bytes.

Design Area
The part of a builder tool where the user assembles the Beans.

Destructor
In C++ and other object-oriented programs, a method called when a class is
destroyed, which often contains “cleanup” code.

Dialog
A Java AWT component that defines a window with a border and is
normally a child of another window.

Digital Signature
Digital signatures are used to detect unauthorized modifications to data and
files and to authenticate the identity of the signer. See also X509 Certificate.

PAGE 444
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

Double-buffering
Double-buffering is a drawing technique used for achieving smooth
animation by drawing to an offscreen graphics context or object and then
using that object to render the image.

DSA
Digital Signature Algorithm.

Encapsulation
The process of hiding the internals of an object.

Encrypt
The process of taking input data (clear text), a key, and a cipher and
encrypting the text such that the result is a meaningless stream of bytes, often
called ciphertext.

Event
An external or internal action that is delivered asynchronously to an
application. It is also a notification that can be produced by a Java Bean.

Event Listener
Any of several classes that register to receive events.

Exception
An event that occurs outside the normal processing of an application or
applet.

Feature
A property, method, or event of a Java Bean.

Field
A data element associated with a class or an object.

Frame
A Java AWT component that defines a top-level window with a border and
optionally a menu.

GUI
Graphical User Interface.

IDL

PAGE 445
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

Interface Description Language. IDL defines the methods and attributes of a


CORBA Object. IDL definitions are language independent. See also CORBA.

idltojava
A Java JDK tool for translating CORBA IDL into equivalent Java language
constructs.

IIOP
Internet Inter-ORB Protocol. See also CORBA.

Inheritance
When a subclass is created or derived from a parent or superclass we say the
new class inherits the methods and data of the parent class.

Instantiate
The process of constructing an object from its class definition.

JAR
Java ARchive. The Java Beans packaging mechanism. A JAR is a zip-
compressed archive that can contain class files, images, and other resources
required by Beans. Any Java application or applet, not just Java Beans, can
use JAR files.

jar
Java ARchive. A JDK application that takes Java class files and creates a
single, potentially compressed, archive from them. See also JAR.

java
The java interpreter. A tool for running java .class files. The Java interpreter
runs or executes Java bytecode applications. See also .class.

Java Bean
A reusable software component that can be visually manipulated by a builder
tool.

javac
The Java Compiler. The Java compiler translates Java programs into
bytecodes. See also .class.

PAGE 446
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

javadoc
A JDK application that parses Java source code and produces documentation
from it.

javah
A Java JDK Utility that creates C/C++ style header files from Java class files
for use while developing Native Methods. See also JNI.

javakey
A JDK application that manages the Java security database, including
manipulating entities, keys, and certifications. See also Digital Signature,
Certificate, Entity.

javap
The Java class disassembler. Javap can be used to disassemble bytecode and
print out human-readable representations of that bytecode. A Java JDK Utility
that can be used to create method and variable signatures, which can then be
used as references to Java methods and variables from a native method.

JavaScript
A scripting language based on Java that allows HTML authors to add simple
scripts to their pages.

JCE
The Java Cryptography Engine. The JCE provides support within the Java
environment for public key/private key encryption.

jdb
The Java Debugger. A tool for testing and debugging Java applets and
applications. The Java debugger allows developers to step through code and
examine and set variables. See also java and javac.

JNI
Java Native Method Interface.
JVM
The Java Virtual Machine.

Layout manager
Any of several classes that implement specific policies for laying out
components within a container. The GridBag class is an example of a layout
manager.

PAGE 447
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

link
The process of combining one or more object files with zero or more library
files to create an executable format file.

Marshalling
To place in methodical or proper order. Within CORBA or DCOM, the process of
translating structures and objects to a network-neutral form and then back
again. See also CORBA.

MD5
Message Digest 5.

Member
A constructor, field, or method of a Java class.

Member Variable
See Attribute.

Message Digest
A sophisticated form of a hashcode. A message digest is generated from a
file or message using a specific algorithm. Message digests are often used to
determine if a file or message has been corrupted during transport.

Method
A function that is associated with a class or object, or a function associated
with a Java Bean.

MIDL
Microsoft Interface Description Language.

MS-RPC
Microsoft Remote Procedure Call.

Multithreaded
Multithreading is the ability of a single process to spawn multiple,
simultaneous executions paths.

PAGE 448
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

Native Method
An external method, normally written in a language such as C or C++, but
callable from Java.

native2ascii
Native to ASCII Converter. A JDK application that converts a natively
encoded file into its ASCII equivalent using UNICODE notation.

OLE
Object Linking and Embedding. An early form of COM.

OMG
Object Management Group. A group of some 500 software vendor and user
organizations devoted to distributed object technology. See also CORBA.

OOP
Object-Oriented Programming.

ORB
Object Request Broker. The central component of CORBA that transfers object
requests and results between CORBA Clients and Servers. See also CORBA.

PEM
Privacy Enhanced Mail.

Pixel Picture Element.


Normally the smallest addressable unit of a given display device.

PKCS#5
Public Key Cryptology Standard #5.

Polymorphism
From the Greek poly meaning many and morphic meaning forms. Many
forms. In object-oriented programming, when one class has several methods,
all which have the same name but perform different functions, those methods
are said to be “polymorphic” to one another.

PAGE 449
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

Private Key
The unpublished portion of a public key/private key pair. Private keys are
used to digitally sign a message that will later be authenticated using its
associated Public key.

Property
A data element associated with a Java Bean.

Property Editor
An AWT component that can display and allow visual modification of a
specific data type. The property sheet to edit properties that have complex
data types uses property editors.

Property Sheet
The part of a builder tool that allows users to view and alter the properties of
a Bean.

Public Key
The published portion of a public key/private key pair. Public keys are used
to validate the integrity and sender of a message.

Reflection
The Java mechanism that allows one object to examine the structure of
another at run time. Reflection can be used to create objects, invoke
methods, and manipulate properties.

Remote Method
The Java mechanism that enables one Java object to call methods on another,
even if the two objects run on different machines.

Remote Object Registry


The Java application that enables an RMI client object to locate an RMI
server object.

Remote Procedure Call


A function invocation that is initiated from one process (called the client) but
is executed by another (called the server).

PAGE 450
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

Rmic
The Java utility that generates the stub and skeleton classes used by RMI.

RPC
See Remote Procedure Call.

RSA
A public key/private key algorithm named after its inventors, Ron Rivest,
Adi Shamir, and Leonard Adleman.

Serialization
The Java mechanism that allows objects to persist their data and running
state.

Server
A process that receives and handles remote requests.

SHA-1
Secure Hash Algorithm.

Skeleton
See stub.

SSPI
Standard Security Provider Interface.

Starvation
The process whereby one application, thread, or process is stopped from ever
gaining a resource that it requires due to another application, thread, or
process forever holding that resource. Starvation often leads to deadlock. See
also Deadlock.

Stub
A piece of machine-generated code that exposes a simple interface, but
implements a complex operation such as network communications.

Synchronous
Happening or reoccurring at the same time.

PAGE 451
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

Thread
A lightweight form of a process. One or more threads will share the memory
and execution environment of a single process and may all be executing at
once.

Window
A Java AWT Component that defines a top-level window with no borders
and no menubar.

WYSIWYG
What you see is what you get.

X509 Certificate
An X.509 certificate contains a number of fields including version, serial
number, issuer, and subject name, and is used to assign a Digital Signature to
a file, allowing that file to be authenticated.

PAGE 452
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

Index
@Documented, 202
@exception, 37, 40, 41, 44, 45
@FunctionalInterface, 199
-, 50 @Ignore, 410, 412, 414
@Inherited, 202
@link, 37, 38, 39, 41, 45
! @Override, 198
!, 54 @param, 37, 40, 41, 44, 45
!=, 52 @Retention, 203
@return, 37, 40, 41, 45
@Rule, 418
% @RunWith, 415
@SafeVarargs, 200
%, 50
@see, 37, 38, 39, 41, 44, 45
@since, 37, 38, 39, 41
& @Suite, 415
@SuppressWarnings, 199
&, 56 @Target, 203
&&, 54 @Test, 408, 409, 410, 412, 414
@throws, 37, 40, 41
* @version, 35, 36, 37, 39, 40, 41, 42, 44

*, 50
*/, 34
^
^, 56, 57
.
.au File, 442 |
.avi file, 442 |, 56
.class File, 442 ||, 54
.dll file, 442
.gif file, 442
.html, .htm file, 442 ~
.jar file, 442
~, 29, 56, 59
.jpg file, 442
.mgp or .mpeg file, 442
.midi file, 442 “
.so file, 443
.wav file, 443 “is-a” relationship, 128

/ +
/, 50 +, 50
/*, 34 ++i, 53
/**, 34
//, 34 <
<, 52
? <<, 56, 59
? operator, 86 <=, 52

@ =
@After, 410 ==, 52
@AfterClass, 410
@author, 35, 36, 37, 39, 40, 41, 42, 44 >
@Before, 410, 418
@BeforeClass, 410 >, 52
@Category, 418 >=, 52
@deprecated, 37, 38, 39, 41, 42, 45, 199 >>, 56, 58, 59
@Deprecated, 199 >>>, 56, 59

PAGE 453
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

A B
abstract, 27, 114, 128, 131, 140, 435 BevelBorder, 398
AbstractBorder, 398 big endian, 312
AbstractCollection, 243 BitSet, 233
Abstraction, 112 bitwise AND operator, 56
AbstractMap, 260 bitwise OR operator, 56
AbstractSet, 244 boolean, 27, 28, 52, 435
access modifier, 115, 116 BorderLayout, 359
ACL, 443 borders, 397
ActionEvent, 273, 275, 282, 283 Bound Property, 444
ActionListener, 271, 273 break, 27, 80, 87, 97, 435
actionPerformed(), 273 breakpoint, 421, 422
ActiveX, 443 Breakpoint, 444
Adapters, 443 browser, 10, 22, 23
add(), 272, 356 buckets, 227
addActionListener(), 275 BufferedReader, 310, 311
addElement(), 219, 224 BufferedWriter, 321
addition, 50 Builder Tool, 444
addTest(), 416 byte, 27, 28, 29, 30, 31, 56, 304, 435
addTestSuite(), 416 ByteArrayInputStream, 313
AdjustmentEvent, 282, 283 bytecode, 9, 10, 18
AdjustmentListener, 271 byvalue, 435
AND operator, 56
andNot(), 235
annotation, 198, 201
C
anonymous class, 149, 279 capacity(), 69, 222
applet, 22, 23, 294, 298, 300, 443 case, 27, 87, 435
Applet, 21, 149, 150, 294, 295 casting, 104
appletviewer, 22, 443 catch, 27, 63, 163, 164, 167, 168, 169, 436
Application, 443 CBC, 444
arguments, 117 CDE, 444
arithmetic operators, 50, 51 CFB Cipher Feedback Mode, 444
ArithmeticException, 162, 172 CGI Common Gateway Interface., 444
array, 98 char, 27, 32, 33, 435
arraycopy(), 101 character literals, 32
ArrayIndexOutOfBoundsException, 162, 164, 172 [Link](), 330
ArrayList, 255 CharArrayReader, 310
array-of-array, 101 CharArrayWriter, 321
Arrays, 217 charAt(), 66
ASCII, 32, 304, 305, 306 check boxes, 369
assert, 27 Cipher, 444
Assert class, 413 class, 27, 114, 116, 274, 357, 436
assertEquals, 413 class modifiers, 114
assertFalse, 413 ClassCastException, 162, 207
AssertionError, 404, 405 ClassNotFoundException, 162
AssertionException, 413 CLASSPATH, 15, 16, 107, 108, 444
Assertions, 404 clear, 428
assertNotNull, 413 clear(), 234
assertNotSame, 413 Client, 444
assertNull, 413 clone(), 101
assertSame, 413 close(), 311
assertTrue, 413 Collection interface, 240
assignment statements, 60 Collection Interface, 239
Asynchronous, 443 COM, 445
Attribute, 443 combo box, 387
Authentication, 443 command line argument, 315
Authorization, 444 Comments, 34, 35
autoboxing, 157, 158 Comparable, 212, 265, 267
auto-unboxing, 157 Comparable interface, 145
AWT, 353, 444 compile, 19
AWTEvent, 282 compiler, 20, 30, 34
Compiler, 445

PAGE 454
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

complement, 28, 29, 56, 59 do, 27, 436


Component, 445 do while, 94
ComponentAdapter, 278 dot(.) operator, 65, 117
ComponentEvent, 282, 283 double, 27, 32, 436
ComponentListener, 271 Double-buffering, 447
CompoundBorder, 398 do-while, 80, 90
concat(), 68 DSA, 447
concurrent threads, 183
Confidentiality, 445
const, 27, 49, 436
E
constants, 49 elementAt(), 219
Constrained Property, 445 elements(), 228
constructor, 65, 120 else, 27, 82, 436
Constructor, 445 empty(), 225
constructor method, 118 EmptyBorder, 398
consume(), 292 Encapsulation, 112, 447
Consuming, 289 Encrypt, 447
cont, 427 endian, 312
container, 272 ensureCapacity(), 69, 222
ContainerAdapter, 278 enum, 27
ContainerEvent, 282, 283 enum type, 191
ContainerListener, 271 enumeration, 191, 192, 197
Containers, 445 Enumeration, 221
Containment, 445 EOFException, 162
containment hierarchy, 355 Equal to operator, 52
contains(), 220, 228 equality in Strings, 66
continue, 27, 80, 97, 436 equality operator, 66
CORBA, 445 equality operators, 52
countTestCases(), 416 equals(), 66, 67, 159
CPP, 445 equalsIgnoreCase(), 67
currentThread(), 174 equalsIgnoreCase()., 66
Customizer, 446 erasure, 211, 216
Error class, 162
D escape characters, 78
escape sequences, 33
daemon threads, 188 EtchedBorder, 398
data format, 303 Event, 447
data race, 183 event handlers, 292
DataInputStream, 312, 313, 314, 316, 326 event handling, 149
DataOutputStream, 326 Event Listener, 447
DCE, 446 Event listeners, 271
DCOM, 446 EventObject, 281
deadlock, 184 EventObject class, 271
Deadlock, 446 Exception, 447
Debugger, 446 Exception class, 162
debugging, 419 exception handling, 161
Decimal, 30 exit, 428
DecimalFormat, 139, 323, 325 extends, 27, 126, 437
Decrypt, 446
default, 27, 87, 115, 116, 436
defaultWriteObject(), 339
F
delete(), 69 fail, 413
deleteCharAt(), 69 false, 27, 28, 52, 54, 437
delimiter, 70 Feature, 447
deserialization, 338 Field, 447
Design Area, 446 File, 326, 327
destroy(), 295 FileFormatException, 167
Destructor, 446 FileInputStream, 310, 313, 314, 319
Dialog, 446 FileOutputStream, 313, 337
Dialog boxes, 389 FileReader, 310
Dictionary, 226 FileWriter, 323
Digital Signature, 446 FilterInputStream, 312, 313
division, 50 FilterReader, 310

PAGE 455
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

FilterWriter, 321 IIOP, 448


final, 27, 49, 114, 130, 140, 147, 437 IllegalArgumentException, 227
finally, 27, 169, 298, 307, 437 IllegalThreadStateException, 188
firstElement(), 219 immutable, 64, 152
float, 27, 31, 32, 49 implements, 27, 437
floating-point, 31, 32, 50 import, 27, 108, 438
FlowLayout, 357 indexOf(), 67, 220
FocusAdapter, 278 IndexOutOfBoundsException, 220
FocusEvent, 282, 284 inequality operator, 52
FocusListener, 271 inheritance, 126, 128
for, 27, 80, 90, 92, 283, 297, 317, 382, 437 Inheritance, 112, 448
for-each, 80, 90, 95 init(), 295
format string, 74, 76 initCause(), 170
Frame, 447 inner class, 148, 149
InputEvent, 282, 284
InputStream, 305, 306, 307, 311, 312, 313
G InputStreamReader, 306, 308, 310, 311, 313, 317, 319
garbage collection, 189 insert(), 69
gc(), 190 insertElementAt(), 219
generic types, 208 Insets, 360
generics, 207 instanceof, 27, 437
get(), 234 Instantiate, 448
getCause(), 170 int, 27, 30, 31, 49, 438
getChars(), 66 interface, 27, 140, 145, 147, 437
getClass(), 169 interpreter, 9
getFilePointer(), 335 IOException, 163
getID(), 282 isAdjusting(), 384
getInsets(), 360 isEmpty(), 228
getMessage(), 169 ItemEvent, 282, 283
getName(), 169, 174, 416 ItemListener, 271
getProperty(), 231
getSource(), 281 J
getText(), 363
getValueIsAdjusting(), 384 JApplet, 354
goto, 27 jar, 448
Greater than operator, 52 JAR, 448
Greater than or Equal to operator, 52 java, 448
GridBagLayout, 378 Java Bean, 448
GridLayout, 360 Java foundation classes (JFC), 353
GUI, 447 Java virtual machine (JVM), 9
GUI components, 353 Java Virtual Manager, 10
JAVA_HOME, 15, 16
Java’s debugger, 419
H javac, 19, 82, 448
HashMap, 261 javadoc, 35, 42, 44, 449
HashSet, 244 javadoc tags, 36
Hashtable(), 226 javah, 449
hasMoreElements(), 70, 221 javakey, 449
hasMoreTokens(), 70 javap, 449
hasNext(), 331 JavaScript, 449
heap memory, 64 JButton, 272, 365
heap space, 189 JCE, 449
Hexadecimal, 30 JCheckBoxMenuItem(), 389
HTML, 10, 22, 35, 297, 298, 300, 301 JComboBox, 354
Hypertext Markup Language, 10 JComponent, 362
jdb, 449
JDB, 419
I JDK, 13, 18, 35
i++, 53 JEditorPane, 378
IDL, 447 JFrame, 354
idltojava, 448 JGlassPane, 355
if, 27, 79, 81, 82, 437 JLabel, 363
if-else-if, 85 JLayered, 355

PAGE 456
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

JNI, 449 member class, 148


JOptionPane, 389 Member Variable, 450
JPanel, 272, 354 memory management, 189
JPasswordField, 378 menuCancelled(), 389
JRadioButtonMenuItem()., 389 menuDeselected(), 389
JScrollPane, 354 MenuListener, 389
JTabbedPane, 354, 395 menus, 389
JTable, 354 menuSelected(), 389
JTextField, 354, 378 Message Digest, 450
JTextPane, 378 metadata, 198
JUnit, 6, 406, 407, 408, 409, 410, 412, 413, 414, 415, 416, Method, 450
418 methods, 116
JUnit annotations, 409 MIDL, 450
JVM, 9, 10, 25, 449 MIN_PRIORITY, 178
mnemonic key, 365
modulus, 50
K monitor, 426
KeyAdapter, 278 Most Significant Bit, 28
KeyEvent, 282, 285 MouseAdapter, 278
KeyListener, 271 MouseEvent, 282, 286
keys(), 228 MouseListener, 271
MouseMotionAdapter, 278
MouseMotionListener, 271
L MSB, 28, 29, 30, 58
lastElement(), 220 MS-RPC, 450
lastIndexOf(), 67, 220 multicasting, 290
late binding, 130, 142 Multicasting, 289
Layout manager, 449 multi-catch, 171
layout managers, 357 multidimensional array, 101
length(), 234 multi-line comments, 35
Less than operator, 52 multiple inheritance, 140
Less than or Equal to operator, 52 multiplication, 50
LineBorder, 398 multithreaded, 173
link, 450 Multithreaded, 450
LinkedList, 251 mutator method, 118
list, 422 mutually exclusive threads, 181
List Box, 384
List Interface, 239, 250 N
list(), 231
listener interface, 271 named constant, 191
little endian, 312 narrowing, 105
load factor, 227 native, 27, 438
load(), 232 Native Method, 451
local class, 149 native2ascii, 451
locals, 425 nested class, 148
locking, 183 nested if, 84
logical AND operator, 54, 56 new, 27, 64, 118, 120, 165
logical NOT operator, 54 next, 422
logical operators, 54 nextElement(), 71, 221
logical OR operator, 54, 56 nextLine(), 330
long, 27, 31, 304 nextToken(), 70
lower bound wildcard, 216 nextXXX(), 331
NORM_PRIORITY, 178
NoSuchElementException, 220
M Not Equal to operator, 52
MalformedURLException, 162 notifyAll(), 185
Map, 257 NPAPI, 23
Map Interface, 239 null, 27, 189, 304, 438
Marshalling, 450 NullPointerException, 99, 162
MatteBorder, 398 NumberFormat, 323
MAX_PRIORITY, 178
MD5, 450
Member, 450

PAGE 457
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

O Q
Object Oriented, 25 quit, 428
ObjectInputStream, 313
ObjectOutputStream, 339
Octal, 30, 33
R
OLE, 451 race condition, 183
OMG, 451 radio buttons, 372
One’s Complement, 29, 56 RandomFileAccess, 335
OOP, 451 read(), 307
OpenJDK, 16 Reader, 311
Operators, 50 Reader class, 305
OR operator, 56 Recovery Testing, 402
ORB, 451 Reflection, 452
order of precedence, 61 regionMatches(), 67
OutputStreamWriter, 321 register listeners, 274
overload, 130 regular expression, 71
override, 126, 131 relational operators, 52, 83
remainder, 50
P Remote Method, 452
remote method invocation (RMI), 338
pack(), 364 Remote Object Registry, 452
package, 27, 106, 108, 109 Remote Procedure Call, 452
PaintEvent, 282, 284 remove(), 228
PARAM tag, 300 removeAllElements(), 222
parameter_list, 117 removeElement(), 221
parameterized tests, 416 removeRange(), 222
parameters, 116 replace(), 68
parseXXX(), 155 Resumption, 161
parsing, 70 return, 27, 80, 97, 439
peek(), 225 reverse(), 69
PEM, 451 Rmic, 453
Performance Testing, 403 RPC, 453
PipedInputStream, 313 RSA, 453
PipedReader, 310 run(), 174, 416
PipedWriter, 321 Runnable interface, 173
PKCS#5, 451 Runnable interface., 174
polymorphism, 129, 142 run-time errors, 161
Polymorphism, 112, 451 RuntimeException, 162, 163
pop(), 225
postfix expression, 53
postfix operator, 53
S
predefined constant, 191 Scanner, 5, 318, 324, 330, 331, 332
prefix expression, 53 scope, 62
prefix operator, 53 Security Testing, 402
primitive data types, 28, 33 seek(), 335
primitive wrapper classes, 317 self-typed, 191
printf(), 74, 76 SequenceInputStream, 314, 319
PrintWriter, 321, 322, 323, 329 Serializable, 341
private, 27, 115, 116, 131 serialization, 338, 339
Private Key, 452 Serialization, 453
Properties, 230 Server, 453
Property, 452 Set Interface, 239, 244
Property Editor, 452 set(), 234
Property Sheet, 452 setAlignment(), 358
propertyNames(), 232 setElementAt(), 219
protected, 27, 115, 116, 438 setEnabled(), 365
public, 25, 27, 114, 115, 116, 147, 439 setHgap(), 358
Public Key, 452 setLayout(), 357
push(), 224 setLength(), 69
put(), 230 setName(), 416
putAll(), 230 setPriority(), 174, 178
setProperty(), 230, 231

PAGE 458
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

setSize(), 222 testCount(), 416


setText(), 363 TextEvent, 282, 283
setVgap()\, 358 TextListener, 271
setVisible(), 364 this, 27, 119, 121, 175, 274, 440
SHA-1, 453 thread, 173
Shift left (arithmetic) operator, 56 Thread, 454
Shift right (arithmetic) operator, 56 Thread class, 173
Shift right (logical) operator, 56 thread priority, 178
short, 27, 31, 33, 439 threadgroups, 429
showConfirmationDialog, 390 threads, 173, 429
shuffle, 268 threadsafe, 440
size(), 220, 228, 234 throw, 27, 163, 164, 165, 166, 168, 440
Skeleton, 453 Throwable, 161
sleep(), 174 throws, 440
sort(), 145 TiledBorder, 398
SortedMap, 266 toCharArray(), 66
SortedSet, 266 token, 331
sorting, 265 tokens, 70
split(), 71 toLowerCase(), 68
SSPI, 453 Tool tips, 367
Stack, 224 toString(), 281
star seven, 9 toUpperCase(), 68
start(), 175, 295 transient, 27, 338, 440
startsWith(), 67 TreeMap, 263
Starvation, 453 TreeSet, 248
static, 25, 27, 120, 121, 122, 140, 147, 148, 338, 439 trim(), 68
static block, 121 trimToSize(), 222
static final, 146 true, 27, 28, 52, 54, 440
static import, 110 truncation, 325
step up, 423 try, 27, 163, 164, 168, 169, 440
stop(), 295 try-catch, 163
store(), 231 two’s complement, 28, 29, 30, 31
Stress Testing, 403 typecast, 30, 101, 145
strictfp, 27 typecasting, 30, 31
string concatenation, 64
StringBuffer, 68, 69
StringBufferInputStream, 314
U
StringBuilder, 68 unary minus, 50
Strings, 63 unbounded wildcard, 215
StringTokenizer, 70 unboxing, 158
StringWriter, 321 Unicode, 32, 33, 304, 306
Stub, 453 unsigned, 28, 32
subclass, 126 unwatch, 428
substring(), 65, 68 upper bounded wildcard, 214
subtraction, 50
subtype, 214
super, 27, 128, 129, 439 V
superclass, 126 valueOf(), 154, 155, 194
Swing, 353 values(), 194
switch, 27, 79, 87, 88, 89, 439 varargs, 74, 123
synchronized, 27, 68, 180, 183, 184, 439 variable, 28, 30, 31, 47, 48, 49
Synchronous, 453 variable arguments, 74
[Link], 305 variable-arity method, 123
[Link](), 190 variables, 25, 30, 47, 48, 121
[Link], 305 Vector, 218, 219, 220
[Link], 305 Virtual key codes, 285
void, 25, 27, 116, 441
T volatile, 27

Termination, 161
ternary operator, 86 W
test suite, 415 wait(), 185
testAt(), 416 warning(), 416

PAGE 459
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA

watch, 426 writeObject(), 339


WeakHashMap, 264 Writer class, 305, 321
where, 424 WYSIWYG, 454
while, 27, 80, 90, 441
white-space character, 70
widefp, 27
X
widening, 105 X509 Certificate, 454
wildcard, 214 XOR (Exclusive OR) operator, 56
Window, 454 xor(), 235
WindowAdapter, 278 xxxValue(), 153
windowClosed, 276
windowClosed(), 278
WindowEvent, 282, 284 Y
WindowListener, 271, 275, 278 yield(), 178
wrapper class, 151

PAGE 460
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018

You might also like