Practical Java Programming Guide
Practical Java Programming Guide
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
PAGE 3
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA
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).
Copyright Notice:
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”.
PAGE 7
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA
Java Program
Java API’s
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.
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.
PAGE 8
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA
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.
PAGE 9
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA
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
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;
PAGE 13
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA
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
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
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
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];
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.
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
PAGE 22
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA
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.
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
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
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
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
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
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;
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
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)
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.
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;
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.
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 */
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;
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 */
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;
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.
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.
PAGE 35
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA
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
5. Dating features
@since <version>
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
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
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.
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.
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
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)
PAGE 39
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA
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]
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.
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.
/**
* 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
/**
* 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;
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';
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
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
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;
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
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++;
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
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;
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;
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;
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;
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));
}
}
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.
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
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
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
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;
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;
PAGE 58
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA
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
:
}
PAGE 61
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA
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.";
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);
}
}
PAGE 62
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA
Do you understand how this is achieved? Well the method called is:
substring(0, 15);
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
[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);
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.
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
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.
PAGE 65
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA
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
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.
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(:)
PAGE 68
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA
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.
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
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.
This is what the output looks like once you run the example:
Initial String: Splitting VZAP's world
PAGE 70
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA
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.
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.
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
PAGE 72
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA
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
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 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.
PAGE 74
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA
PAGE 75
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA
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;
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.
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.
do while
PAGE 78
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA
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;
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.
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;
PAGE 81
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA
PAGE 82
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA
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 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));
}
}
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
import [Link];
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
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.
Another example;
public class TestWhileLoop2{
public static void main(String[] args){
int a=1;
while(a<100)
a++;
[Link]("a is: " + a);
}
}
PAGE 88
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA
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
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 increment defines how the loop control variable will change each time the
loop is repeated.
PAGE 90
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA
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.
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--){
:
:
}
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
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.
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
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;
PAGE 93
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA
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.
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;
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.
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.
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
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();
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;
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[]).
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
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 ;
arrayOne
10
[Link] == 5 20
30
40
50
arrayTwo
null
[Link] == 0
PAGE 100
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA
arrayOne
10
[Link] == 5 20
30
40
50
arrayTwo
[Link] == 5
arrayOne
10
[Link] == 5 20
1000
40
50
arrayTwo
[Link] == 5
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.
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;
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
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.
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
and;
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;
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].*;
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];
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].*;
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
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.
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
class Employee {
public String fName;
public String lName;
public float salary;
public int employeeNum;
PAGE 111
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA
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.
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>;
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
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.
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;
For example;
public int power(int base, n); //NO WAY
public int power(int base, int n); //OK
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.
To call a method, make use of the dot(.) operator together with either the instance
name or the class name. For example;
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.
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) { }
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)
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
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.
For example;
class Employee{
:
:
private static int lastEmployeeNumber;
:
:
}
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).
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;
PAGE 119
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA
static {
:
payroll = ..;
:
}
:
:
}
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.
PAGE 120
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA
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;
}
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));
}
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)
PAGE 122
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA
• 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;
PAGE 125
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA
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.
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
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.
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 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
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{
:
}
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).
PAGE 129
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA
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.
PAGE 130
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA
package [Link];
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];
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];
PAGE 133
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA
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].*;
PAGE 134
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA
[Link](outputString);
Looking at PartTimeEmployee.
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
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.
PAGE 136
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA
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{
:
}
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.
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];
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].*;
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.
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;
The recommended language is "Note: this class has a natural ordering that is
inconsistent with equals."
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
[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());
}
}
}
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();
}
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. 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;
}
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.
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
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].*;
add(myButton);
[Link](new MyInnerButtonHandlerClasss());
} // This is the end of the init() method.
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].*;
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
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
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");
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.
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.
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
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);
}
}
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);
}
}
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);
}
}
PAGE 154
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA
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);
}
}
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.
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);
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
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);
}
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))
PAGE 157
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA
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.
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).
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.
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
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
OR
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{
:
}
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
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;
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
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.
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;
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.
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];
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) {
:
}
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
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.
PAGE 171
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA
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.
:
}
:
}
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]();
}
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 {
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);
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();
}
}
}
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
//************************************************************************
class TestPrimeRange extends Thread{
static long possPrime;
int from, to;
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;
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;
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;
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;
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;
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];
[Link]();
[Link]();
while(true);
}
}
//*********************************************************************
class LevelContainer{
private double liquidLevel;
private boolean updated = false;
//*********************************************************************
class SaveLevel extends Thread{
private DecimalFormat myFormat = new DecimalFormat("#0.00");
private LevelContainer levelContainer;
PAGE 184
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA
//*********************************************************************
class ReadLevel extends Thread{
private DecimalFormat myFormat = new DecimalFormat("#0.00");
private LevelContainer levelContainer;
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()
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.
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;
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");
}
}
}
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.
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 program should result in the following appearing in your console;
All possible user statuses are:
PENDING
ACTIVE
INACTIVE
DELETED
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;
}
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]();
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:");
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;
PAGE 194
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA
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
}
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
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
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 { }
@Documented
public @interface VzapAnnotation {
//Annotation body
}
@VzapAnnotation
public class OurClass {
//Class body
}
PAGE 200
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA
[Link]
@Inherited
public @interface VzapAnnotation {
}
// ************************************
@VzapAnnotation
public class SuperClass {
...
}
// ************************************
public class ExtendedClass extends SuperClass {
...
}
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.
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..
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];
PAGE 202
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA
@VzapDeveloper ()
public void fooMethodC() {
[Link]("This method is written by Vzapper");
}
}
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];
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
There is still more we can discuss regarding annotations but what you have here
gives you most of what you need to know.
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.
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
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>();
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]());
public T getName(){
return [Link];
}
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.
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().
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);
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");
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");
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.
PAGE 210
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA
PAGE 211
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA
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.
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];
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.
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.
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));
}
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
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.
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);
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);
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
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
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.
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.
This ensures that the Vector instance can store at least minimumCapacity. If the
Vector instance is less than the minimumCapacity, it allocates more space.
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];
void run(){
[Link]("\nWelcome to the Vector Demo!\n");
// 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);
PAGE 221
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA
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();
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];
PAGE 223
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA
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]());
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 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.
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.
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 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();
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
void run(){
// let us add key-values to a Hashtable
[Link]("Drink", "Drambuie");
[Link]("Contents", "750ml");
[Link]("Colour", "Honey");
[Link]("Power", "Hick!!! Yummie");
} // end of run()
} // end of HashTest class
PAGE 227
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA
Hick!!!
Yummie
Drambuie
Honey
750ml
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 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.
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.
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
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.
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];
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.
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);
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.
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.
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.
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];
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);
// **********************
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");
}
}
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.
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.
PAGE 236
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA
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
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.
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.
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
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.
PAGE 239
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA
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
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.
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
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.
class HashSetTest {
public static void main(String[] args){
HashSetTest testHS = new HashSetTest();
[Link]();
}
PAGE 245
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA
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.
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]);
}
:
:
}
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.
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 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);
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);
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
PAGE 249
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA
First
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
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.
// ****************************
void run(){
// create two instances of a LinkedList
myListOne = new LinkedList<String>();
myListTwo = new LinkedList<String>();
PAGE 251
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA
// 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);
// ****************************
// 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++;
}
}
PAGE 252
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA
One
Cup
of Java
Please!
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
Below is some simple code showing the adding of elements and the deleting of
elements from an ArrayList.
import [Link];
import [Link];
// *********************
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.");
// 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](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
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.
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 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.
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];
/*
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
/*
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].*;
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
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].*;
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.
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.
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.
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].*;
// ************************************
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]());
}
}
}
}
PAGE 265
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA
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].*;
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);
}
}
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.
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].*;
// ********************************************
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");
// ********************************************
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].*;
public ButtonPanel(){
:
}
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);
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.
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;
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].*;
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;
//**************************************************************
class ButtonTest extends JFrame{
public ButtonTest(){
setTitle("VZAP Buttons");
setSize(300, 200);
setLocation (300,400);
MyHandlerClass myWinHandler = new MyHandlerClass();
addWindowListener(myWinHandler);
//**************************************************************
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) {}
}
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].*;
//*****************************************************************
class ButtonPanel extends JPanel implements ActionListener{
PAGE 276
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA
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);
}
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
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
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
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.
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.
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.
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].*;
//******************************************************************
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);
}
//******************************************************************
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.
//*****************************************************************
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());
}
//******************************************************************
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
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.
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.
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
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>
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];
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>
PAGE 300
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA
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
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].*;
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.");
}
}
}
PAGE 307
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA
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
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
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]);
PAGE 311
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA
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].*;
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;
to
FileInputStream inFileStream = new FileInputStream(args[0]);
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].*;
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?
PAGE 314
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA
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;
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
Let us assume we have two files. One called [Link] which contains:
“One cup of Java and cake please.”
We want to print this out to the screen. The code to do this looks as follows;
import [Link].*;
int dataIn = 0;
while((dataIn=[Link]()) != -1){
[Link]((char)dataIn);
}
}
PAGE 317
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA
}
}
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
Which issues a carriage return linefeed at the end of writing to the screen, or;
[Link]("Message");
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].*;
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].*;
[Link](switchOnOff);
[Link](pi);
[Link](counter);
[Link](ionCount);
[Link]();
}
catch (IOException e){
[Link]("\nIO Error:" + e);
}
}
}
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].*;
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.
PAGE 323
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA
import [Link].*;
with
FileOutputStream (args[0]);
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.
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
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;
PAGE 326
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA
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];
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];
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];
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];
PAGE 329
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA
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];
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];
//*******************************
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]();
}
}
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
PAGE 332
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA
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
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].*;
[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);
}
}
}
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.
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.
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
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];
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
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 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.
[Link]("Opening file...");
FileInputStream in = new FileInputStream("c:\\[Link]");
ObjectInputStream objIn = new ObjectInputStream(in);
[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
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 AccountRecord(){
this ("","",0,0.0);
}
PAGE 342
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA
// -----
// ans in bytes = 72
}
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.
import [Link].*;
import [Link].*;
PAGE 344
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA
//Instantiating buttons
choice1 = new JButton("Choice 1");
choice2 = new JButton("Choice 2");
choice3 = new JButton("Choice 3");
PAGE 345
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA
entries[amountPos] = [Link]();
return entries;
}
This final section of code is our actual program. i.e. It contains the main() method.
import [Link].*;
import [Link].*;
import [Link].*;
import [Link].*;
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();
}
}
);
PAGE 346
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA
addRecord();
}
}
);
[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;
[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
// 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()
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 CreateRandomFile(){
blank = new AccountRecord();
openFile();
}
[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
• 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
other layers
Add components to
this. Default layout
Content Pane
manager is the
border layout.
JPanel
PAGE 353
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA
"Has a"
JMenuBar
JRootPane
JContentPane
JGlassPane
To add a component to a container, you use one of the various forms of the add()
method.
PAGE 354
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA
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.
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.
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
For more on this layout manager go and study the Java documentation.
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.
PAGE 358
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA
import [Link].*;
import [Link].*;
[Link]().setLayout(myGrid);
[Link](new Font("SansSerif", [Link], 24));
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].*;
[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 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].*;
//Now add the label with picture to the frame i.e. top-level container
[Link]().add(myLabel);
PAGE 361
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA
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;
Button is disabled.
That is why it is
grayed.
import [Link].*;
import [Link].*;
import [Link].*;
[Link]().add(myICB);
[Link]();
[Link](true);
PAGE 363
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA
//******************************************************************************
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 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 + " ");
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.
The code is below and the single line that adds the tool tip to the button is
highlighted.
import [Link].*;
import [Link].*;
import [Link].*;
[Link]().add(myB);
[Link](220,80);
[Link](true);
//*******************************************************************
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
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].*;
StringBuffer choices;
JLabel pictureLabel;
public CheckBoxCartoon(){
// Create the check boxes
chinButton = new JCheckBox("Chin");
[Link](false);
PAGE 367
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA
[Link](myListener);
[Link](myListener);
[Link](myListener);
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]());
}
}
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].*;
JRadioButton portButton;
JRadioButton dramButton;
JRadioButton irishButton;
JRadioButton pieButton;
JRadioButton donutButton;
JRadioButton cakeButton;
Border raisedbevel;
public JavaRadioButton() {
// Create the radio buttons.
portButton = new JRadioButton(portString);
[Link](KeyEvent.VK_P);
[Link](portString);
[Link](true);
PAGE 371
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA
[Link](irishButton);
setLayout(new BorderLayout());
add(labelPanel, [Link]);
add(radioPanel, [Link]);
add(picture, [Link]);
add(picture2, [Link]);
setBorder([Link](1,20,20,20));
}
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
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.
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.
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
JTextComponent
JPasswordField JTextPane
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.
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;
JTextField myTextField;
JPasswordField myPassField;
JTextArea myTextArea;
JLabel myLabel;
JLabel myPassLabel;
protected JLabel myActionLabel;
[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
[Link](myGridLayout);
[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
[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();
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;
[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].*;
[Link](new WindowAdapter()
{
public void windowClosing(WindowEvent e)
{
[Link](0);
}
});
[Link]().add([Link]());
[Link]();
[Link](true);
}
public SplitFrameList(){
myList = new JList(myPics);
[Link](ListSelectionModel.SINGLE_SELECTION);
[Link](0);
[Link](this);
PAGE 383
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA
[Link](new Dimension([Link](),
[Link]()));
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.
import [Link].*;
import [Link].*;
import [Link].*;
import [Link].*;
[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
}
});
[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]();
}
});
PAGE 386
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA
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
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.
PAGE 388
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA
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);
}
});
//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);
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);
[Link]();
//*************************************************************************************
//Build the second menu.
menu1 = new JMenu("IconText");
[Link](KeyEvent.VK_I);
[Link](this);
[Link](menu1);
[Link]();
//*************************************************************************************
//Build the third and submenu menu.
menu2 = new JMenu("OtherStuff");
[Link](KeyEvent.VK_S);
[Link](menu2);
[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);
[Link]();
[Link](submenu);
//******************************************************************************************
//Build the fourth menu.
menu3 = new JMenu("About");
[Link](KeyEvent.VK_A);
[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);
}
//******************************************************************************************
// 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.
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){}
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.
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].*;
[Link]().add(new MyTabs(),[Link]);
[Link](400, 125);
[Link](true);
}
public MyTabs() {
JTabbedPane tabbedPane = new JTabbedPane();
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];
[Link]();
[Link](true);
}
public BorderDemo() {
super ("BorderDemo");
Border blackline, etched, raisedbevel, loweredbevel, empty;
blackline = [Link]([Link]);
etched = [Link]();
raisedbevel = [Link]();
loweredbevel = [Link]();
empty = [Link]();
PAGE 397
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA
titled = [Link]("title");
addCompForBorder(titled, "default titled border"
+ " (default just., default pos.)",
titledBorders);
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);
getContentPane().add(tabbedPane, [Link]);
}
PAGE 399
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA
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.
• 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
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);
}
}
Assertions
Next, let us look at a feature that was added in JDK1.4, and that is - Assertions.
PAGE 402
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA
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.
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
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.
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.
Now, create a test class that will test the Calculate class.
@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
time: 0
OK (1 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];
The output generated is almost exactly the same as your original example.
Adding values: 2 + 5
@Test sum(): 7 = 7
true
We then test the result of the test over the lines following this line, verifying
whether the tests passed or failed.
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
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
@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];
@Test(timeout=1000)
public void testSum() {
[Link]("@Test sum(): " + sumAns + " = " + expectedSum);
assertEquals(expectedSum, sumAns);
try{
[Link](1500);
}catch(Exception ex){}
}
}
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];
@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
//********************
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
}
}}
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’.
@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");
}
}
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.
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] })
Simple, Huh!!
Of course you can write your own test suite runner. Here is an example;
import [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
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;
@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));
}
}
If you really want to run your test using the default, built in runner then do this;
java [Link] CalculateTest
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
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;
PAGE 417
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA
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 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.
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.
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]
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
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
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
PAGE 429
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA
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
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
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
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.
.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.
.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.
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
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.
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.
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
PAGE 455
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA
PAGE 456
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018
VZAP’s PRACTICAL COURSE IN JAVA
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
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
PAGE 460
© Van Zyl and Pritchard (Pty)Ltd. 3rd Edition 2018