Sie sind auf Seite 1von 260

Java

Page 1 - Copyright 2012 Walter Milner - all rights reserved


Java
The First Step ...................................................................................................................................... 4
Basic Programming Ideas .................................................................... 6
Command line programming .............................................................................................................. 7
Installing and Using an IDE ................................................................................................................ 10
Writing Your Own Programs ............................................................................................................. 12
How Java works ................................................................................................................................. 14
Data ................................................................................................................................................... 16
Data types ......................................................................................................................................... 17
Variables ........................................................................................................................................... 18
Input and Output .............................................................................................................................. 20
Statements ........................................................................................................................................ 23
The Three Frames of Programming .................................................................................................. 24
Expressions........................................................................................................................................ 27
Increment decrement and short-cut ................................................................................................ 29
Conditional Statements .................................................................................................................... 30
Algorithms ......................................................................................................................................... 35
Loops ................................................................................................................................................. 38
Testing ............................................................................................................................................... 43
Data Structures ................................................................................................................................. 44
Bitwise operations ............................................................................................................................ 51
Using a Debugger .............................................................................................................................. 54
Type casts .......................................................................................................................................... 57
Structured Programming .................................................................. 59
Static methods and parameter passing ............................................................................................ 60
Scope ................................................................................................................................................. 64
Recursion .......................................................................................................................................... 66
When it does not work ..................................................................................................................... 69
OOP ................................................................................................... 72
Classes and objects ........................................................................................................................... 73
Characters and Strings ...................................................................................................................... 76
Java
Page 2 - Copyright 2012 Walter Milner - all rights reserved
A first look at Swing .......................................................................................................................... 80
The Java API ...................................................................................................................................... 83
Subclassing ........................................................................................................................................ 84
Variables and values ......................................................................................................................... 87
Wrapper Classes................................................................................................................................ 94
Overloading ....................................................................................................................................... 95
Inheritance ........................................................................................................................................ 98
The Object class .............................................................................................................................. 100
Overloading and overriding ............................................................................................................ 102
super ............................................................................................................................................... 103
this................................................................................................................................................... 108
static ................................................................................................................................................ 110
Date and Time in Java ..................................................................................................................... 115
Interfaces ........................................................................................................................................ 119
Event handling ................................................................................................................................ 121
Defining a new class ........................................................................................................................ 124
Projects and Packages ..................................................................................................................... 126
Encapsulation .................................................................................................................................. 128
Writing new classes - a personnel system ...................................................................................... 130
Writing New Classes - Tic Tac Toe ................................................................................................... 140
Binary Trees .................................................................................................................................... 146
Hash tables ...................................................................................................................................... 151
Swing .............................................................................................. 155
Starting a Swing application ............................................................................................................ 156
Swing event handling ...................................................................................................................... 157
Swing containers ............................................................................................................................. 161
Swing widgets ................................................................................................................................. 168
Images ............................................................................................................................................. 170
Color ................................................................................................................................................ 172
Fonts................................................................................................................................................ 173
Menus, Popups andToolbars .......................................................................................................... 174
Swing and MVC ............................................................................................................................... 177
Inheritance - a GUI Tic Tac Toe ....................................................................................................... 181
Java 2D ............................................................................................................................................ 186
Java
Page 3 - Copyright 2012 Walter Milner - all rights reserved
More OOP ....................................................................................... 192
abstract ........................................................................................................................................... 193
Annotations ..................................................................................................................................... 198
Nested Classes ................................................................................................................................ 200
Generics .......................................................................................................................................... 205
The Collections Framework ............................................................................................................ 211
Enums .............................................................................................................................................. 216
Exceptions ....................................................................................................................................... 218
Multi-threading ............................................................................................................................... 225
Classes and types ............................................................................................................................ 237
Input and Output ............................................................................................................................ 241
Reflection ........................................................................................................................................ 249
Networking - UDP ........................................................................................................................... 251
Networking - TCP ............................................................................................................................ 256
Networking - URLs........................................................................................................................... 258

Java
Page 4 - Copyright 2012 Walter Milner - all rights reserved
The First Step
This is intended for people who are learning Java and who have never programmed before.
Java is a big deal. Learning to program in Java is not like learning wordprocessing or learning how to
use a graphics program or editing a video. Such applications try to be as easy as possible to use. Java
is a language which was designed to be used by experienced professional programmers who were
experienced in coding in C. It was designed to be the best possible general-purpose language,
designed on the basis of around 50 years development of programming languages. It was designed
to be the best, not the easiest.
So expect to take this seriously, expect to have to think hard, and expect to spend considerable time
learning it - mostly by using it to write programs. An undergraduate might expect to learn basic Java
over their first year. They might follow more advanced topics over the next two yeas.
You will find it easier if you also learn basic computer science at the same time - compilers
interpreters and syntax, algorithms and data structures and so on. This will help to make more sense
of many of the topics.
Try out the code in the book. It is easiest and faster if you copy and paste it from an electronic
version. Try and make small changes, and see what happens. Write lots of your own small programs.
If things won't work - look at the chapter about debugging.
What is Java?
Java is a general purpose programming language, designed by a small group working at Sun
MicroSystems. Any further description would not make sense until you learn more of the concepts
involved.
What to read first
You could start at the beginning and read it to the end. Or you could start at the end, but this is not
recommended.
The inter-relationships between the concepts in Java mean it is not possible to order the
presentation into a single line. So you might read a section with partial understanding, read on, then
go back and re-read with more understanding. In fact you should.
The reason for this is that Java was designed so that experienced programmers could learn it quickly.
But they already had a significant set of concepts already developed. If you are a beginner, you do
not, and so you will probably have to go back and forth.
There are five main sections:
Basic programming ideas - including setting up your computer to write and run Java
Structured programming
OOP - object-oriented programming
Java
Page 5 - Copyright 2012 Walter Milner - all rights reserved
Swing - writing GUI programs in Java
More OOP - not so basic OOP ideas.
What else to read
There is a great deal of Java material on the web. Some is good, most is not.
The most reliable material is from Oracle (who took over Sun). 'The Java Programming Language' by
Arnold, Gosling and Holmes is the key text, but not the easiest. 'The Java Language Specification' sets
out formally the language. This is a free download, but is not for beginners. 'The Java Virtual
Machine Specification' is another free download but again is not for beginners.
Oracle offer an on-line set of tutorial 'Trails'. These are more suitable for people converting from
other languages.
Useful Links

Where appropriate, links to reliable learning materials are given. Some key links follow. These are
not suitable for total beginners, but bookmark them now:
The Java SE 7 API
The Java 7 Language Specification
Java 7 Virtual Machine Specification
The Oracle Java Tutorials
Java 7 SE Documentation






Java
Page 6 - Copyright 2012 Walter Milner - all rights reserved
Basic Programming Ideas

This part is mostly about what a computer program actually is, how you can work out what a
program will do, and how you write one.
Some people think these ideas are obvious. Others do not, and so programming makes no sense to
them, and they quickly drop out. Many courses do not address these ideas.
If you are new to programming, read this carefully.
This part also leads you through what to install on your computer and how to set it up so that you
can write and run Java programs.
You must write lots of small simple programs. Or you will not understand anything.
Java
Page 7 - Copyright 2012 Walter Milner - all rights reserved
Command line programming
This section is about setting up a computer and writing a first Java program using the 'command
line'. Most people think this is the best way to start. The details here assume you are using
Windows. If you use Linux or another OS, the principles are the same but the details are different -
use Google.
Follow through this tutorial as you read it.
You need to:
Use a text editor, such as Notepad, to write the source code. You save this as a file with the
extension .java.
Use the compiler to compile it into a bytecode file, with the extension .class. You might get
error messages at this stage.
Use the JRE to execute the bytecode. Error messages are also possible here.
You need to have the compiler and other tools installed this is called the software development
toolkit ( JDK ). This is a free download from the web. Google Java JDK. You want Java SE (Standard
Edition) not J2EE (Enterprise Edition). The JRE (to run Java) is bundled with the JDK (to write Java).
Select the one matching your OS Windows, Linux, Mac or Solaris.
Once you have installed the JDK, we can start using it, as follows:
To get to the command line (on Windows XP) go Start.. Accessories.. Command Prompt. (On
Windows 7, go Start..All
programs..Accessories..
Command Prompt.) You will
see a window with a black
background and a prompt like
C:\Documents and
Settings\Walter Milner>
Type in the word java and
press Enter. In other words you
would see:
C:\Documents and Settings\Walter Milner>java
and you hit Enter (things you type are in yellow). You should get lots of lines of help messages listing
options. We are just checking you have the JDK correctly installed.
If it says Not recognised, check the download and installation, and also the 'path' setting. The path
is an 'environment variable' which is a list of folders. When you type in a command, the OS searches
in those folders for a program with the same name. In this case we want it to find and run the
program named java.exe. This will probably be in the folder named
C:\Program Files\Java\jdk1.7.0\bin
Command line interface
Java
Page 8 - Copyright 2012 Walter Milner - all rights reserved
depending on the version. Check
you have this, then make sure
this is included in the list of
folders in the path. Google how to
set the path for your version of
Windows.
Type in
cd Desktop
This changes directory to your
Desktop.
Type in
notepad
This will start Notepad, the text editor, running. In Notepad type in the following:
public class ProgramOne
{
public static void main(String[] args)
{
System.out.println("It works");
}

}
Type it exactly as it is here. The best way if possible is to cut and paste it. It must be capital P for
ProgramOne, capital S for String, capital S for System. Each bracket must be the correct type. The
quotes must be double not single .
Then save this, in the Desktop. The filename must be ProgramOne.java note the capital P.
Click back at the command line. Type in
dir *.java
This means list all the files ending in java. You should see your file ProgramOne.java listed. If not you
have saved it in the wrong place.
Next type in
javac ProgramOne.java
javac is the Java compiler. You are telling the compiler to compile your file ProgramOne.java into
bytecode. You might get an error message. If so, read it very carefully it will tell you the line
number where the error is. Go back to Notepad, find the line and correct it. Save it again and run the
compiler. Repeat until you get no error message.
Type in
dir *.class
Running java.exe
Java
Page 9 - Copyright 2012 Walter Milner - all rights reserved
which lists all files ending in class. You should see ProgramOne.class, which is the bytecode produced
by the compiler.
Then type in
java ProgramOne
Check capital P. This invokes the JRE and executes your bytecode. You should see
It works
You have now started. You are no longer maggots.
You can write all your Java code like this use Notepad to write it, compile it with javac and run it
with java.
Summary
To write and run Java programs at the command line, you need the JDK and the JRE, which are free
downloads.
Exercise
Make sure you follow through this tutorial on your computer
Java
Page 10 - Copyright 2012 Walter Milner - all rights reserved
Installing and Using an IDE
An IDE is an 'integrated desktop environment'. This is a piece of software which includes an editor, in
which you can write your source code, and the ability to compile and run the code from one button.
They also include many other features, which take a long time to explore - probably you will not use
some of them. It is suggested you start with the basic usage described here, and progress on a need
to know basis.
There are two common (and
free) IDEs - NetBeans and
Eclipse.
Netbeans
Google NetBeans, and download
the latest version for your OS.
This will include the JRE.
For a first try-out, do the
following:
Run NetBeans
From the menu, go File..
New project.. Choose
category Java.. Java
application..Next..
Project name
ProgramOne .. Create
main class yes, and set
as main project yes,
then Finish
You should see
something like on the
left. The right-hand pane
headed Main.java is
your source code. The syntax colouring helps you see what is what. On the left you see your
projects, with the Source packages containing the package programone,File..New.. Java Project and
inside that, the source code Main.java.
Make a small change to the source code, like this:
public static void main(String[] args)
{
System.out.println("It works");
}
so you just change the TODO line.
NetBeans 7.1.2 running on openSUSE Linux
Figure 1
Java
Page 11 - Copyright 2012 Walter Milner - all rights reserved
Then compile it and run the bytecode by clicking the green triangle button under the menu.
Youll either get an error message, or towards the bottom of the screen, a pane headed Output will
appear, saying It works.
This has set up a 'project'. This is a set of source files - in this case, just one, called Main.java, but for
typical projects there will be several. There might also be additional 'libraries' of system code which
your project uses, and maybe resources like image or sound files.
Using Eclipse
Google Eclipse downloads. You want Eclipse for Java Developers. Download and install it.
For your first try-out, start Eclipse,
then go File.. New.. Java
project..Project Name
programone.. Finish.
Then go File..New..Java class..
Name Main, check public static
void main. You should see:

The source code editor pane is on
the right. Make a small change to
the source code, like this:
public static void main(String[] args)
{
System.out.println("It works");
}
so you just change the TODO line.
Run it by clicking the green arrow button under the menu. Towards the bottom you will see a pane
headed Console, which should say It works.
How to carry on
You can use the code in the following sections, and write your own, by just changing the source
code. At the command line you need to save, compile and run it. In NetBeans or Eclipse, just change
the source code and run it.
Summary
You can use IDEs such as NetBeans or Eclipse to write and run Java instead of using teh command
line. Both are free downloads.
Java
Page 12 - Copyright 2012 Walter Milner - all rights reserved
Writing Your Own Programs
Here is a Java program to use as a model for your programs:
class MyProgram
{
public static void main(String[] args)
{

System.out.println("Hello");

}
}
Modify this like :
Write your code to replace the System.out.println as shown.
The class name ( MyProgram ) must match the filename it is saved in, including capitalisation. So the
class MyProgram must be save in the file named MyProgram.java.
Using the command line
1. Use Notepad or any text editor to write the program.
2. Save it with the correct filename. If the class name is ProgramTwo, save it as ProgramTwo.java
3. Compile it by typing javac <filename>. So if you wrote ProgramTwo.java, say javac
ProgramTwo.java
4. Run it by saying java <classfile>. So if you are writing PrograTwo, say java ProgramTwo.
Using NetBeans
In NetBeans, programs are written as groups of files called 'Projects'. Do as follows:
1. From the menu, go File.. New Project.. Java..Java application (Next) Project Name 'Whatever' ,
Create Main Class Test (or whatever), and Finish
2. In the editor pane you will see a source code file, public class Test (or whatever), and a public
static void main. Write you code there.
3. To compile and run it, click the green arrow in the toolbar.
Using Eclipse
This is very similar. See the part on Eclipse in the previous section.
Java
Page 13 - Copyright 2012 Walter Milner - all rights reserved
Summary
1. Use the model given as a template for your own programs.
2. The filename must match the name of the class, and end .java
Exercise
Modify and run a program at the command line or using an IDE


Java
Page 14 - Copyright 2012 Walter Milner - all rights reserved
How Java works
People use computers as if they were servants. But there are significant differences.
Computers are very fast like several thousand million operations per second
There are a very limited set of kinds of things they can do like moving pieces of data
around in memory, doing arithmetic, comparing data and so on
Processors seem to be like brains but in fact they are electronic devices, which can input
binary codes which are treated as instructions and which are carried out moving data and
so on.
How computers work
Computers and all other programmable digital devices contain a processor. This is an electronic
device which can recognise and execute instructions. An instruction is a very simple step - like
moving data around in memory, doing arithmetic, comparing data and so on. These instructions are
encoded as binary strings, like 0110 1101, and held in memory. The processor fetches one
instruction at a time from memory, decodes it, carries it out, and moves on to the next one. The
processor will carry out around a thousand million instructions per second.
A program is contains a sequence of these instructions. A program is stored in a file, and must be
loaded into memory before the instructions are carried out (because it would be too slow to read it
in from file one instruction at a time). This is called machine code or native code.
Different processor chips have different instruction sets - so a machine code program for a Motorola
chip will not work on a computer with an Intel chip.
Programs also use facilities provided by the OS (Windows or Linux and so on). This means the same
program will not run on different OS.
Writing programs using machine code is extremely difficult and error-prone. Instead programs are
normally written in a high-level language such as Java, which uses English words.
High-level language programs must be converted into machine
code before they can be executed. This is done by a piece of
software called a compiler. The program as you write it is called
source code.
In fact Java from the start was based on the Internet, and so Java
programs needed to work on a wide range of computers with
different processors (and so different machine code) and
different operating systems (such as Windows, Linux, MacOS and
Solaris). In other words Java is cross-platform.
But how to do this? The instruction sets of different processors
are different - so how could the same Java program work on
different processors?
The solution to this was the idea of a virtual machine ( the Java
Source code and byte code
Java
Page 15 - Copyright 2012 Walter Milner - all rights reserved
Virtual machine, JVM). This was a piece of software which in effect ironed out the differences of
different platforms, so that they all seemed the same. Each different platform has its own JVM,
taking into account the hardware differences.
A Java application is compiled into an intermediate form called bytecode. A piece of software called
the Java Runtime Environment (JRE) then executes the bytecode on the JVM.
This means the same Java program will run on a wide range of platforms. This is one of the most
significant feature of Java. Compared with other languages, especially C and C++, it is slightly slower
but it has the big advantage that it will run unchanged on many different platforms.
EXAMPLE
Suppose you were planning to write a personal finance application which people could use to track
their spending and saving. This could be a desktop application in other words it would be a
program which ran on the users computer, rather than on a server across the Internet. You plan to
sell the application as a download from your website.
Do you use Java or C++? C++ would probably be slightly faster, but this is not a speed-critical
application. If you use C++, you would need to write different versions for different types of
computers Windows machines, Linux, Macs and so on. By contrast, the same Java code would
work the same on all these platforms, provided users have the JRE installed.
Having decided to use Java, you would write the program as source code. You would then need to
compile it, producing bytecode. It is this bytecode which users would buy. They would download and
install the bytecode. When this ran, the JRE would execute it on the JVM. Different types of
computers would have different JVMs, making them all seem the same and enabling the same code
to run on different platforms.
Summary
1. Java source code is compiled into an intermediate form called bytecode.
2. Bytecode runs on a JVM
3. There are JVMs for different hardware/OS platforms
4. The same Java program will run on several different platforms
Exercise
1. Why do we need to use compilers?
2. Is the bytecode of a Java app different on different platforms?
3. What is a JVM?

Java
Page 16 - Copyright 2012 Walter Milner - all rights reserved
Data
Computer programs deal with data. Here are some examples of data in different contexts:
Word processing - the text of the document, including font name and size and style, colour, spacing.
Images and their psoitions. Page size, margin sizes. Most of this data is made of strings (sequences of
characters) but some is numeric - like the size of margins. The data is in memory when the document
is being edited, and otherwise placed in a file, usually stored on disc.
Email - the text of messages, the email addresses of contacts, dates and times of messages.
Graphics programs - an image can be represented in different ways, but the most common is to have
a rectangle made of rows and columns of pixels. Each pixel will have three numbers representing the
red, green and blue parts of the colour at that point. There might be a fourth number for how
transparent the pixel is.
Browser - this handles a web page, which is a piece of text representing the page in HTML. The
browser has to render the html and present a visual version of it.
Summary
programs handle data
data is held in memory or in a file
data is input (from a keyboard, mouse, a file, a network connection etc) and output (to a
screen, a printer, a file etc).

Java
Page 17 - Copyright 2012 Walter Milner - all rights reserved
Data types
In general data comes in different types - numbers, text and so on.
In a programming language, the idea of data type is very important.
In Java there are two kinds of types:
Reference types. These are about objects. More on objects and references later
Primitive types. These are single values. This section is about primitive types.
An example of a primitive type is an int. This is short for integer - a whole number. The int type
represents a positive or negative whole number. An int is held in 32 binary digits, bits, which is 4
bytes, of memory. This means there is a minimum value - about -2 billion - and a maximum, of +2
billion. The numbers are held using a method called two's complement (see bit-wise operations).
Integer arithmetic is completely accurate.
Sometimes this range is not enough - or sometimes it is too much, so other types of whole number
are available. Here is the complete set:
Name
Memory usage
(bytes)
Minimum value Maximum
byte 1 -128 127
short 2 -32,768 32,767
int 4 -2,147,483,64 2,147,483,63
long 8 -9,223,372,036,854,775,808 9,223,372,036,854,775,807

Often we need numbers with decimal parts - what mathematicians would call rational numbers. In
computing these are called floating point numbers. Two versions are available - float (in 4 bytes) and
double (in 8 bytes). Floating point arithmetic is slower than using integers, and in general it is not
completely accurate. This is because many numbers cannot be represented as a finite sequence of
bits, in base 2.
In addition to numbers , there are two other primitive types.
boolean data has just two possible values - true and false. boolean data is used for logic.
char represents a character. Java uses the Unicode character set, which uses 2 bytes = 16 bits to
represent each character.
Summary
Java operates with several different data types
Exercise
1. How do you decide whether to use a byte, short, int or long?
2. What is the difference between a double and an int?
3. Some programing languages use ASCII. Why does Java use Unicode?

Java
Page 18 - Copyright 2012 Walter Milner - all rights reserved
Variables
Java programs handle data by using variables. Here is a program fragment which is pretty easy to see
what it does:
int x;
int y;
int z;
x = 2;
y = 3;
z = x+y;
Clearly the program adds 2 and 3. In more detail:
The program uses three variables, named x y and z. The variables have data type int. The program
starts by declaring these variables:
int x;
int y;
int z;
Variables must be declared like this, before they are used. The declaration tells the compiler what
memory it needs to allocate for this data, how they will be referred to (their names) and what data
type they are.
The three lines are three statements. These are declaration statements. All statements must end in a
semi-colon ; if you miss that out, the compiler will give you an error message.
You can put statements on the same line:
int x; int y; int z;
but this makes things harder to read - don't do it.
You can declare variables of the same type together, like
int x,y,z;
The program then has three assignment statements:
x = 2;
y = 3;
z = x+y;
An assignment statement assigns a value to a variable. The first statement gives x the value 2. The 2
and the 3 are literal constants. These are of type int - if you want type long, say for example 2L.
The third assignment is different. 'x+y' is an expression. The compiler sets up code so that the values
of x and y will be added, and the resulting value of the expression will be assigned to z.
Note that the calculation takes place at run-time, not compile-time. We can see that obviously z will
be 5 - but the compiler does not actually work that out. It produces code which will do the addition,
when the program runs.
A variable has three attributes - a name, a type, and a value. Once declared, we cannot change its
name or its type, only its value. There is a fourth attribute, namely the address in memory where it is
Java
Page 19 - Copyright 2012 Walter Milner - all rights reserved
held, but we cannot get or refer to that in Java - we do not need to. Also, this is an address in the
JVM, not the physical machine.
Summary
Changing data items in a program are called variables
Variables have type
Variables must be declared before use
Variables can have values assigned to them
Variables are held in memory
Exercise
1. Variables must be .. before use?
2. What is a 'literal constant'? Give an example.
3. Give an example of an 'expression'.

Java
Page 20 - Copyright 2012 Walter Milner - all rights reserved
Input and Output
To start with we will look at output, to the 'console' - so this is just output of characters, not
graphics.
This is done with a statement like
System.out.println("A B C D E");
This outputs everything in the string enclosed by the double quotes, including the spaces. If we want
to output a number, we can say it like
int x;
x=4;
System.out.println(x);
We can output a string and a number like
System.out.println("The value of x is "+x);
Note the string is joined to the variable by a +. Or two values:
System.out.println("x = "+x+" and y = "+y);
println goes on to a new line after it has finished, but print stays on the same line. For example
System.out.print("A");
System.out.print("B");
System.out.print("C");
would output
ABC
all on the same line.
Input
We can have assignments like
x=3;
which give variables constant values, known at compile-time. But we usually need to enable our
programs to input data values at run-time. Wordprocessing, for example, means the user inputs data
(text) when the wordprocessor software is running. This is what we mean by input.
Keyboard input can be done using a class called Scanner. For example:
java.util.Scanner scanner = new java.util.Scanner(System.in);
int x, y, z;
x = scanner.nextInt();
y = scanner.nextInt();
z = x + y;
System.out.println(z);
We will improve this program in three steps:
Comments

Java
Page 21 - Copyright 2012 Walter Milner - all rights reserved
A comment is some text which will be ignored by the compiler. Comments are used to say who
wrote the program, when, why, what its supposed to do, and to explain obscure parts of code.
There are two ways of having comments in Java. One is to start with /* and end with */. This can
cover several lines. The other is a line comment, which starts // and goes to the end of the line. For
example
/* A program to input 2 numbers
and output the sum */
// create the keyboard input scanner
java.util.Scanner scanner = new java.util.Scanner(System.in);
int x, y, z;
// input 2 ints
x = scanner.nextInt();
y = scanner.nextInt();
z = x + y; // calculate sum
System.out.println(z); // output result

Import
The class Scanner is located in the package (group of classes) called java.util. Its fully-qualified name
is java.util.Scanner. This tells the compiler where to find Scanner, and distinguishes it from any class
also called Scanner in other packages. But its a lot of typing. Provided we say
import java.util.Scanner;
then we can just say
Scanner scanner = new Scanner(System.in);
so the whole thing is
import java.util.Scanner;
/* input 2 numbers and output the sum */
class Test {

public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int x, y, z;
x = scanner.nextInt();
y = scanner.nextInt();
z = x + y;
System.out.println(z);


}
}
IDEs typically generate import statements for you - in NetBeans, right-click and choose Fix Imports.
Program listings here will usually omit import statements.
User prompts
A user prompt is some output to tell the user what to do. For example:
Java
Page 22 - Copyright 2012 Walter Milner - all rights reserved
Scanner scanner = new Scanner(System.in);
int x, y, z;
System.out.println("Enter a number, then Enter");
x = scanner.nextInt();
System.out.println("Now another");
y = scanner.nextInt();
z = x + y;
System.out.println(z);
which produces, for example
Enter a number, then Enter
3
Now another
4
7

Summary
As a program runs, data values can be input from the keyboard and other sources
Results can be output to the screen or elsewhere.
Exercise
1. Change the program so it subtracts the two values.
2. Change the program so it inputs and adds three values.
3. What is the difference between println and print?
4. Give three reasons for using a comment.

Java
Page 23 - Copyright 2012 Walter Milner - all rights reserved
Statements
A statement is an important part of Java code.
Previously we have seen three types of statement. The first is a declaration statement, like
int x;
The second is an assignment statement, like
z=x+y;
The third is a method invocation:
System.out.println("Hello");
There are several other types of statements which we will meet.
In Java one statement is usually written on one line. It does not have to be, but code is easier to read
if it is. The important point is that a statement ends with a ; semi-colon.

Java
Page 24 - Copyright 2012 Walter Milner - all rights reserved
The Three Frames of Programming
When writing a program, or reading someone else's, there are three mental frames you need to
think about. In other words, there are three areas you must pay attention to:
Program text
Changing variable values
Input/output
The first one, program text, is obviously important - its what the program is.
The second means tracking how variable values change, as the code executes step by step. This is
needed because when an early program step changes a variable value, this will in general affect
what later program steps do. Some people think this is obvious, but some do not.
We will return to input/output later.
For example: ( * means multiply)
int x;
int y;
x=3;
y=2*x;
x=x+1;
y=y*x;
System.out.println(y);
What will this program do?
We could guess, or try to work it out in our heads. An
easier and more reliable way is to trace it - track what
will happen step by step, in the program code and in
memory.
In the table alongside, on the left we see what values
we have in memory, after each step. On the right, we
see the program text. The step which has just executed
in shown in yellow. We have to be careful are we
looking at memory before it has executed, or after? In
this table we see the memory contents after that step.
Look at this table very carefully. Make sure you
understand everything it shows.
We will use this technique of tracing to see what more
complex program structures do. With experience you
will be able to think about how program text and
memory affect each other with ease.
Variable exchange
As an example - how can we exchange the values of two variables? Suppose the variables are x and
y, and initially x is 1 and y is 2. After the swap, x should be 2 and y 1.
Memory Program text

int x;
int y;
x=3;
y=2*x;
x=x+1;
y=y*x;

int x;
int y;
x=3;
y=2*x;
x=x+1;
y=y*x;

int x;
int y;
x=3;
y=2*x;
x=x+1;
y=y*x;

int x;
int y;
x=3;
y=2*x;
x=x+1;
y=y*x;
Java
Page 25 - Copyright 2012 Walter Milner - all rights reserved
The obvious way to do this is with two statements:
x=y;
y=x;
Suppose we trace this:
Values in memory
Program
step
Effect
x 1
y 2

Initial
state

x 2
y 2

x=y;
y=x;
The value from y (2) has been
written into cell x, over-
writing the previous 1
x 2
y 2

x=y;
y=x;

The value from x (now 2) is
written into y - which was 2
anyway.
The problem is that the first x=y over-writes the initial value of x, which is lost and cannot be placed
in y. How can we fix this?
The usual solution is to use an extra location, as a temporary store. One initial value is copied there,
the other initial value written into the first, and then the copy written into the second. In other
words:
temp=x;
x=y;
y=temp;
We trace this to check:
Values in memory
Program
step
Effect
x 1
y 2
temp ?

Initial
state

x 1
y 2
temp 1

temp=x;
x=y;
y=temp;
We've made a temporary copy
of x
x 2
y 2
temp 1

temp=x;
x=y;
y=temp;
Write the value of y into x
Java
Page 26 - Copyright 2012 Walter Milner - all rights reserved




Exercise
Suppose we have three variables, x,y and z, and we need to 'shuffle' their values : x->y, y->z, z->x. So
if to start with x=1, y=2 and z=3, afterwards x=3, y=1, z=2.
How would you program this?
Try it and test it works.



x 2
y 1
temp 1

temp=x;
x=y;
y=temp;
Write the initial value of x,
from temp, into y
Java
Page 27 - Copyright 2012 Walter Milner - all rights reserved
Expressions
Something like 4-3 is an expression. In an assignment statement, we say something like
x = <an expression >;
We use for subtraction, * for multiplication and / for division. So examples of expressions are
4 * 3
12-3
12 / 4
For example
y = 20/5;
makes the value of y to be 4.
% is the modulo operator, or remainder
so 10%3 is 1, because 10 divided by 3 gives remainder 1
17%5 is 2
10%5 is 0
% 10 is useful for getting the separate digits of a number. For example
int x= 12345;
x%10 is 5
What about
2+3*4 ?
Will it do the addition first (so it gets 20) or the multiplication first, so it gets 14? The answer is that it
works the same as normal mathematics, which means it will do multiplication and division first, then
addition and subtraction. So
4+5*2 is 14, not 18.
Also as in normal maths we can use brackets operations in brackets are done first. So
(4 + 5) * 2 = 9 * 2 = 18
Note if we are using ints, division works using a whole number result, and remainders are discarded.
So for example
13/3 is 4
Java
Page 28 - Copyright 2012 Walter Milner - all rights reserved
12/3 is 4
15/3 is 5
16/3 is 5
Exercise
Evaluate the following expressions. The first two are done for you. Check your answers with little
Java programs.
2+3 = 5
2-3 = -1
2*3
6/3
7/3
0/3
2+3*4
2*3+4
3-3/4
(3 * 3)/4
(3-3)/4
(5-1)*(10-1)
Expressions with floating point numbers are similar, except that floating point division is used - so
7.0/2.0 is 3.5
Take care. 7 is an int, 7.0 is a double. So while 7.0/2.0 = 3.5, 7/2=3.
We cannot do arithmetic with boolean types, but we can do logic. We use ! for not, && for AND and
|| for OR. Google logical AND OR and NOT. For example:
boolean a=true;
boolean b=false;
then !a is false. a || b is true. a&&b is false. See the later section on conditional statements.
Java
Page 29 - Copyright 2012 Walter Milner - all rights reserved
Increment decrement and short-cut
Increment operator
For ints, we often want to increase them by 1, and there is an operator to do this:
int x=27;
x++;
makes x be 28.
In fact there are two versions of this - post-increment (x++) and pre-increment (++x). In post-
increment, the variable is first used, then incremented. For pre-increment, it is first incremented
then used. For example
int x=1;
int y;
y = x++;
makes y be 1, and then changes x to 2. But
int x=1;
int y;
y = ++x;
first increases x to 2, then makes y be 2 also.
You can also say x-- or --x
Short-cut operators
Suppose you want to increase x by 2. You cannot say x+++. You could say x++ twice, or you could say
x = x+2;
But the usual way is
x += 2;
Similarly
x -= 3; // same as x = x - 3;
x *= 4; // same as x = x * 4;
x /= 2; // same as x = x / 2;
and for a boolean type
boolean b = true;
b != b; // same as b = !b; so now b is false
Exercise
Suppose x and y are ints, and x=2 and y=3. After
x *= y++;
How big are x and y now? Write a little program to check.

Java
Page 30 - Copyright 2012 Walter Milner - all rights reserved
Conditional Statements
As well as arithmetic, input and output, there are only two other basic features a program can have:
1. Comparing values and doing different actions for different data
2. Repeating actions
This section is about the first of these.
Suppose we need a program which will input a number, and then output a warning message if it is
greater than 100.
That description uses the word if and we can write it using an if statement
Scanner scanner = new Scanner(System.in);
double number;
System.out.println(Enter a number);
number = scanner.nextDouble();
if (number > 100.0)
System.out.println("Too big");
Try this. Run it twice firstly entering a number less than 100, then greater than 100.
Exercise
Alter this so you only get a message if the number is greater than 1000.
Syntax
Syntax means grammar rules.
An if statement is like this:
if ( <some condition> )
<what to do if the condition is true>

The <some condition> is an expression which evaluates to true or false. If it is true, the statements in
the curly brackets are executed. If it is not, nothing happens and we just move on to what comes
next.
Example
Suppose we want a program which gives a discount of 10% if the purchase is over 100:
Scanner scanner = new Scanner(System.in);
double purchase;
double discount;
System.out.println("Enter purchase ");
purchase=scanner.nextDouble();
discount=0.0;
if (purchase>100)
discount=purchase*0.10;
purchase=purchase-discount;
System.out.println("After discount this is "+purchase);
This sets the discount to zero before the if. This means if the purchase is not over 100, the discount
is zero, but if it is, it is 10%.
Exercise
Try this out.
Java
Page 31 - Copyright 2012 Walter Milner - all rights reserved
Change it so you get a 20% discount.
Tracing an if
Tracing a program fragment might help to understand ifs. For example:
int x;
int y;
Scanner myScanner = new Scanner(System.in);
x=myScanner.nextInt();
y=1;
if (x>10)
y=2;
System.out.println(y)
Suppose the user inputs 12:
Memory Program Comment
x ?
y ?

int x;
int y;
Scanner myScanner = new Scanner(System.in);
x=myScanner.nextInt();
y=1;
if (x>10)
y=2;
System.out.println(y);
x and y declared
x 12
y ?

int x;
int y;
Scanner myScanner = new Scanner(System.in);
x=myScanner.nextInt();
y=1;
if (x>10)
y=2;
System.out.println(y);
scanner object
created (omitted)
and 12 input
x 12
y 1

int x;
int y;
Scanner myScanner = new Scanner(System.in);
x=myScanner.nextInt();
y=1;
if (x>10)
y=2;
System.out.println(y);
y becomes 1
x 12
y 2

int x;
int y;
Scanner myScanner = new Scanner(System.in);
x=myScanner.nextInt();
y=1;
if (x>10)
y=2;
System.out.println(y);
x is greater than
10, so y=2; is
executed
x 12
y 2

int x;
int y;
Scanner myScanner = new Scanner(System.in);
x=myScanner.nextInt();
y=1;
2 is output
Java
Page 32 - Copyright 2012 Walter Milner - all rights reserved
if (x>10)
y=2;
System.out.println(y);

Conditional as flowchart
This is another way of looking at ifs, as shown at the side.

ifs, semi-colons and blocks
Do NOT put a semi-colon at the end of an if header - this is WRONG:
if (x>4);
y=10;
As a result of Java syntax, this is allowable. So unfortunately the compiler will not
tell you it is wrong - but it is. The ; ends the statement, so the if stops there - and
y=10; is executed either way. In effect it says if x is greater than 4, do nothing.
Then just make y=10.
Often you want to do several things if the condition is true . A block will do this. This is just several
statements enclosed in curly brackets. For example
if (x>4)
{
y=10;
z=2;
}
A block does not need a semi-colon after it.
Else
We often want to do something if a condition is true, and something else if it is not. The if..else
structure does this:
if (something)
do option one
else
do option two
For example, suppose we want to accept a number only if it is greater than 10. We want to tell the
user whether it was accepted of not:
..
x=myScanner.nextInt()
if (x>10)
System.out.println("Accepted");
else
System.out.println("Not accepted");
Exercise
Write a program which inputs an integer. If the value inputted is greater than 50, output "Accepted".
Otherwise output the message "Too small".
Java
Page 33 - Copyright 2012 Walter Milner - all rights reserved
Indentation
Indentation means setting code in from the left margin by amounts which show the code structure.
For example:
if (x>100)
{
..
..
}
else
{
..
..
}
This helps to make things clearer, especially when we come to have ifs inside ifs and loops inside
loops. Many IDE editors will do this for you - right-click and choose Format.
Compound conditions
Suppose we want to require a value to be between 5 and 10. One way to do this would be to first
check if it was more than 5, then less than 10, with two ifs:
if (x>5)
if(x<10)
System.out.println("OK");
In this structure, the statement inside the first if is itself an if. This is OK - an if can contain any type
of statement.
But we can do the two tests together, like this:
if (x>5 && x<10)
System.out.println("OK");
The && means 'and' - so it reads if x is greater than 5 and x is less than 10..
The following is WRONG:
if (x>5 && <10)
System.out.println("OK");
You can say 'x is greater than 5 and less than 10' in English, but not in Java.
The symbol for 'or' is ||. So
if (x<5 || x<10)
System.out.println("OK");
says OK if x is less than 5 or greater than 10.
Equality and assignment
To test if two values are equal, use ==
if (x==5)
System.out.println("OK");
This says OK if x is 5, and nothing else.
This is WRONG:
Java
Page 34 - Copyright 2012 Walter Milner - all rights reserved
if (x=5)
System.out.println("OK");
x=5 is an assignment - it tells the system to make x 5. It should be x==5, which asks whether x is 5.
The symbol ! means NOT, so != mans not equal to:
if (x!=5)
System.out.println("OK");
accepts anything except 5.
You need to be careful with edge values. For example
if (!(x > 10))
System.out.println("OK");
means 'if x is not greater than 10'. So it accepts 10, or less.
Exercise
Write a program which accepts numbers up to 5 inclusive, and over 9, outputting 'OK', and
outputting 'Out of range' otherwise.
Java
Page 35 - Copyright 2012 Walter Milner - all rights reserved
Algorithms
Suppose we need some code to input two integers, and then outputs them in order of size, largest
first. So input 26, 20 outputs 26 20. Input 3,4 outputs 4,3:
import java.util.Scanner;

public class Main {

public static void main(String[] args) {
int x;
int y;
Scanner myScanner = new Scanner(System.in);
x = myScanner.nextInt();
y = myScanner.nextInt();
if (x > y) {
System.out.println(x + " " + y);
} else {
System.out.println(y + " " + x);
}
}
}
This is easy - we compare x and y, and if x is bigger, output x then y, otherwise y then x.
This is a simple algorithm.
An algorithm is a method or recipe or solution to a problem, as a series of simple logical steps. A
program is an implementation of an algorithm in a particular language.
For clever programming, finding the correct algorithm is more significant that actually writing the
program. Fortunately optimal algorithms for many standard tasks have been invented, and
sometimes even coded into languages.
Not so easy..
Suppose we need to input three numbers and output them in order, biggest first. How would you do
that? Before you read on, decide what algorithm you would use, and program it.
One algorithm would be
1. Find the biggest, and output it.
2. Find the middle and output it.
3. Find the smallest, and output it.
Finding the middle one is not easy. If the numbers are x y z, then x is the middle if the order is
y x z or z x y.
so we need to test if y is greater than x and x is greater than z, or z is greater than x and x is greater
than y.
Similarly for y or z is the middle one.
Here it is:
Java
Page 36 - Copyright 2012 Walter Milner - all rights reserved
int x, y, z;
Scanner myScanner = new Scanner(System.in);
x = myScanner.nextInt();
y = myScanner.nextInt();
z = myScanner.nextInt();
// find biggest
if (x > y && x > z) {
System.out.println(x);
}
if (y > x && y > z) {
System.out.println(y);
}
if (z > x && z > y) {
System.out.println(z);
}
// find middle
if ((x > y && x < z) || (x < y && x > z)) {
System.out.println(x);
}
if ((x > y && y > z) || (x < y && y < z)) {
System.out.println(y);
}
if ((z > y && z < x) || (z < y && z > x)) {
System.out.println(z);
}
// find smallest
if (x < y && x < z) {
System.out.println(x);
}
if (y < x && y < z) {
System.out.println(y);
}
if (z < x && z < y) {
System.out.println(z);
}
This is getting tricky. We have included comments like
// find biggest
to help keep track of what we are doing. Try this method.
Is it the best way? It uses 9 comparisons. If we've found the biggest and the middle, we should not
have to find the smallest - which suggests it is not.
An alternative algorithm is to simply test the 6 possibilities, which are
x y z
x z y
y x z
y z x
z x y
z y x
Here we go:
Java
Page 37 - Copyright 2012 Walter Milner - all rights reserved
int x, y, z;
Scanner myScanner = new Scanner(System.in);
x = myScanner.nextInt();
y = myScanner.nextInt();
z = myScanner.nextInt();
if (x > y && y > z) {
System.out.println(x + " " + y + " " + z);
}
if (x > z && z > y) {
System.out.println(x + " " + z + " " + y);
}
if (y > x && x > z) {
System.out.println(y + " " + x + " " + z);
}
if (y > z && z > x) {
System.out.println(y + " " + z + " " + x);
}
if (z > x && x > y) {
System.out.println(z + " " + x + " " + y);
}
if (z > y && y > x) {
System.out.println(z + " " + y + " " + x);
}

Exercise
Try this way. Do you think this is more efficient that the first? Could it be further improved?
Was your method more efficient?
What happens if two numbers are equal?
Java
Page 38 - Copyright 2012 Walter Milner - all rights reserved
Loops
Suppose we want to add up the first twelve integers. This does it:
int total=0;
total+=1;
total+=2;
total+=3;
total+=4;
total+=5;
total+=6;
total+=7;
total+=8;
total+=9;
total+=10;
total+=11;
total+=12;
This works, but it's a lot of typing. Suppose we needed to add up the first 12000 integers? This
method would be impractical.
The code above has almost the same statement total+=?; twelve times. What we need is a way to
execute the same statement several times.
We could use the statement total+=n; and change the value of the variable n. This would need to be
1, then 2, then 3, up to 12. Here it is
int total = 0;
int n;
n = 1;
while (n < 13) {
total += n;
n++;
}
System.out.println(total);
Study this code carefully. We have a new kind of statement - a while loop.
1. There is a loop header, while (n<13)
2. This is followed by the loop body - a block { } containing two statements: total+=n; and n++;
3. The loop body is repeatedly executed, so long as the condition (n<13) is true.
4. The index n is initialised to be 1.
The loop body is repeated. The first time, n is 1, so the first statement in teh loop body is in effect
total+=1;. The second statement, n++; increase n to be 2.
So on the next repeat, it does total+=2; and n is increased to 3.
On the third repeat it does total+=3;
This will continue up to and including n=12, when it does total+=12; and n increases to 13.
But then the condition to continue, n<13, is no longer true, so the loop terminates.
How could we modify this to add up integers from 1 to 20? Just change the condition:
Java
Page 39 - Copyright 2012 Walter Milner - all rights reserved
int total = 0;
int n;
n = 1;
while (n < 21) {
total += n;
n++;
}
System.out.println(total);
Add up the numbers from 10 to 20? Change the initialisation:
int total = 0;
int n;
n = 10;
while (n < 21) {
total += n;
n++;
}
System.out.println(total);
Add up the odd numbers from 1 to 1000? We need 1,3,5,7, so we need to start at 1 and go up in
steps of 2:
int total = 0;
int n;
n = 1;
while (n < 1001) {
total += n;
n+=2;
}
System.out.println(total);
Display the total as we go along? Have the output inside the loop body:
int total = 0;
int n;
n = 1;
while (n < 1001) {
total += n;
System.out.println("n = "+n+" total = "+total);
n+=2;
}
while loops
1. The condition must be in round brackets, like (n<13)
2. The condition can be any boolean expression, such as (n<13 && x!=5)
3. There should be no semi-colon at the end of the loop header
4. If there is just one statement in the loop body, it does not need to be a block - such as
while (n<10)
n++;
5. You might have an endless loop, such as

while (true)
total += n;

In this case, you would need to use the IDE to cancel the process, or use Task Manager in Windows.
do..while loop
The do while loop is very similar. The only difference is that the condition is checked at the end:
Java
Page 40 - Copyright 2012 Walter Milner - all rights reserved
int total=0;
int n=1;
do{
total+=n;
n++;
} while (n<10);
In most situations the choice of while or do..while is arbitrary. The only difference is that do..while
will execute at least once. In a while, if the condition is false the first time in, the loop body will
never be executed.
Exercise
Write a program which adds up the even numbers from 2 to 10 inclusive and outputs the total.
Test that it gives the correct answer
Change it so it adds the even numbers from 2 to 10000.

Programming with loops example
We often need some ingenuity to solve a programming problem with a loop. A key stage is to
recognise that a task involves repeating something, so a loop is needed.
Suppose we need to separate, and print separately, the digits of a number. So given 1234, it should
output
1
2
3
4
We need to do this for each digit - so we are repeating something and need a loop. Do we know
how many times to repeat? The number could be 1234 (4 times) or 54321 (5 times) or whatever, so
it is not a fixed number of repeats.
How to separate the digits? Use integer division by 10, and modulo. For example, if the number is
n=1234, then
n%10 is 4, the lowest digit, and
n/10 is 123. So change n to this, and loop. So we have an outline:

given the number n
while..
digit = n%10, and output it
n = n/10
When should the loop end? n will get smaller. On the last output, n is less than 10. Then it is zero. So
our code is

int n = 1234;
while (n > 0) {
int digit = n % 10;
System.out.println(digit);
n /= 10;
}
We have declared and assigned the variable digit inside the loop. This is OK.
This is not quite right - the output is least significant digit first, when we wanted most sgnificant first.
This is easily fixed using an array, which we will meet later.

for loops
The most common loop in Java is the for loop. This has a loop header and body like this:

Java
Page 41 - Copyright 2012 Walter Milner - all rights reserved
for (.........) {
// loop body
}


Here is an example, to add up the numbers 1 to 5:
int number;
int total;
total = 0;
for (int c = 1; c < 6; c++) {
number = c;
total = total + number;
}
System.out.println(total);
The loop header has three parts, separated by semi-colons. It goes
for ( start; loop so long as; change after each repeat )
So in our example, we start with c=1, we repeat so long as c is
less than 6, and after each repetition, it increases c by 1. In other
words, c goes 1 2 3 4 and 5. The loop body is repeated for each
of these. So the first time it says number = 1, then number = 2,
then number = 3, then - you've got it.

Exercise
Modify this program so it adds up the numbers 1 to 1000. Is it correct? If you cannot remember how
to work it out, google 'arithmetic progression'
Note that in the loop start:
int c=1;
we both initialise c to be 1, and declare it. We do not have to declare it here (it could have been
declared with the other variables) but it can be, and often is. If it is, it can only be used in the loop
body ('its scope is restricted to the loop')
Another example
This program outputs 100 down to 0 in steps of 2:
for (int c = 100; c > -1; c=c-2) {
System.out.println(c);
}

If the loop body has just one statement in it, you do not need the block (the curly braces). As with an
if, a semi-colon at the end of the header is WRONG. This is WRONG
for (x=0; x<100; x++);
{
..
}
The reason is the same as the if - the semi-colon ends the statement, and cuts off the loop body.
Java
Page 42 - Copyright 2012 Walter Milner - all rights reserved
Exercise
Write loops which will output
1. 0 1 2 3 4 5 6 7 8 9 10
2. 10 8 6 4 2 0
3. 5 4 3 2 1 0 -1 -2 -3 -4 -5
4. Write a loop which will calculate the total of 1+2+3+4+5..., stopping when the total exceeds 100.
5. Write a program which first inputs an integer n, then calculates and outputs 1X2X3X4X..n (which is
called n! or n factorial)
Nested loops
The statements in a loop body can be any type, including loops themselves. Look at the following
program:
for (int c = 1; c < 6; c++)
for (int d = 1; d<6; d++)
System.out.println(c+" "+d);
What do you think it will output?
Try it - can you explain what it does?
Exercise
1. Write a program which will output the 5 times table, like this
1 X 5 = 5
2 X 5 = 10
3 X 5 = 15
..
12 X 5 = 60
2. Extend this so it outputs all the multiplication tables, one after the other, from the 2 to the 12
times table.
break and continue
These are two new types of statements which can be used in loops (and conditionals).
You use continue; part way through a loop body. It misses out the rest of the loop body, and repeats.
You would usually use it with an if, like

while(...)
{
..
if (..) continue;
.. this is missed out if the if was true
}

break is similar, but it breaks out of the loop completely. So you might say:

while (true)
{
....
if (..) break; // ends the loop totally
..
}
You can break out of a loop, but not out of an if. This was a famous bug which crashed AT&T in 1990.
Java
Page 43 - Copyright 2012 Walter Milner - all rights reserved
Testing
Beware of bugs in the above code; I have only proved it correct, not tried it.
- Donald E. Knuth
Testing means checking a program works by trying to run it.
You should write program code in small sections, and test each small section before you write more.
Testing is a major aspect of software engineering. In Java, the JUnit framework is a formal way of
testing code. Since testing may take a long time, the process is sometimes automated.
However the beginner programmer needs to test code in an informal manner. To test, you need to
know what the output should be - otherwise you cannot tell if it works. For example, we might have
some code to convert Centigrade temperaturs to Fahrenheit:
int centi = 17;
int fahr = centi*9/5 + 32;
System.out.println(fahr);
If we run this, it outputs 62. However that does not help unless we know what the correct answer is.
In fact it is 62.6. Why is our code wrong? The correct answer is not an int, but we have used that as
the type. The correction is simple:
double centi = 17;
double fahr = centi*9/5 + 32;
System.out.println(fahr);
Sometimes thought is needed to work out how to test something - a testing strategy. For example,
you might be working on code to write data into a file, and read it back. You might write both the
writing and reading code at the same time. How to test it? If it does not work, is the writing wrong,
or the reading? The solution is to look at the file directly, say in a text editor. If it is wrong, the
writing code has the error. If it is correct, the reading code is wrong.
Java
Page 44 - Copyright 2012 Walter Milner - all rights reserved
Data Structures
In previous sections we have used data as single items. There are many situations where we need to
use many items of data in an organised structure. Some examples are
The color of the pixels in a line on a graphic image
The colour of the pixels in a rectangle
The set of exam marks for the students in a class
The transactions on a bank account
The frames of a video clip
The items in a data structure are called elements or nodes.
Data structures
Some standard ways of arranging data are

Linear list - data elements are
next to each other

Linked list - elements are linked
by pointers. They are not next to
each other in memory

Binary tree - each element is
linked to two others, except for
leaf nodes

Queue - elements join at one end
and leave at the other
Stack - elements join and leave at
the top
Data structures and algorithms
We need to be able to add new elements to the data structure, delete them, find one, and go
through everything in the structure - traverse it. How that is done - the algorithm - will depend on
which data structure it is. Some algorithms and data structures will use more memory and be faster
than others. The study of algorithms and data structures is central to classic Computer Science.
Java
Page 45 - Copyright 2012 Walter Milner - all rights reserved
Data Structures and Languages
There are two different ways of looking at this -
In the abstract, using diagrams like those above
Concrete implementations of these structures in a programming language. The structures
might be 'built-in' to the language, or it might be possible for the programmer to write their
own implementations
Both ways have their advantages. The abstract language-independent approach lets us focus on the
structure itself. A concrete implementation lets us use these theoretical ideas in reality.
Data Structures in Java
The Java language allows the programmer to implement most of these ideas. The standard classes
include the 'container' classes which already provide implementations of many of them, and
'generics' offer algorithms to use them. The only thing Java does not allow is direct access to
memory through actual numeric addresses - because this is a common source of bugs.
We will look in this section at one structure - the array.
Arrays
Imagine a street of houses. Each house has a distinct house number. Each house contains different
things.
We can think of an array like this. It is a set of boxes, or elements. Each element has a different
index, which is like the house number, except that Java arrays start at 0 rather than 1. Each element
contains some data. This could be any type, such as integers, doubles, objects or whatever - but they
have to be the same type. We can get to any element through its index - to read the data out of the
element, or to change it.
Streets have street names, and arrays also have names. In a Java program arrays are variables, and
like all variables we have to declare them before use. For example:
int[] myArray = new int[5];
This declares myArray to be the type 'array of ints', and it constructs an array with five elements -
indexed 0 to 4. Java arrays are indexed using [ square brackets ].
We can put values into the array to match the picture above using:
Java
Page 46 - Copyright 2012 Walter Milner - all rights reserved
myArray[0]=48;
myArray[1]=72;
myArray[2]=31;
myArray[3]=99;
myArray[4]=43;
Note the array index goes from 0 to 4.
We could output the values from the array like this:
System.out.println(myArray[0]);
System.out.println(myArray[1]);
System.out.println(myArray[2]);
System.out.println(myArray[3]);
System.out.println(myArray[4]);
Arrays and loops
The last two fragments show program code with very similar statements repeated. These are
situations where loops are appropriate. For example we can output the array with:
for (int i=0; i<5; i++)
System.out.println(myArray[i]);
Trace through this:
Execution Value of i Action
for (int i=0; i<5; i++)
System.out.println(myArray[i]);
i=0 Initialise i to 0
for (int i=0; i<5; i++)
System.out.println(myArray[i]);
i=0 Output myArray[0]
for (int i=0; i<5; i++)
System.out.println(myArray[i]);
i=1 Increment i, continue
for (int i=0; i<5; i++)
System.out.println(myArray[i]);
i=1 Output myArray[1]
for (int i=0; i<5; i++)
System.out.println(myArray[i]);
i=2 Increment i, continue
for (int i=0; i<5; i++)
System.out.println(myArray[i]);
i=2 Output myArray[2]
for (int i=0; i<5; i++)
System.out.println(myArray[i]);
i=3 Increment i, continue
for (int i=0; i<5; i++)
System.out.println(myArray[i]);
i=3 Output myArray[3]
for (int i=0; i<5; i++)
System.out.println(myArray[i]);
i=4 Increment i, continue
for (int i=0; i<5; i++)
System.out.println(myArray[i]);
i=4 Output myArray[4]
for (int i=0; i<5; i++)
System.out.println(myArray[i]);
i=5 Increment i, stop
Exercise
Run this program
Alter it so it outputs the array in reverse sequence. The index will need to start at 4 and stop after 0.
Java
Page 47 - Copyright 2012 Walter Milner - all rights reserved
Random numbers
How do we get numbers to put in the array? In real programs they come from pixels read in from a
jpeg or similar. For our study programs, we could input values from the keyboard using a Scanner,
but this is tedious and for an array with a 1000 elements, impractical. A good alternative is to use
numbers generated at random by the computer.
The class Math has a method called random which produces a number in the range 0 to 1 - a double
type with decimal parts. This is called Math.random().
If we multiply it by say 1000.0, we will have a random number in the range 0 to 1000. This is
Math.random()*1000.0
We can change this to a whole number by 'casting' it to an int. This is done by
(int)(Math.random()*1000.0).
Putting this in a loop, we have
for (int i=0; i<5; i++)
myArray[i]=(int) (Math.random()*1000.0);
Exercise
Follow this with the loop for outputting the array. Run the program several times. Do you get the
same random values each time?
Summing an array
We can add up all the values in an array by using the following simple algorithm
initialise a running total to 0
for each value in the array,
add the value into the running total
After this, the running total will be the sum of all the elements.
For example:
int[] myArray = new int[5000];
// fill array with numbers
for (int i=0; i<5000; i++)
myArray[i]=(int) (Math.random()*1000.0);
// find total
int total=0;
for (int i=0; i<5000; i++)
total+=myArray[i];
// output total
System.out.println("Total = "+total);
Exercise
Modify this so it outputs the average as well as the total.
Magic numbers
Magic numbers are numbers which appear in code, and do not have immediately obvious meanings.
For example in the loop header:
Java
Page 48 - Copyright 2012 Walter Milner - all rights reserved
for (int i=0; i<5000; i++)
the 5000 is a magic number. Why 5000? We know it is because the array has been declared to have
5000 elements, but in a long and complex program we might have forgotten this. Or (more likely)
your program is being read by another programmer who has the task of maintaining your code. Do
them a favour, help them out and make the code self-evident:
final int ARRAY_LENGTH = 5000;
int[] myArray = new int[ARRAY_LENGTH];
// fill array with numbers
for (int i=0; i<ARRAY_LENGTH; i++)
myArray[i]=(int) (Math.random()*1000.0);
// find total
int total=0;
for (int i=0; i<ARRAY_LENGTH; i++)
total+=myArray[i];
// output total
System.out.println("Total = "+total);
ARRAY_LENGTH is in capitals because this is the convention for constant values. Just by looking at it
we know it is supposed to be a constant.
It is declared to be a final int. This forces it to be constant - it can only be given a value in its
initialisation. If code further on changes it, it will not compile. This is an example of using a language
feature to make bug-free programming easier. The compiler will tell us if we go wrong.
If for some reason we decide the array length should be different, we just have to change one line of
code, where ARRAY_LENGTH is initialised. Otherwise we would have had to have searched for every
occurrence of 5000, check if it was appropriate, and change it if it was.
Finding extreme values
For example, how could we find the largest number in the array? And its location?
Here is an algorithm, using the idea of 'the biggest so far'.
Set biggestSoFar to be the first element
Set location to be the first
For each subsequent element:
If this element is bigger than the biggestSoFar,
Change biggestSoFar to be this element
Change location to be this location
At the end, biggestSoFar will be the biggest in the whole array.
Here is an implementation of this in Java:
Java
Page 49 - Copyright 2012 Walter Milner - all rights reserved
final int ARRAY_LENGTH = 5000;
int[] myArray = new int[ARRAY_LENGTH];
// fill array with numbers
for (int i=0; i<ARRAY_LENGTH; i++)
myArray[i]=(int) (Math.random()*1000000.0);
// find maximum
int biggestSoFar=myArray[0];
int location = 0;
for (int i=1; i<ARRAY_LENGTH; i++)
if (myArray[i]>biggestSoFar)
{
biggestSoFar=myArray[i];
location=i;
}
// output result
System.out.println("Largest is = "+biggestSoFar);
System.out.println("Located at = "+location);
The range has been changed to 0 to 1 million - otherwise the maximum is almost always 999.
Exercise
Make sure you understand every line in the above program.
Change it so it finds the smallest value.
How can you test this program?
Sorting
In computing, 'sort' means to arrange data in order.
In normal life, sorting means separating things out into different types. The reason why sort came to
mean ordering is a curious historical tale involving Herman Hollerith (the founder of IBM), the US
Census of 1901, and a method now called a radix sort. Google it for the details.
How could we re-arrange the numbers in our array into decreasing order, biggest first? Invent a
method.
One way would be to find the biggest (which we can already do) and swap it into first place. Then
find the second biggest, and swap it into second place. Then the third, and so on.
Our current find biggest starts at 0. Introduce another variable for where it starts:
// find maximum, from start
int start=0;
int biggestSoFar=myArray[start];
int location = start;
for (int i=start+1; i<ARRAY_LENGTH; i++)
if (myArray[i]>biggestSoFar)
{
biggestSoFar=myArray[i];
location=i;
}
Then exchange the biggest value with the one at the start. Remember the variable exchange trick we
saw before:
//swap values at start and location of max
int temp=myArray[start];
myArray[start]=myArray[location];
myArray[location]=temp;
Now we need to do this first with start as 0, then 1, then 2, and finally at one from the end.
In other words we need to enclose this in a loop:
Java
Page 50 - Copyright 2012 Walter Milner - all rights reserved
for (int start=0; start<ARRAY_LENGTH-1; start++)
{
..
}
After we've sorted it, we want to output the array in a loop. Here's the whole thing:
final int ARRAY_LENGTH = 5000;
int[] myArray = new int[ARRAY_LENGTH];
// fill array with numbers
for (int i = 0; i < ARRAY_LENGTH; i++) {
myArray[i] = (int) (Math.random() * 1000000.0);
}
// sort begins
for (int start = 0; start < ARRAY_LENGTH - 1; start++) {
// find maximum, from start
int biggestSoFar = myArray[start];
int location = start;
for (int i = start + 1; i < ARRAY_LENGTH; i++) {
if (myArray[i] > biggestSoFar) {
biggestSoFar = myArray[i];
location = i;
}
}
//swap values at start and location of max
int temp = myArray[start];
myArray[start] = myArray[location];
myArray[location] = temp;
}

// output array
for (int i = 0; i < ARRAY_LENGTH; i++) {
System.out.println(myArray[i]);
}
}
How many steps are involved in this method? To find the biggest we go through the whole array,
5000 steps. We have to do this 4999 times - about 5000. As we do this we don't have to do as many
steps - it goes from all to none, so averages half, or 2500. So the total steps is approximately 1/2
5000 X 5000, or around 12 million.
Exercise
Before you run it, roughly how long do you think it will take to sort 5000 numbers? That's 12 million
steps.
Copy and run this program.
Change the array length. Try a very small number - say 10. How long does it take? Try a bigger array -
say 100 000. That will be 5 billion steps. This is not an exceptionally large array - an image with a
resolution of 1000 by 1000 pixels has one million elements.
This method is a type of exchange sort. It is simple but slow.
Exercise
Think of a faster way. To get some ideas, google 'sorting algorithms'. Don't go mad. Find one you can
understand, and implement it in Java.
Java
Page 51 - Copyright 2012 Walter Milner - all rights reserved
Bitwise operations
All computer data is represented by strings of bits. Java has some operators which work at the bit
level, and their use can provide some insight into how data is stored.
Shift and masks
The >> operator shifts the bits in a number to the right - shifting 0s in on the left. So x>>1 shifts the
bits in x one place right, and puts a 0 at the front.
The & operator forms a bitwise AND mask. For example, what is 12 & 3 ? In base 2, 12 is 1010, and 3
is 0011, so
1010
0011 AND
----
0010 = 2
We are taking pairs of bits and forming the logical AND. 1 AND 0 is 0, 0 AND 0 is 0, 1 AND 1 is 1 and
so on.
& is the bitwise AND, while && is the logical AND eg if (x>7 && y<3)...
& masks are usually used to isolate certain bits from a pattern. For example, a mask with 1 gets the
right-hand least significant bit only. For example 15&1 is
1111 (15)
0001 AND
----
0001 (lsb of 15)
But 8&1 is
1000 (8)
0001 AND
----
0000 (lsb of 8)
| is the corresponding OR bitwise mask.
The bit shift and mask gives us a way of outputting a number as a binary string:
Java
Page 52 - Copyright 2012 Walter Milner - all rights reserved
// this code outputs the int b in binary
int[] result = new int[32]; // to hold the result

for (int n = 0; n < 32; n++) { // or each bit
result[n] = b & 1; // get and store lsb
b = b>>1; // shift right
}
int spacer = 0; // count places
for (int n = 31; n != -1; n--) { // msb first
System.out.print(result[n]); // output bit
spacer++;
if (spacer == 4) { // space every 4 bits
System.out.print(" ");
spacer = 0;
}
}
System.out.println(); // new line at end

then for example
b=18 outputs 0000 0000 0000 0000 0000 0000 0001 0010
We can also use this to show the effects of the shift:
b=1234 0000 0000 0000 0000 0000 0100 1101 0010
1234>>1 0000 0000 0000 0000 0000 0010 0110 1001
1234>>2 0000 0000 0000 0000 0000 0001 0011 0100
1234>>3 0000 0000 0000 0000 0000 0000 1001 1010
1234>>4 0000 0000 0000 0000 0000 0000 0100 1101

and the & mask:
b=58 0000 0000 0000 0000 0000 0000 0011 1010
58 & 0B1111 0000 0000 0000 0000 0000 0000 0000 1010
This also shows how we can write a number in base 2 in Java code.
Negative numbers
Look at this:
b=3 0000 0000 0000 0000 0000 0000 0000 0011
2 0000 0000 0000 0000 0000 0000 0000 0010
1 0000 0000 0000 0000 0000 0000 0000 0001
0 0000 0000 0000 0000 0000 0000 0000 0000
-1 1111 1111 1111 1111 1111 1111 1111 1111
-2 1111 1111 1111 1111 1111 1111 1111 1110
-3 1111 1111 1111 1111 1111 1111 1111 1101

Positive numbers are stored in their binary form. Negative numbes are stored (in Java) in something
called 2's complement. This is formed in 2 steps - change all the 1s to 0s and vice versa, then add 1.
For example
+3 = 0000 0011
1111 1100 (step 1)
+1 (step 2)
1111 1101 ( -3 in 2's complement).
Java
Page 53 - Copyright 2012 Walter Milner - all rights reserved
Inversion
~ switches 1s to 0s and vice versa.
Left shift
<< is left shift.
For example
123456 0000 0000 0000 0001 1110 0010 0100 0000
~123456 1111 1111 1111 1110 0001 1101 1011 1111
123456 << 3 0000 0000 0000 1111 0001 0010 0000 0000
Exercise
Use the code in this section to display a value in binary, to show the binary form of 123456, and the
effects of & masks, | masks, inversion and left shift


Java
Page 54 - Copyright 2012 Walter Milner - all rights reserved
Using a Debugger
As soon as we started programming, we found to our surprise that it wasn't as easy to get programs right as
we had thought. Debugging had to be discovered. I can remember the exact instant when I realized that a large
part of my life from then on was going to be spent in finding mistakes in my own programs.
Maurice Wilkes discovers debugging, 1949

This is about using a debugger - a piece of software which provides features to help debug code.
We will show this in NetBeans - other debuggers have similar features.
Suppose our code is:
int[] data = new int[100];
for (int i = 0; i < data.length; i++) {
data[i] = 5;
}
int total = 0;
for (int i = 1; i < data.length; i++) {
total += data[i];
}
System.out.println(total);
So we are filling an array of 100 ints with the value 5, then adding them up, and getting the answer
495 not 500. Why?
The best approach is to read the code carefully - the bug is fairly obvious. But let's pretend we can't
see it, and follow it through in a debugger.
Debugger features
A debugger offers the facility to execute single steps of code and observe the values of 'watch'
variables after each step. In more detail:
1. Step over - this means execute a single step of code. If it is a method invocation, we step
over the method and carry out. For example, if it is System.out.println, we do not want to go
thorugh all the steps in println, since that would take a long time, and we know it is error-
free
2. Step into - trace into a method - opposite of step over
3. Step out - finish this method invocation trace immediately
4. Run to cursor. We might start with a thousand lines of code which we know are OK. We do
not want to have to step through all of those. So place the cursor on the first suspect line,
and run at full speed to this point.
5. Add watch. Choose another variable - or expression - to display the value of.
6. Set breakpoint. A place in code where execution should pause, if some condition is true.



Java
Page 55 - Copyright 2012 Walter Milner - all rights reserved


Using a debugger
Go Debug.. Debug Main project, then
Run to cursor. We have run over the
initial loop, and we are about to
execute total=0

Watch variables there. The array has
been initialised as we expected

F8 step over. total is now 0. We are
about to start the second loop

Java
Page 56 - Copyright 2012 Walter Milner - all rights reserved
F8. About to execute loop body first
time. i is 1

F8. We have executed total +=data[1]
so total is now 5. But what happened to
data[0]?

We have found the bug.


This outlines how to use a debugger. This is a powerful technique, but it takes time to set it up. Use a
debugger to find bugs as a last resort.


Java
Page 57 - Copyright 2012 Walter Milner - all rights reserved
Type casts
Here is a reminder of the Java primitive types

Whole numbers byte - 1 bytes long
short - 2 bytes long
int - 4 bytes long
long - 8 bytes long
Decimal numbers float - 4 bytes long
double - 8 bytes long
Character char - 2 bytes long
Boolean boolean

What happens if we assign a value of one type to a variable of another type? For example
int x = 56;
long y = x;
No problem - no compile-time or runtime error.
In fact a type conversion is taking place. The 4 bytes of the int and being widened to the 8 bytes of
the long. This is a widening conversion and there is no problem.

But

int x = 56;
short y = x;

is a compile-time error, a 'possible loss of precision'. This is because we are trying to put the 32 bits
of an int into the 16 bits of a short, so we might lose some - a narrowing conversion.

If we are sure there will not be a problem, we can tell the compiler we understand what we are
doing:

int x = 56;
short y = (short) x;
Here the (short) is a type cast - an instruction to change the type.

If we don't understand what we are doing, we may get an unexpected result:

int x = 70000;
short y = (short) x;
System.out.println(y);
this outputs 4464. This is because 70000 is too big to fit into 16 bits, and the lost bits were not all
zero.
Or
int x = 0B1111_1111_1111_1111_1111; // 20 1 bits
short y = (short) x; // reduce to 16
System.out.println(y);
outputs -1. This is because y is 1111111111111111, which is the 2's complement form of -1. The 0B
notation to write values in base 2 only works from Java 7 onwards.
In summary - changing to a type with more bits works no problem. If you want a change to fewer
bits, you must use a type cast like (short), and you may lose bits.
Java
Page 58 - Copyright 2012 Walter Milner - all rights reserved
The brackets on a type cast are unusual - they go around the type, not what you are going to cast.
This means you often need another pair of brackets.
For example, suppose we want random integers up to 100. Math.random() produces a random
double from 0 to 1. So we could multiply by 100 then cast to an int:
int x = (int) Math.random()*100;

but this is always 0. Why?
Because the type cast is applied first to the 0.something, producing 0, then 0*100 is 0. We must
multiply first, then do the typecast:
int x = (int) (Math.random()*100);

Exercise
What happens if you do a widening conversion?
When is an explicit type cast required?


Java
Page 59 - Copyright 2012 Walter Milner - all rights reserved
Structured Programming

This topic is about the structure of source code.
So far, we have seen less than around 20 lines of code in each program. In real applications, there
would typically be millions of lines of code. That means it is important to think about how that code
is structured. The structure might be arranging it in separate parts, units, blocks, modules or any
kind of section. This is a question of modularity. The option of having a million lines of code in a
single unit is impractical.
Splitting code into smaller units has clear advantages. Small units are simpler and easier to write.
They are easier to test. They can be written by teams. The units can be re-used in other projects.
The units used in this section are called 'static methods'.The reason why this term is used will be
clearer later. The style of programming here is not object-oriented - it is more in the style known as
structured programming, as used in C and Pascal. But it is a useful preliminary to OOP.
As well as splitting up the code, we need a way to pass data from one section to another. This is
known as parameter passing or argument passing.

Java
Page 60 - Copyright 2012 Walter Milner - all rights reserved
Static methods and parameter passing
Suppose we have two variables, called x and y, of type double, and we want to find their average.
Not a problem - just add them up and divide by 2:
double x=28.0;
double y=17.6;
double average=(x+y)/2.0;
Now suppose we want the average of a and b:
double a=8.0;
double b=107.6;
double average2=(a+b)/2.0;
But maybe we want to find the average of several hundred pairs of values. There are two issues - we
would have almost the same piece of code (adding and dividing by 2) duplicated hundreds of times.
But we also need the code to apply to different variables.
The solution is like this:
class Test {

static double average(double d1, double d2) {
double a;
a = (d1 + d2) / 2.0;
return a;
}

public static void main(String[] args) {
double x = 12.3;
double y = 3.4;
double z;
z = average(x, y);
System.out.println(z); // about 7
}
}
Follow through what happens:
1. Execution starts at main
2. Variables x and y are declared and assigned initial values.
3. Variable z is declared
4. We have an assignment z = average(...
5. This invokes the method named average. Execution switches to the block of code starting 'static
double average..'
6. The values of x and y in main are copied to d1 and d2, respectively, in the 'average' code block.
7. In average, a variable 'a' is declared, and there is a calculation to work out the average of d1 and
d2.
8. The code block returns the value 'a'.
9. Execution returns to main, at the point it came from. The value returned from 'average' is
assigned to z
10. z is output - so we can check it has worked.
In 'static double average..', the word double means that the type of the returned value is double.

Java
Page 61 - Copyright 2012 Walter Milner - all rights reserved
The execution path

Execution starts at main. When the
invocation of 'average' is reached,
execution switches to it. At the
'return' statement, execution
switches back to where it came from
(here, in 'main'), and carries on from
there.


The data path
The value of x is copied to d1. The value of y is
copied to d2.
The return value, 'a', is assigned to z.
The parameters in the method header (here, d1
and 2) are sometimes called the formal
parameters. The parameters in the method
invocation ( x and y) are the actual parameters.
So the values of the actual parameters are
copied to the formal parameters.
Exercise
Modify this so that it finds the average of 3
values. Test it.
How it works
The method invocation process works using a data structure called a stack. A stack is simply a pile of
data. Data items are added to the stacked ('pushed') by placing them on top of the stack. Data is
removed (popped) by taking the top item off the stack. The effect is that a stack is a last in, first out
(LIFO) structure. The item that comes out of it will be the last thing that was put in it.
When a method is invoked, the current address (location of the program instruction) is pushed onto
the stack. At the end of a method (the return statement) a value is popped off the stack, and
execution proceeds from there - in other words, it returns to where it came from.
The issue is that inside a method, we might have an invocation of another method, and so on. In fact
we already have this in this example, since the method 'average' is invoked from the method 'main'.
But using a stack means there will not be a mix-up. No matter how many method invocations there
are, it will always return to the last one invoked, which is what is needed.
Java
Page 62 - Copyright 2012 Walter Milner - all rights reserved
What if a method invokes itself? This would require an infinitely big stack. Your program will end,
with the error message 'Stack overflow'. See the section on recursion.
The stack is also used to pass parameters. At the invocation, the return address is pushed onto the
stack. Then copies of the actual parameters (x and y) are pushed onto the stack. At the start of the
method, the correct number of values are popped off the stack (here 2) and placed in the formal
parameters (d1 and d2). Just 1 value, the return address, is left on the stack, ready for the return
statement.
Another example - factorial
The factorial of a number n (usually written n!) is 1 x 2 x 3 x.. n. So for example 3! is 1 x 2 x 3 = 6.
We could have a method to calculate factorials:
class Test {

static long factorial(int n) {
long temp = 1;
for (int i = 2; i <= n; i++) {
temp *= i;
}
return temp;
}

public static void main(String[] args) {
for (int n = 1; n < 21; n++) {
System.out.println("n= " + n + " n! = " + factorial(n));
}
}
}
Check how the factorial method works.
In main, we use a variable n. We also use n as the name of the formal parameter in the factorial
method. Does it matter? Will the values of the two n's get mixed up? No.
The name of the actual parameter is n, same as the formal parameter. Does that matter? No.
Does a formal parameter have to have the same name as the actual parameter? No. Can it? Yes.
Exercise
A nth. triangular number is the sum of all integers from 1 to n. So the fourth is 1+2+3+4 =10.
Write a program which has a static method to find the nth triangular number, and which outputs the
first 10 triangular numbers.
The Math class
Suppose we want to use the sine function. How to do that? We could write our own static method,
calculating a sine as a power series expansion, but it might be tricky. We don't have to, its already
there.
The Math class has a collection of static methods for all the usual maths functions. We use it by
invoking Math.sin() (taking its argument=parameter in radians). The class also has Math.PI as a
constant. So for example
Java
Page 63 - Copyright 2012 Walter Milner - all rights reserved

System.out.println(Math.PI);
System.out.println(Math.sin(Math.PI/6));
double angle = 2.0; //radians
double sin = Math.sin(angle);
double cos = Math.cos(angle);
System.out.println(sin*sin+cos*cos);
which outputs:
3.141592653589793
0.49999999999999994
1.0
Remember that floating point arithmetic is not totally accurate.
Exercise
Write a program which inputs the radius of a circle and outputs its area.
Java
Page 64 - Copyright 2012 Walter Milner - all rights reserved
Scope
Instead of finding the average of x and y as (x+y)/2, we could calculate it as x/2+y/2. For example:
public class Test {

static double average1(double x, double y) {
double result = (x + y) / 2;
return result;
}

static double average2(double x, double y) {
double result = x / 2 + y / 2;
return result;
}

public static void main(String args[]) {
double x = 3;
double y = 4;
double z;
z = average1(x, y);
System.out.println(z);
z = average2(x, y);
System.out.println(z);
}
}

This works as expected.
But both methods declare a local variable 'result' with the same name. Will this name clash be a
problem? No. Why not? Because they are in different scope.
Suppose we go back to one method, and refer to 'result' in 'main':
public class Test {

static double average1(double x, double y) {
double result = (x + y) / 2;
return result;
}


public static void main(String args[]) {
double x = 3;
double y = 4;
double z;
z = average1(x, y);
System.err.println(result);
}
}
This is a problem - we get a compile-time error, and the compiler complains that 'it cannot find the
symbol result'.
Another example:
scope of 'result'
'result' is out of scope
Java
Page 65 - Copyright 2012 Walter Milner - all rights reserved
static double average1(double x, double y) {
if (x > 5) {
double result = (x + y) / 2;
}
if (x > 7) {
double result = (x + y) / 2;
}
return 3.5;
}
Here we have declared 'result' twice in the same method. This is not a problem. We have two blocks,
enclosed in { }, and scope is limited to that block. The two 'result's are in different scope.
Why was Java (and Pascal and C and C++ and most versions of Basic and many other languages)
designed like this? It means that when choosing a local variable name, you do not need to worry if
you have used the same name elsewhere. With an application with many thousand lines of code,
written by a team, and using variable names like x and y and result and count and sum, that would
otherwise be a big problem. With local variables having limited scope it is not a problem.



Java
Page 66 - Copyright 2012 Walter Milner - all rights reserved
Recursion

Recursion is a programming technique in which a method invokes itself.
Recursive factorial
Recall that n factorial n! = 1 x 2 x 3 x..n
An equivalent way of defining this is to say that
if n==1, n!=1
else n! = n x (n-1)!
Look at that carefully.
Here it is in Java:
static long factorial(int n) {
if (n == 1) {
return 1;
} else {
return n * factorial(n - 1);
}
}
This is recursive, since the factorial method refers to the factorial method.
Exercise
Use this to output 2! to 10!

About recursion
Recursive methods are often very short, very elegant and very close to a mathematical definition (as
in this case).
Once you get the idea, they are very easy to write.
A recursive method can always be 'unrolled' into an iterative (looping) method. The previous section
had a factorial method with a loop.
They are sometimes highly inefficient.
Fibonacci sequence
The famous Fibonacci sequence is 1,1,2,3,5,8,13.. We start off 1,1 then add the last two numbers.
So the definition is
if n=1 or 2, fib(n)=1
else fib(n)=fib(n-1)+fib(n-2)
and in Java:
Java
Page 67 - Copyright 2012 Walter Milner - all rights reserved
class Test {

static long fib(int n) {
if (n == 1 || n == 2) {
return 1;
} else {
return fib(n - 1) + fib(n - 2);
}
}

public static void main(String[] args) {
for (int i = 1; i < 20; i++) {
System.out.print(fib(i)+" ");
}
}
}
which outputs
1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597 2584 4181
There is a large and significant branch of mathematics related to the Fibonacci sequence. Google it.
An entire research journal is devoted to it.
The time complexity of recursive methods
When we compare different algorithms, we look at how much memory they use (space complexity)
and how much time (time complexity). Ideally we want algorithms which are small and fast.
For our recursive Fibonacci - if we work out fib(20), how many times will the method be invoked?
Spend some time trying to work that out.
We can modify the code to count it for us:
class Test {

static int count = 0;

static long fib(int n) {
count++;
if (n == 1 || n == 2) {
return 1;
} else {
return fib(n - 1) + fib(n - 2);
}
}

public static void main(String[] args) {
fib(20);
System.out.println(count);
}
}

The answer is 13529. Why?
fib 20 -> fib 19+ fib 18
fib 17 + fib 16
fib 15 + fib 14
fib 16 + fib 15
fib 18 + fib 17
fib 16 + fib 15
fib 17 + fib 16
So this, just the beginning, shows fib 18 is called twice, fib 17 3 times, fib 16 4 times and so on. There
is a large amount of repeated calculation, and we end up with 13529 calls.
Java
Page 68 - Copyright 2012 Walter Milner - all rights reserved
Iterative Fibonacci

Here is an iterative version:
class Test {

static int count = 0;

static long fib(int n) {
count++;
long last1 = 1, last2 = 0, next = 0;
for (int i = 0; i < n; i++) {
next = last1 + last2;
last2 = last1;
last1 = next;
}
return next;
}

public static void main(String[] args) {
fib(20);
System.out.println(count);
}
}
In this, fib is invoked just once. So this algorithm is 13000 times faster when n=20. This is a good
illustration of the fact that the choice of a different algorithm can sometimes produce code whichis
very much faster.
It can be proved that any recursive procedure can be re-written as an iterative one.
But sometimes recursion is efficient. Remember it!
Java
Page 69 - Copyright 2012 Walter Milner - all rights reserved
When it does not work
What do you do when a Java program goes wrong? There are three case
1. It won't compile. This is easy to fix.
2. It compiles and runs, but crashes. In Java this will involve 'thowing an exception'. This is fairly easy
to fix.
3. It compiles and runs, but does the wrong thing, or outputs the wrong result. This is a problem.
We will look at each case
Compile error
These are easy to fix, because the compiler will tell you the line where the error is, and some clue as
to what the error is. In NetBeans and Eclipse, the IDE will flag the error with an ugly red line before
you run it. For example in NetBeans:

The light bulbs at lines 9 and 10 mean information. The red exclamation marks mean an error. The
red wavy line under d means there is some problem with it.
Hover the mouse over the information, and it tells you the error message:

The phrase 'cannot find symbol - symbol variable: d' means the compiler cannot work out what 'd' is.
This usually means you have forgotten to declare it, which is the problem here. It says it three times
because d occurs three times in that line. The compiler is telling you what the problem is and where
it is - its easy to fix. Just declare d.
Java
Page 70 - Copyright 2012 Walter Milner - all rights reserved

Run-time exception
The first version of Java was developed for the software in TV remotes. If a TV remote crashes, the
user is going to be quite annoyed. So Java was developed to handle run-time errors in a controlled
way.
These events are called exceptions. For example:
There is no red waviness so no compile-time errors. But when we run it:

we get an exception. Read the message carefully. The type of exception is
java.lang.ArithmeticException. So its something to do with arithmetic. / by zero is divide by zero.
Then it tells us where - at Main.main - in other words, in the method called main, in the class called
Main. And Main.java:8 means it is at line 8 in the file called Main.java. Pretty easy to fix.
In practice exception messages are a lot more tricky to read than this. Here we just have one
method, called main. What often happens is that we have one method which uses another, which
uses another, which uses another, maybe to a depth of ten, and the exception occurs at the tenth
level, causing one at the ninth, and so on, each of which are reported. So many of the exceptions are
not in code you have written. But you have caused it, indirectly. Look towards the top at files you
have written, and look in them at the line numbers indicated.
Incorrect programs
In formal software development, you start with a specification - a statement of what the program
should do, in terms of possible input and required output. A program which performs according to
this specification is correct. Otherwise its incorrect.
In other words the program runs, but it does the wrong thing and produces the wrong output. This is
hard to fix. In effect it is a detective novel, a whodunnit, and you have to find the guilty party.
Usually this is done by a combination of hunch and logical deduction.
Here are some suggestions
1. One piece of evidence is the output - what it actually does. Can you make sense of that? How
could the actual output have been caused?
Java
Page 71 - Copyright 2012 Walter Milner - all rights reserved
2. Can you work out which piece of code is causing the error? You should write and test code in very
short pieces. Do not write code like an essay, 2000 words at a time. Write at most 10 lines, and test
it. This means you can be fairly confident (does not always work) that what you have written is
correct. Or if it goes wrong, look in the last ten lines you have written.
If you have written 2000 lines of code since you last tested it, the bug is anywhere in those 2000
lines. You might as well start again, this time 10 lines at a time.
3. Use comment debugging. This means enclosing some lines of code in comments. If you still get the
error, those lines are correct, and you can uncomment them. This avoids deleting and re-writing
correct code.
4. Use print debugging. Use System.out.println to output the value of a variable in suspicious code.
Do you get the value you think it should be? The prize is when you find an incorrect value. You can
then work backwards from there - how could it have got that value? You are close to the solution.
5. Check the algorithm. Is the method of solution actually correct? This might involve paper and
pencil calculation. Chose an easy case.
6. Use a debugger. IDEs usually have a built-in debugger, which lets you step through the code one
statement at a time, and set up 'watch variables' so you can see the values they take on step by step.
You also have options like 'run to cursor', 'step into' and 'step over'. Because it takes time to set the
debugger up, avoid this if possible. Sometimes it isn't possible.
Java
Page 72 - Copyright 2012 Walter Milner - all rights reserved
OOP

Java is an OOP language - it uses object-oriented programming. This is a different approach to
programming from structured programming. The code we have seen up till now has not been typical
Java.
This section introduces the key ideas of class and object.
It provides some examples of using common Java classes

Java
Page 73 - Copyright 2012 Walter Milner - all rights reserved
Classes and objects
Objects
Variables like ints or doubles can be thought of in two ways - data storage in memory, or as
representing quantities in the real world. Similarly we can think of objects in two ways. We can think
of what they actually are in memory, and what the idea is, in terms of what they represent.
Objects in Java represent things. Here are some examples of objects
Objects Context
Buttons, windows, scroll bars, drop-
down lists, combo boxes
GUI programming
Employees, managers, departments HR - personnel management
Aliens, demons from hell, monsters Video game
Accounts, cheques, direct debits Banking
Goods for sale, customers, orders Sales management
Files, directories, drives, computers File management
Aircraft, flights, runways, air lines Air traffic control
Some objects represent real physical objects in the real world, such as aircraft. Others are in the
virtual world of the computer, such as a file.
All objects are things. Objects are nouns.
Exercise
What objects would you expect to have in a program used to manage a veterinary clinic?
Objects in memory
As a Java program runs, objects are created and sometimes destroyed. They are held in memory.
The information held in each object is held in a block of memory.
Sometimes objects are made to persist by storing them in a file, so that they can be accessed again
the next time the application runs.
What is in an object?
Objects have two kinds of members:
Fields. Sometiems called data members. These are pieces of data about the object needed by the
program. For example, an employee would have a payroll number. A window has a title and a
background colour. Data members might be primitive types like ints, or they might be objects
themselves.
Methods. These are pieces of code which are blocks of instructions appropriate when an object does
something. For example an employee might have a method called changeDepartment, which does
what is needed when an employee moves to a different department. A window might have a
method for dealing with a button click. Methods are verbs - doing words.
There is also have a third kind of item:
Constructors. These are pieces of code which do what is needed when a new object is created. This
might involve initialising values for data members, or constructing some other objects.
Java
Page 74 - Copyright 2012 Walter Milner - all rights reserved
Classes
Imagine a window in a GUI program. The window might have four buttons on it. That's four objects.
But they are all buttons. They are all the same type. A class is a type of object.
Or:
Class Objects
Cat - The cat (Felis catus), also known
as the domestic cat or housecat to
distinguish it from other felines and
felids, is a small furry domesticated
carnivorous mammal that is valued
by humans for its companionship and
for its ability to hunt vermin and
household pests.
From Wikipedia, the free
encyclopedia







A class is a type of object.
When a Java program creates an object belonging to a class, we say the object instantiates the class.
Or, the object is an instance of the class.
Class names start with a capital letter. Objects do not. So we might have a class called Cat, and an
object, an instance of the Cat class, called tufty.
Classes objects and code
A Java application will use existing classes,
creating objects which are instances of them.
But an application will also set up new
classes. The programmer needs to specify
what fields, methods and constructors the
class has - in a class definition. Each class
definition is in a different source code file,
which has the same filename as the name of
the class. So if we define a class called Cat, it
must be in the file called Cat.java.
One of those class definitions must have a method called public static void main. This method is the
point where the application will start execution :
Encapsulation
One aspect of OOP is the idea of encapsulation. The point of this is to 'seal up' the contents of an
object, in order to ensure that the data in it cannot be corrupted by program bugs. The problem we
are trying to fix is the possibility that bugs in a program might corrupt the data in an object and
render it invalid. The solution is to ensure that wherever possible, the data members cannot be
accessed from outside the class.
Java
Page 75 - Copyright 2012 Walter Milner - all rights reserved
The solution is implemented by two ideas - access control and accessor methods.
Access control is achieved by the use of the keywords public and private (plus others). If a member is
public, it can be accessed from anywhere. If it is private, it can only be accessed from inside the
class. Most members, especially data fields, should be private. Sometimes they cannot be - for
example
public static void main(String[] args)
has to be public, since it must be executed by the runtime system, outside the class.
However, we often need to be able to 'read' the values of data members - for example, finding out
the width of a window. Sometimes we want to 'write' a new value - such as changing the width of a
window. And we want to do this and still keep the data members private.
This is achieved by having public accessor methods. A getter method allows data members to be
read from outside the class. These usually start with 'get' - such as getWidth. They are very simple.
To 'write' a new value to a private data field, we use a public setter method. An example would be
setWidth. Such methods should include checks to ensure that the value being set is valid. For
example, attempts to make the width of a window negative are ignored.
Exercise
1. What is an object?
2. Objects have three kinds of things - what are they?
3. How are classes and objects related?
4. How are classes and the source code files making up an application related?
5. What is the purpose of encapsulation?
Java
Page 76 - Copyright 2012 Walter Milner - all rights reserved
Characters and Strings
The char type is a primitive - a simple value, not an object. A char literal is enclosed in single quotes
like 'x' (not double quotes like "x" which is a string). So
char myChar='a';
System.out.println(myChar);
A char is internally represented as a 16 bit number, being the Unicode (Google) code for a character.
The first of these are the same as the older 7 bit ASCII code set. For example, 65 to 90 are the letters
A to Z:
char c;
for (int code=65; code<91; code++)
{
c=(char)code; // type cast the number to the equivalent char
System.out.print(code+" "+c+" : ");
}
outputs:
65 A : 66 B : 67 C : 68 D : 69 E : 70 F : 71 G : 72 H : 73 I : 74 J : 75 K : 76 L : 77 M : 78 N : 79 O : 80 P :
81 Q : 82 R : 83 S : 84 T : 85 U : 86 V : 87 W : 88 X : 89 Y : 90 Z :

We can also have a char literal as its Unicode value, in hex, directly:

char uniChar = '\u0030'; // hex 30 = decimal 48 = digit zero

The visual appearance will depend on which character it is, and which font is currently being used.
Some (most) fonts cannot display all 65000 Unicode characters.
On Windows, the CharMap utility is useful for finding characters and their codes.

The first 32 ASCII characters are usually treated as 'control characters' in the sense of controlling the
output rather then displaying normal symbols. These are mostly historical, being used to control the
position of the head of a teletype machine. But some are still useful:
char uniChar = 10; // line feed
System.out.println(uniChar); // produces 2 new lines
The line feed can also be represented as an 'escape sequence':
char uniChar = '\n'; // new line
System.out.println(uniChar);

Strings
A char is a primitive type representing one character. A String in Java is a sequence of zero or more
characters. Strings are objects, instances of the class String.
For example:
String s = "Hello from Java"; // make a string
System.out.println(s); // output it
s="line one \n line two"; // two lines
s="one "+"two"; // + concatenates = joins, strings
int x=4;
s="x = "+x; // s is 'x = 4'
s=""; // s is a string with no characters
s=null; // s is null - not the same as ""

Java
Page 77 - Copyright 2012 Walter Milner - all rights reserved
The String class has many useful methods.
We can invoke a method (make it happen) on an object by using the syntax
<object name>.<method>()

Some methods take parameters, others do not.

Here are a few examples

String s = "Hello from Java"; // make a string
int n = s.length(); // length of string = 15
// getting parts of a string
char c=s.charAt(1); // 'e'. Character at some position - first char is position 0
String s1=s.substring(1, 3); // s1 is "el". Part of a string
s.contains("from"); // true. Does it contain another string
s.equals("Hello from Leicester"); // false. Compares two strings
s.indexOf("from"); // 6. Location of one string in the other. -1 if not there
s.startsWith("Hello"); // true
s.replace("Java", "C++"); // returns "Hello from C++"
String[] words= s.split(" "); // words is an array of 3 strings "Hello", "from" and "Java"
Exercise
Try this out.

There are several ways to convert between numbers and strings. For example:
int i;
double d;
String s3 = Integer.toString(i);
String s4 = Double.toString(d);
and the other way round:
String s1="28";
String s2="1.24";
int i = Integer.parseInt(s1);
double d=Double.parseDouble(s2);
When a string is changed into a number, there is the chance that the string is not a valid number -
such as 1.2.3. In this case a NumberFormatException will be thrown, which you can catch:
String s="1.2.3";
double d;
try{
d=Double.parseDouble(s);
}
catch (NumberFormatException nfe)
{
System.out.println("Its gone horribly wrong");
// put code here to fix things
}

But in Java strings are unusual objects, in that

Strings are immutable
This means a String object, once created, cannot be changed. It often looks like we are changing a
string object, when in fact we are creating a new one and setting a reference to it. For example
String s="One"; // make a String object, and set s to refer to it
s="Two"; // Do NOT change the "One" string - make a new string, "Two", and set
// s to refer to it
or
Java
Page 78 - Copyright 2012 Walter Milner - all rights reserved
String s="ABC";
s = s+"DEF"; // makes a new string, from ABC and DEF
Sometimes this does not matter much. Sometimes it does - for example:
String s = "A";
for (int i=0; i<1000; i++)
s+="A";
This creates 1001 String objects. It loses all but 1 reference to them, so it creates 1000 garbage
objects.
Consequently it is sometimes better to use some alternatives.
Arrays of char
An array of char is the same as an array of anything else - we can certainly change its elements. The
String class has a method toCharArray which creates an array of the chars from a String, and there is
a String constructor which takes a char array as argument. For example, the following turns a String
to an array of chars, then swaps characters to reverse the array:
String s = "What a fine mess";
char[] array = s.toCharArray();
int size = array.length;
for (int i = 0; i < size/2; i++) {
char temp = array[i];
array[i] = array[size - i - 1];
array[size - i - 1] = temp;
}
String reverse = new String(array);
System.out.println(reverse); // ssem enif a tahW
The point of this is avoiding creating a large number of intermediate String objects.
StringBuilder and StringBuffer
A StringBuilder is in effect a mutable String. The class has a reverse() method, so this is even easier
than with a char array:
String s = "What a fine mess";
StringBuilder sb = new StringBuilder(s);
sb = sb.reverse();
String reverse = new String(sb);
System.out.println(reverse);
StringBuffer is the same as a StringBuilder, except that it is thread-safe - wich means that your
program is running several threads which might access the same data at the same time, StringBuffer
will ensure it will work correctly - while StringBuilder will not. On the other hand, it will be slightly
slower.
So, no threads => use StringBuilder. Threads, use StringBuffer.
Exercise
Write a static recursive method which reverses a String. The header should be
static String reverse(String s)
It should follow this pseudo-code:
if the length of s is one, return s
else return reverse(s with first char omitted) + first char of s
Test it works.
Java
Page 79 - Copyright 2012 Walter Milner - all rights reserved
How efficient is this?
Re-write it using StringBuilder instead.

Java
Page 80 - Copyright 2012 Walter Milner - all rights reserved
A first look at Swing
Swing is a set of packages which provide the programmer with what is needed to write GUIs
(graphical user interfaces). We will use them to provide examples the idea of classes and objects.
Hello World - in a GUI
Our first Java program outputted the String "Hello World!". Here it is again, as a GUI:
import javax.swing.JFrame;

public class Main {

public static void main(String[] args) {
JFrame myWindow = new JFrame("Hello world!");
myWindow.setBounds(50, 50, 300, 200);
myWindow.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
myWindow.setVisible(true);
}
}
This outputs:

We will take this one line at a time. The important point is how we are using concepts about classes
and objects.
Swing contains a class called JFrame which is a GUI 'window'. A class is a type of object.
The line
JFrame myWindow = new JFrame("Hello world!");
does two things. Firstly it declares a variable, named myWindow, which is of type JFrame. Secondly it
actually makes a new object, and sets myWindow to refer to it.
Constructing a new object is done using the keyword new. Classes have a constructor, which does
what is needed to create a new object - a new instance of the class. The fragment
.. = new JFrame("Hello world!");
invokes the constructor of the JFrame class, making a new object - a JFrame object.
We still have a little work to do. We have to tell that window object to do various things, using setter
methods :
myWindow.setBounds(50, 50, 300, 200);
tells the window object to have a position and size. These are determined by the 50,50,300,200. The
first two numbers fix the position of the top left of the window, relative to the top left of the screen.
Java
Page 81 - Copyright 2012 Walter Milner - all rights reserved
So this window appears 50 pixels in from the left, and 50 pixels down from the top. The next two
numbers fix the width (300 pixels) and height (200 pixels).
Something like setBounds is a method. A method is a process which an object can perform. This has
been programmed into the definition of the class.
Note the syntax. The pattern is to say
<name of the object>.<method to do>
We send a message to the object telling it to do the method. We might also supply parameters (as in
this case) to specify what we want.
The next statement has the same pattern:
myWindow.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
This is about what happens when the top right 'close' button on the window is clicked. Unless we tell
it otherwise, this closes the window, but does not exit the application. This is because an application
might have several windows which open and close as the user uses it. For most of these, they would
not want to close the application when they closed the window. This would only be true for the 'top-
level' main window. This statement changes that, so that when the window is closed, the
application stops.
While it follows the
object.method
pattern, the argument is slightly different. JFrame.EXIT_ON_CLOSE is a constant - it is a name for a
number. We know it is a constant because it is in capital letters. The value of it is 3. The
setDefaultCloseOperation method expects to be given a number, which is used as a code for what
should happen when the window closes. A 3 means to end the application.
So why not say
myWindow.setDefaultCloseOperation(3);
which is a lot shorter? Three reasons
1. This version does not say what it means. Anyone reading the program - probably a programmer
tasked with maintaining it - would have to work out - why 3? This would be an example of a magic
number, to be avoided.
2. When writing it, you would have to remember that 3 is the value for exiting on close - and all the
other constant values for thousands of classes.
3. If the coding alters, and it is no longer 3, this version would no longer work. But because the value
of the name EXIT_ON_CLOSE would also change, a version using the symbol would still work.
The form JFrame.EXIT_ON_CLOSE shows that we are referring to the value EXIT_ON_CLOSE which is a
member of the JFrame class. If other classes also use EXIT_ON_CLOSE there will not be a clash.
The final statement
Java
Page 82 - Copyright 2012 Walter Milner - all rights reserved
myWindow.setVisible(true);
is simple. When a new JFrame object is constructed, it is not displayed. Only when we send it the
setVisible message, with an argument of true, does it become visible.
In a Swing GUI, there is a choice - create and close new windows as they are needed, or create them
as invisible windows and switch on and off their visibility as required.
Exercise
Run this program.
Alter it so that the size and position of the window changes.
Change the window title.
Make it so that two JFrame objects appear.
Java
Page 83 - Copyright 2012 Walter Milner - all rights reserved
The Java API
How does the programmer know all this stuff? How do we know what classes there are and what
they can do? By referring to the API - the application program interface. This is the documentation of
the standard Java classes. It is online, currently at
http://download.oracle.com/javase/7/docs/api/
It is a good idea to find it and bookmark it. It is very consistent, because the documentation is
generated automatically by a tool called javadoc.
The API looks like this:
The top left frame shows a choice of packages - groups of classes. The bottom left shows a list of
classes. The main panel on the right shows information on the selected class, including its
constructors, methods and other information. It may provide some notes on how to use the class,
but you often need to look elsewhere for this. The API is primarily for reference. It contains several
concepts which we have not yet covered.
Do not be put off by the very large number of classes. This is good news, not bad, in that it
represents a lot of programming already done and which you can re-use.
Java
Page 84 - Copyright 2012 Walter Milner - all rights reserved
Subclassing
As well as just using existing classes out of the box, we can also make our own classes by modifying
existing ones. Here is a different approach to our windows program:
import javax.swing.JFrame;

public class Main extends JFrame {

public Main() {
super("Hello world!");
setBounds(50, 50, 300, 200);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
}

public static void main(String[] args) {
Main main = new Main();
}
}
Try this program out.
There are three differences here.
1. Our Main class now extends JFrame
2. We have written a constructor for our class
3. The main method now instantiates our Main class
We will examine each of these in more detail:
Extending a class
The line
public class Main extends JFrame {
means that the class called Main IS the class called JFrame, but with features changed or added on.
In other words, everything in the JFrame class is in the Main class. Consequently, everything a
JFrame can do, our class can do as well. But we can add extra parts. We will add a constructor and a
method called main.
Main is now a subclass of JFrame. Jframe is a base class or superclass of Main.
Writing a constructor
The line
public Main() {
starts the constructor. Remember that a constructor does what is needed to create an object, an
instance of the class.
How do we know it is the constructor? Because its name matches the name of the class. Take note -
a constructor is not a method, and does not have a return type, not even void.
The statements in the constructor are not very different from what we had before:
super("Hello world!");

Java
Page 85 - Copyright 2012 Walter Milner - all rights reserved
This invokes the constructor of the superclass, which is JFrame. In other words it makes a basic
JFrame with the given title.
The next line
setBounds(50, 50, 300, 200);
is very similar to what we had before:
myWindow.setBounds(50, 50, 300, 200);
except that we are no longer referring to the object myWindow. So which object are we referring
to? The answer is this object being constructed.
Similarly for the rest:
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
set up the properties of the object we are constructing.
Instantiating the class
Remember the main method is where execution starts. This now says:
Main myWindow = new Main();
This declares a variable called myWindow, which will be an object of class Main. The part:
.. = new Main();
invokes the constructor of Main, which we have just written, and will actually make such an object.
Definitions do not execute sequentially
Here is our definition of the Main class:
import javax.swing.JFrame;

public class Main extends JFrame {

public Main() {
.. the constructor..
}

public static void main(String[] args) {
.. start execution here ..
}
}
Suppose we had written the parts in a different sequence, like:
Java
Page 86 - Copyright 2012 Walter Milner - all rights reserved
import javax.swing.JFrame;

public class Main extends JFrame {

public static void main(String[] args) {
.. start execution here ..
}

public Main() {
.. the constructor..
}

}
Does this make any difference? No. Why not? Because the class definition is just a definition, not a
program to be executed sequentially. When execution needs to start, the system looks for main(). If
it needs to instantiate the class, it looks for the constructor. The order of these definitions makes no
difference.

Exercise
Suppose we had two lines in main:
Main myWindow1 = new Main();
Main myWindow2 = new Main();
What would happen?
Try it.
Explain it (try moving the window).
Java
Page 87 - Copyright 2012 Walter Milner - all rights reserved
Variables and values
Primitive and Reference Types
Primitive types are for example ints and doubles and chars. These are not objects. They have single
values.
Reference types are objects.
So for example
int x = 3; // x is a primitive type
String text = new String("Click me"); // text is a reference type
In fact there are significant differences in the way these are stored. If we have three int variables x y
and z, with values 1 2 and 3, we might think of them as being held in memory like this:

It is more effective to think of this as a symbol table:

But if we have say
String a = new String("One");
String b = new String("Two");
we can think of memory like this:
Here object 'a' is held in memory starting at address 21. Object 'b' starts at address 25. In the symbol
table, next to 'a' it says 21, the start address of the object. Next to 'b' it says 25, the start address of
the object. In the symbol table therefore we have pointers to where the object is in memory. A
pointer to something is the address of it. This is what a reference is.

Java
Page 88 - Copyright 2012 Walter Milner - all rights reserved
In a Java program we do not know, and cannot find out, the actual numeric address of these things.
But we do not need to know. It is more useful to think of this situation like this:

Here we have pointers as arrows. In reality they are numeric addresses, but they can be thought of
as actual pointers to different memory locations.
References and taking out the garbage
Suppose we have this code:
String a = new String("One");
String b = new String("Two");
b = a;
What happens? After the first two statements the situation is as in the previous diagram. After the
third statement, we have

b=a means that b now points to the same object as 'a' points to. Both a and b reference the same
object.
It does NOT mean this:

it does not make b point to a - it makes b point to what a points to.
But what now of object b? Nothing refers to it. This means that our Java program can no longer use
that object, since we have effectively lost track of where it is.
It has become garbage - data in memory which is no longer needed. What will happen is that the
garbage collector , part of the runtime software, will return this memory block to free memory, from
where it can be re-used.
Java
Page 89 - Copyright 2012 Walter Milner - all rights reserved
More precisely, the garbage collector might do that. It takes time to do a garbage collection, and if
there is plenty of free memory already, it is a waste of time. So the garbage collector has an
algorithm which means it will only do it if it is worthwhile.
null
The special value null is a 'pointer to nowhere'. We will see some uses for it later.
A common problem relates to null. This code:
String s="cat";
System.out.println(s);
executes as expected. But
String s="cat";
s=null;
System.out.println(s);
results in a run-time exception:
Exception in thread "main" java.lang.NullPointerException
at Main.main(Main.java:12)
Line 12 is the println statement. This error usually arises when we try to invoke a method on an
object reference which is null - so in effect the object does not exist. Typically the program is trying
to access uninitialised data. Sometimes the compiler can detect this - but not always.
The println method invokes the toString() method of its argument. toString is a method which all
objects have, which converts the object to an equivalent string. So this println statement is in effect
System.out.println(s.toString());
so we are invoking a method on s.
The line s=null; means that s points to nowhere - it does not point to an object, so we cannot invoke
a method call on it. If we do, we get a NullPointerException.
Swapping reference type variables
We saw that to exchange the values of primitive types, we needed to use a third temporary
location, like:
int x=1;
int y=2;
int temp;
temp=x;
x=y;
y=temp;
Will the same pattern work for reference types? Strings are objects - how about
Java
Page 90 - Copyright 2012 Walter Milner - all rights reserved
String s1 =new String("One");
String s2 = new String("Two");
String temp;
temp=s1;
s1=s2;
s2=temp;
After the first three statements, we have:


After temp=s1; this changes to


After s1=s2;

and after s2=temp;



so this has done what we wanted.
Exercise
For Strings, a statement like:
s2=s2+"ne";
constructs a new string object, containing the text in s2 joined at the front to 'ne'. It then makes s2
refer to this new object.
What do you think the following code will do?
Java
Page 91 - Copyright 2012 Walter Milner - all rights reserved
String s1="One";
String s2="O";
s2=s2+"ne";
System.out.println(s1);
System.out.println(s2);
if (s1==s2)
System.out.println("Equal");
Try it.
Explain what happens.
Look at the String API and look at the equals() method.

Parameter passing
Suppose we have a method which finds the average of two values:
double average(double x, double y)
{
double result;
result=(x+y)/2.0;
return result;
}
and we invoke this method by:
double a; double b;
a=2.0;
b=3.0;
double c = average(a,b);
How exactly does this work?
The items x and y, or a and b, are called
parameters or arguments. The x and y in the
definition of the method are sometimes
called formal parameters, while the ones
used in the invocation of the method (in
this example, a and b) are actual
parameters. Actual parameters can be
constants, variables or expressions.
The way this works varies between
different languages. In Java, the values of
actual parameters are copied, and these are passed to the formal parameters. This is sometimes
called "pass by value".
Which parameter is copied to which depends on the order - that is, the first (a) is copied to the first
(x), the second (b) to the second (y) and so on. The process involves a stack - the actual parameter
copies are pushed onto a stack, then in the start of the method the values are popped back off the
stack and assigned to the formal parameters.
Suppose a method changes a parameter value? For example,
Java
Page 92 - Copyright 2012 Walter Milner - all rights reserved
double average(double x, double y)
{
double result;
result=(x+y)/2.0;
x+=1.0;
return result;
}
Does changing x affect a?
The answer is no, because x is a copy of a. Changing the copy will not affect the original.
Reference types as parameters
Does it make any difference if the parameter is a reference type - an object? In one sense no, since
the parameter is still copied. But for a reference type, this is a pointer to the object. The pointer is
copied, not the object.
For example, suppose we want a method to find which day of the week it is:
int getDay(GregorianCalendar formalDate)
{
int result = formalDate.get(GregorianCalendar.DAY_OF_WEEK);
return result;
}
This uses the class GregorianCalendar, which does what we want. We could use this by:
GregorianCalendar date=new GregorianCalendar();
System.out.println("Day (sunday =1) "+getDay(date));
But suppose the method changes the formal parameter:
int getDay(GregorianCalendar formalDate)
{
int result = formalDate.get(GregorianCalendar.DAY_OF_WEEK);
// make it Sunday
formalDate.set(GregorianCalendar.DAY_OF_WEEK, 1);
return result;
}
and see what happens:
GregorianCalendar date=new GregorianCalendar();
System.out.println("Day (sunday =1) "+getDay(date));
System.out.println(date.getDisplayName(GregorianCalendar.DAY_OF_WEEK, GregorianCalendar.LONG,
Locale.ENGLISH));
The output of this (run on a Thursday) is:
Day (sunday =1) 5
Sunday
So it correctly tells us it is Thursday - but then changing the formal parameter has made it Sunday.
How come a reference type can be changed?
The rule is the same - parameters are copied then the copy is passed into the method. But a
reference type parameter is a pointer to an object. Changing the pointer, such as by
Java
Page 93 - Copyright 2012 Walter Milner - all rights reserved
formalDate=null;
would not affect the actual parameter, since it changes a copy. But if the method alters the object
being pointed at, that change will be seen in the invoking code.
Another way of looking at this is to count the objects. In the code above, the keyword new is only
used once. There is only one GregorianCalendar object. A pointer to it is copied and passed into the
method - and the method uses the pointer to change the object pointed to.
Arrays are objects, so this is applicable for arrays as parameters.
Exercise
What do you think this code would do?
static void swap(int[] one, int[] two) {
int temp;
for (int i = 0; i < one.length; i++) {
temp = one[i];
one[i] = two[i];
two[i] = temp;
}
}

public static void main(String[] args) {
int[] a = {1, 2, 3};
int[] b = {4, 5, 6};
swap(a, b);
for (int i = 0; i < a.length; i++) {
System.out.println(a[i]);
}
for (int i = 0; i < b.length; i++) {
System.out.println(b[i]);
}
}
Write a method called zero, which takes an array of ints as parameters, and makes every element
zero. Test it.

Java
Page 94 - Copyright 2012 Walter Milner - all rights reserved
Wrapper Classes
The primitive types, int double char and so on, are simple values. They are not objects and they have
no methods.
Sometimes it is convenient to have an object which is 'like' a primitive. For example, we might have a
class called Integer which is like an int, but is a class with constructors are methods. Such a class is
called a wrapper class, because it wraps a primitive, as a data member.
Most of the useful methods are static:
Integer i = new Integer(3);
System.out.println(i);
System.out.println(i.intValue()); // back to where we started
// some static methods
System.out.println("Biggest int is "+Integer.MAX_VALUE); // 2147483647
System.out.println("Smallest int is "+Integer.MIN_VALUE); //-2147483648
System.out.println("386 in binary is "+Integer.toBinaryString(386)); //110000010
Remember that ints are primitives, and Integers are not - they are objects. Be careful about:
Integer i = 3;
System.out.println(i);
This is an unfortunate feature called autoboxing. It is the same as
Integer i = new Integer(3);
The first version is less typing, but deceptive, because it really looks like i is an int, when it is not.
Similarly
Integer i = new Integer(3);
int i2 = i+1;
This is called unboxing - it is the same as
Integer i = new Integer(3);
int i2 = i.intValue()+1;
This is more typing, but you are clear that i is not an int.
There are corresponding wrapper classes for the other primitives - Byte, Short, Long, Float, Double,
Character and Boolean.
These are the standard wrapper classes. The idea can be used more generally, writing your own
classes which wrap objects. This idea is related to inheritance by composition.
Java
Page 95 - Copyright 2012 Walter Milner - all rights reserved
Overloading
Overloading means having the same name or symbol have several different meanings.
In Java, some operators (like + and / ) are overloaded. Unlike C++, we cannot programmatically
overload operators.
In Java, constructors and methods are very often overloaded.
Operator overloading
We can use + on Strings:
String hello = "Good" + "day";
and it concatenates them.
And we can use + on ints:
int x = 2 + 2;
and it carries out arithmetic addition. So + is overloaded.
More subtly, / is overloaded:
int x = 11/5; // integer division : x is 2
double y = 11.0/5.0; // double division : y is 2.2
What decides which / is used is decided by the operand type, not the left hand side type. So
double y = 11/5; // y = 2.0
What happens here is that first the compiler parses 11/5 and sees / applied to two ints, so it
generates code which will do int division which would give the result 2. Then a typecast is generated
to change int 2 to double 2.0.
But we cannot write Java code to make + (or any other operator) perform differently.
For example you might define a class Vector to model vectors in 3d space. It would be nice if you
could overload + so you could say
Vector a = ..
Vector b = ..
Vector c = a + b;
as you can in maths. You can do this in C++, but not in Java. Instead you must define an add()
method, and say
Vector c = a.add(b);
This works just as well but does not look as neat. It makes the compiler a lot simpler, but it loses
some 'syntactic sugar'.
Java
Page 96 - Copyright 2012 Walter Milner - all rights reserved
Constructor overloading
Classes often have several constructors. The different versions must differ in the number or type of
arguments. For example the Integer wrapper class has two constructors, one taking an int and the
other a String:
Integer int1 = new Integer(3);
Integer int2 = new Integer("1000");
The JFrame class, the Swing model of a GUI window, has 4 constructors. The API shows them as:
So we can say

JFrame win1 = new JFrame(); // window with no title
Jframe win2 = new JFrame("My window"); // window with title;

Method overloading
This is the same idea - several versions of a method, all with the same name but with differing
numbers or types of parameters. For example, the String class has several method called 'indexOf':
For example:
String str = "barbara";
int pos;
pos=str.indexOf('a'); // 1
pos=str.indexOf('a', 2); // 4
pos=str.indexOf("bar"); // 0
pos=str.indexOf("bar", 2); // 3
Exercise
How would you expain to someone what overloading means in Java?
Java
Page 97 - Copyright 2012 Walter Milner - all rights reserved

Java
Page 98 - Copyright 2012 Walter Milner - all rights reserved
Inheritance
We have seen that we can extend a class to create a new, modified class. This is called subclassing.
The original class is called the base class.
Suppose we say
class C extends B ...

This defines a new class C, as a modification or sub-class of class B. This means C objects will have
1. All the data fields of B (they are inherited )
2. Possibly extra data fields
3. All the methods of B (inherited)
4. The inherited methods can be modified so they work differently. The modified methods override
the inherited ones.
5. C objects might have extra methods.
This means a sub-class has everything the base class has, plus extra, and the inherited methods may
be over-ridden to work differently.
Constructors are not inherited.
What is the point of inheritance?
Inheritance allows us to re-use existing code in order to achieve something similar but slightly
different. We can avoid having to start again from scratch.
Example of sub-classing
Suppose we want a GUI application, where all the windows should have a yellow background.
We could start by coding a window class. But there is already a class for a window, named JFrame.
We can re-use that code, and extend JFrame so that we fix its background colour to be yellow:


public class YellowWindow extends JFrame {

YellowWindow(String title) {
super(title); // invoke JFrame constructor
getContentPane().setBackground(Color.yellow);
setVisible(true);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}

public static void main(String args[]) {
YellowWindow one = new YellowWindow("One");
one.setBounds(10, 10, 200, 200);
YellowWindow two = new YellowWindow("Two");
two.setBounds(300, 10, 200, 200);
}
}

Java
Page 99 - Copyright 2012 Walter Milner - all rights reserved

Class hierarchies

A subclass can be the base class for another sub-class. In other words
we can say
class B extends A..
..
class C extends B..
This means we have a class hierarchy:



Exercise
Subclass YellowWindow so you have a JFrame with a yellow background and a fixed initial size of 100
by 100 pixels

Java
Page 100 - Copyright 2012 Walter Milner - all rights reserved
The Object class
We have seen that we can subclass a base class to create a modified new class.
In fact there is a special class named Object, which is the ultimate base class of all other classes.
If we have:

class A...
..
class B extends A..
..
class C extends B..
..

then in fact class A extends class Object, automatically without saying so, and the hierarchy is







Object has just a few methods, which are inherited by all other classes. For example:
Object one = new Object();
System.out.println(one.toString());
// toString() produces a String somehow representing the object
// This produces 'java.lang.Object@55c4d594' - not very useful
System.out.println(one.getClass());
// getClass() returns an object of type Class. System.out.println calls toString() on
// this, outputting 'class java.lang.Object'
Object two = new Object();
System.out.println(one.equals(two));
// .equals is true if 2 objects are 'equal' - see below
// here we get 'false'
So all classes inherit a toString() method, which is supposed to generate a String which can identify
or give useful info on an object.
When an object reference is passed to System.out.println(), the toString() method of the object is
called, and the resulting String outputted. So in fact the following are equivalent:
System.out.println(one.toString());
System.out.println(one);

Java
Page 101 - Copyright 2012 Walter Milner - all rights reserved
The equals() method returns true if the calling object is 'equal to' the parameter object. Object's
version of this only gives true if they are the same object - for example
Object one = new Object()
Object two = one;
System.out.println(one.equals(two));
outputs true since 'one' and 'two' both refer to the same object.
Over-riding toString and equals
Normally we have to over-ride toString and equals to give useful versions. For example:
class MyClass extends Object
{
int x;
MyClass(int y)
{
x=y;
}

public String toString()
{
return super.toString()+" x = "+x;
}

public boolean equals(MyClass other)
{
return x==other.x;
}
}
This says MyClass extends Object - this is not needed. All classes ultimately extend Object.
In the definition of toString, we say super.toString(). This calls the toString of the superclass Object.
We then use + to concatenate this with 'x = whatever', so
MyClass one = new MyClass(1);
System.out.println(one);
outputs ' test.MyClass@3479404a x = 1'
In equals, we just compare the value of x with the value of the x field of the other object. We say
'x==other.x'. This will be a boolean value, true or false, and we just return that value. So
MyClass one = new MyClass(1);
MyClass two = new MyClass(1);
MyClass three = new MyClass(2);
System.out.println(one.equals(two)); // gives true
System.out.println(one.equals(three)); // gives false
How you write .equals() depends on the nature of the object. Some fields will be 'key' identifying
values, while others may be not relevant to identifying the object.
Exercise
What is the difference between an object and Object?
Java
Page 102 - Copyright 2012 Walter Milner - all rights reserved
Overloading and overriding
Overloading means having two or more methods defined in a class with the same name. Their
numbers or types of parameters must differ. Similarly we can have overloaded constructors.
Overriding is when we have a method in a base class, and a definition of a method with the same
name in a subclass. The subclass method overrides the base class method.
An example
class Test {

public static void main(String args[]) {
Base b = new Base();
b.method1();
Sub sub = new Sub();
sub.method1();
sub.method2(1);
sub.method2('x');

}
}

class Base
{
void method1()
{
System.out.println("In method1 in Base");
}

void method2(int x)
{
System.out.println("Overloaded Base method2 with an int");
}
void method2(char x)
{
System.out.println("Overloaded Base method2 with a char");
}
}

class Sub extends Base
{
void method1()
{
System.out.println("Overriding method1 in Sub");
}


}
The output is:
In method1 in Base
Overriding method1 in Sub
Overloaded Base method2 with an int
Overloaded Base method2 with a char

Remember that constructors are not inherited.
Java
Page 103 - Copyright 2012 Walter Milner - all rights reserved
super
'super' is a Java keyword which can be used in several contexts. In general it refers from a subclass to
the base class.
super in method calls
A method in a base class can be invoked from a subclass by using the syntax super.methodName().
For example

class Test {

public static void main(String args[]) {
Sub sub = new Sub();
sub.method1();

}
}

class Base
{
void method1()
{
System.out.println("In method1 in Base");
}
}

class Sub extends Base
{
void method1()
{
super.method1();
System.out.println("Overriding method1 in Sub");
}
}
which outputs
In method1 in Base
Overriding method1 in Sub
You might do this if a subclass method needs to execute the code in the base class, plus extra code.

super and data fields

super can be used to refer to data members in a base class from a subclass, if the subclass
introduces a new field with the same name. The following example is followed by a health warning:
Java
Page 104 - Copyright 2012 Walter Milner - all rights reserved
class Test {

public static void main(String args[]) {
Sub sub = new Sub();
sub.method();

}
}

class Base {

int x = 3;
}

class Sub extends Base {

int x = 4;

void method() {
System.out.println(super.x);
System.out.println(x);
}
}


This outputs 3 then 4.
Note carefully - this code fragment is unusual and not normally good practice. A subclass inherits the
data members of the base class, so in this case Sub already has a data member called x. When Sub
declares it again, the 'x' hides the base class 'x'. A reference to x in the subclass is not to the x in the
base class - we have to say super.x to get to it.Now x was probably declared in the base class for
some reason or purpose, and its now hidden in the subclass, so the sublass may not work properly.
You might well do this accidentally, declaring x in the subclass because you forgot it was a field
already in the base class. For this reason most IDEs will warn you if you do this.
super in constructors

Remember that constructors are not inherited.
In a subclass, you can invoke the constructor of the base class by saying super(). This must be the
first line in the constructor. For example:
Java
Page 105 - Copyright 2012 Walter Milner - all rights reserved
class Test {

public static void main(String args[]) {
Sub sub = new Sub();
System.out.println(sub.x+ " "+ sub.y);
}
}

class Base {

int x;
Base()
{
x=3;
}
}

class Sub extends Base {

int y;
Sub()
{
super();
y=4;
}
}
This outputs 3 4.
This is a typical example (but see later) - the subclass constructor first invokes the base class
constructor, then does further work.
Constructors with arguments
If the base class has a constructor which takes arguments, we can invoke it with super and an
argument value:
class Test {

public static void main(String args[]) {
Sub sub = new Sub();
System.out.println(sub.x + " " + sub.y);
}
}

class Base {

int x;

Base(int val) {
x = val;
}
}

class Sub extends Base {

int y;

Sub() {
super(3);
y = 4;
}
}
which outputs 3 4 as expected.
The no-arg constructor
If you do not write super() as the first line of the subclass constructor, the compiler generates one
for you. For example:
Java
Page 106 - Copyright 2012 Walter Milner - all rights reserved
class Test {

public static void main(String args[]) {
Sub sub = new Sub();
System.out.println(sub.x + " " + sub.y);
}
}

class Base {
int x;
Base() {
x = 3;
}
}

class Sub extends Base {
int y;
Sub() {
y = 4;
}
}
which again outputs 3 4. Note Sub() does not call super(), but x became 3 anyway. The compiler
inserts the super call.
But what if the base class does not have a no-args constructor?
class Test {

public static void main(String args[]) {
Sub sub = new Sub();
System.out.println(sub.x + " " + sub.y);
}
}

class Base {
int x;
Base(int val) {
x = 3;
}
}

class Sub extends Base {
int y;
Sub() {
y = 4;
}
}
This is a compile-time error. The compiler would call Base(), but there is no no-arg constuctor in
Base.
You would fix this either by writing one, or by an explicit use of super with arguments:
Java
Page 107 - Copyright 2012 Walter Milner - all rights reserved
class Test {
public static void main(String args[]) {
Sub sub = new Sub();
System.out.println(sub.x + " " + sub.y);
}
}

class Base {
int x;
Base(int val) {
x = val;
}
}

class Sub extends Base {
int y;
Sub() {
super(3);
y = 4;
}
}
Exercise
Add comments to the last example saying what is happening.
Java
Page 108 - Copyright 2012 Walter Milner - all rights reserved
this
In Java 'this' is a keyword. Inside a method, it is a reference to the object executing the method.
Inside a constructor, it is a reference to the object being constructed.
Example - this.x = x
Suppose we are defining a class Circle, which might have data members for radius and colour:
class Circle
{
double radius;
Color color;
..

}
We would need to pass values for the radius and colour in the constructor:
Circle(double... , Color ...)
{
radius =..
color=..
}
What to name the arguments? The sensible names are color and radius, but then how to tell the
difference between the arguments and the data members if they have the same name? The usual
solution is to use 'this':
Circle(double radius, Color color)
{
this.radius = radius;
this.color = color;
}
Now this.radius is the object data member, while radius is the argument.
Example in Swing
We will expand this example later, but this is a start. When using Swing to program a GUI, we might
subclass a JFrame to make a window:
class MyFrame extends JFrame
{
MyFrame() // the constructor
{
..
}
}
Suppose we want a button on our window. This is what a JButton is. We have to make one, then
'add' it to the window:
class MyFrame extends JFrame
{
MyFrame() // the constructor
{
JButton myButton = new JButton("Click here");
add(myButton);
}
}

Java
Page 109 - Copyright 2012 Walter Milner - all rights reserved
But to make the button work, we have to say what object will 'listen' for button clicks. This is done
by the addActionListener method. This could be the window itself. But how to refer to the window
being constructed? Use 'this':
class MyFrame extends JFrame
{
MyFrame() // the constructor
{
JButton myButton = new JButton("Click here");
add(myButton);
myButton.addActionListener(this);
}
}
We will expand this to fully working code later.
Exercise
If you use 'this' in a method - what does it mean?
Java
Page 110 - Copyright 2012 Walter Milner - all rights reserved
static
Data members and methods can be declared to be 'static'. That means they are per class not per
object.
Despite its name, static does not mean constant. To make a data member constant, use the keyword
'final'.
Example
Suppose we were defining some different types of animals:
class Test {
public static void main(String args[]) {
Mammal dog = new Mammal("Rover",4,0.8);
Insect bee = new Insect("Buzzy", 6, 0.01);
}
}

class Animal
{
double height, weight;
Color color;
String name;
}

class Mammal extends Animal
{
int numberOfLegs;
Mammal(String name, int numberOfLegs, double height)
{
this.name=name;
this.numberOfLegs=numberOfLegs;
this.height=height;
}

}

class Insect extends Animal
{
int numberOfLegs;
Insect(String name, int numberOfLegs, double height)
{
this.name=name;
this.numberOfLegs=numberOfLegs;
this.height=height;
}
}

But - all Mammals have four legs, and all Insects have six legs. The number of legs is not a
characteristic of the individual mammal - the object. It is a characteristic of the class. We can capture
that idea by making numberOfLegs to be static - per class not per object:
Java
Page 111 - Copyright 2012 Walter Milner - all rights reserved
class Test {
public static void main(String args[]) {
Mammal dog = new Mammal("Rover",0.8);
Insect bee = new Insect("Buzzy", 0.01);
}
}

class Animal
{
double height, weight;
Color color;
String name;
}

class Mammal extends Animal
{
static int numberOfLegs;
Mammal(String name, double height)
{
this.name=name;
numberOfLegs=4;
this.height=height;
}

}

class Insect extends Animal
{
static int numberOfLegs;
Insect(String name, double height)
{
this.name=name;
numberOfLegs=6;
this.height=height;
}
}

Methods as well as data members can be static. The idea is the same - per class not per object.
Example - the Math class
We often need to use maths functions like sine and cosine, and constants like . These are bundled
together in the Math class. This has a set of static methods, which are used like:
double val = Math.sin(0.6);
The method is invoked with the syntax <class>.<method>(), instead of <object>.<method>() used for
non-static methods.
If the methods had not been static, we would have to have said
Math math = new Math();
double val = math.sin(0.6);
In fact you cannot say this, because the Math constructor is private. All classes have a constructor -
even if just the compiler-generated no-args one. A common way of preventing a class being
instantiated is to make the constructor private.
Example - the Singleton design pattern
Design patterns are patterns of class use. A very common one is the singleton pattern, which is
where you want to be sure you have one, and only one, instance of a class. For example you might
have a class for the main window of a GUI application. You want to have precisely one main window.
So the singleton pattern is appropriate.
Java
Page 112 - Copyright 2012 Walter Milner - all rights reserved
How to do it? The usual method is to have the constructor private, so it cannot be called from
outside the class. You have a static method called getInstance. This checks whether there is already
an instance, and if so, it returns a reference to it. Otherwise it creates one instance:
class Test {

public static void main(String args[]) {
MySingleton one = MySingleton.getInstance();
MySingleton two = MySingleton.getInstance();
if (one == two) {
System.out.println("Only got one");
}
}
}

class MySingleton {

static MySingleton instance = null;

private MySingleton() {
}

static MySingleton getInstance() {
if (instance == null) {
instance = new MySingleton();
}
return instance;
}
}
Example - autonumber
We often want to have a set of objects each having a unique key field to identify it. For example a
bank account needs a unique account number. This is achieved in databases by having an
'autonumber' field which automatically increases every time a new record is added. We can achieve
the same thing in Java if the class maintains a static field which 'remembers' how many objects have
been created:
Java
Page 113 - Copyright 2012 Walter Milner - all rights reserved
class Test {

public static void main(String args[]) {
BankAccount b1 = new BankAccount("Tom");
BankAccount b2 = new BankAccount("Dick");
BankAccount b3 = new BankAccount("Harry");
BankAccount b4 = new BankAccount("Tom");
b1.display();
b2.display();
b3.display();
b4.display();

}
}

class BankAccount {

static int counter=0;
int accountNumber;
String owner;

BankAccount(String owner)
{
this.owner=owner;
accountNumber=counter;
counter++;
}

void display()
{
System.out.println("Owner: "+owner+ " Account number: "+accountNumber);
}
}
which outputs:
Owner: Tom Account number: 0
Owner: Dick Account number: 1
Owner: Harry Account number: 2
Owner: Tom Account number: 3
Example - main

main is static. It has to be. The key point about main is that execution starts there. If it had been
non-static, the class would have first to have been instantiated, and then main invoked on that
object. But calling main by definition is the first thing that happens.
cannot be referenced from a static context
Beginners often get this
compile-time error:
They will often get rid of
the error message by
making the method to be
static. But then no objects
are instantiated and there
is no OO programming.

'Static context' means the
code is in a static method,
so there is no object, so a
non-static method cannot be invoked.
Java
Page 114 - Copyright 2012 Walter Milner - all rights reserved
The solution is to construct an object, then invoke the method on it:
class Test {

void someMethod() {
System.out.println("hello");
}

public static void main(String args[]) {

Test test = new Test();
test.someMethod();
}
}

Exercise
Describe three situations where the use of 'static' is appropriate.

Java
Page 115 - Copyright 2012 Walter Milner - all rights reserved
Date and Time in Java
This section illustrates more uses of OOP, in the context of dates and time.
Timing
Timing a process is simple. The System class has a static method called currentTimeMillis(), which
returns the current system time in milliseconds. This can be used by storing the current time in a
variable, running the process, finding the new time, and finding the difference.
For example, this outputs in seconds how long it takes to count to one billion:
long start = System.currentTimeMillis();
for (long i=0; i<1000000000; i++);
long end=System.currentTimeMillis();
System.out.println((end-start)/1000.0);
The for loop has no body - we just count. The return type of currentTimeMillis is a long, since an int
does not have sufficient range.
If you run this several times, you get different answers. This is because the computer multitasks, and
is doing other activity as well as running this program.
Exercise
Use this method to time how long it takes to bubble sort an array of random integers. Do this for
various array sizes from 1000 to 1000000. Does this agree with the theory?
The Date class
The fundamental way that Java treats points in time is as a long integer, being the number of
milliseconds since January 1, 1970, 00:00:00 GMT. The number can be negative, so we can represent
times before 1970. A Date object, an instance of the Date class, represents a point in time. Inside a
Date object there is a long integer, which fixes the time. We say Date wraps a long integer.
Here is a simple start:
Date now = new Date();
System.out.println(now);
which will output something like:
Mon Oct 17 16:45:00 BST 2011
There are two Date classes. The one in java.sql is about dates in databases. This Date is in java.util.
The no-args constructor Date(); returns a Date object set to the current time and date. The println
invokes the toString() method of Date, which by default will format it as shown.
Deprecated methods
When the Date class was first designed (in JDK 1.0) the idea was that as well as representing a
moment in time, it would also handle notions like what month it is, what year, the day of the week
and so on. But it was then realized that these were about a calendar, not a moment in time, and that
there were many possible structures for a calendar, used in different parts of the world. So the
Calendar class was set up, in JDK1.1.
Java
Page 116 - Copyright 2012 Walter Milner - all rights reserved
So many of the methods in Date were better handled by Calendar. Those methods in Date were said
to be deprecated. That means they are still available - otherwise old Java code might stop working.
But it signals that there is a better way of doing it, and that in future deprecated methods may
disappear. You should not write Java using a deprecated method.
As an example, Date has another constructor which takes a year (after 1900), month (January=0) and
day as arguments:
Date inThePast = new Date(10,2,4);
System.out.println(inThePast);
which outputs
Fri Mar 04 00:00:00 GMT 1910
but this constructor is deprecated.
The imporant thing about Date is that it wraps a long integer which marks a moment in time. We will
see how this is useful later.
Exercise
Date has a method getTime() which returns the underlying time point. Use this to find out how many
milliseconds after midnight on 1 January 1970 you were born (use the deprecated constructor).

Date Formats
If you just output a Date, you get the default formatting as shown above. If you want to specify the
format yourself, you can use an instance of SimpleDateFormat, which is a subclass of the
DateFormat class.
The format is specified by a format string - see the API for all the details. For example:
Date now = new Date();
String s = "'sometime in' MMMM 'in the year' yyyy");
SimpleDateFormat vagueFormat = new SimpleDateFormat(s);
System.out.println(vagueFormat.format(now));
s=("yyyy.MM.dd G 'at' HH:mm:ss z";
SimpleDateFormat exactFormat = new SimpleDateFormat(s);
System.out.println(exactFormat.format(now));
which outputs:
sometime in October in the year 2011
2011.10.18 AD at 11:41:11 BST
SimpleDateFormat also deals with different time zones. This needs a little thought. It is the same
moment in time no matter where you are. But it is expressed in different ways in different time
zones. Date represents the number of milliseconds since Jan.1,1970 which is the same wherever you
are (in UTC). But you can set a SimpleDateFormat to different time zones and see that moment in
different places:
Java
Page 117 - Copyright 2012 Walter Milner - all rights reserved
Date now = new Date();
String s = "yyyy.MM.dd G 'at' HH:mm:ss z";
SimpleDateFormat exactFormat = new SimpleDateFormat(s);
System.out.println("In London, " + exactFormat.format(now));

TimeZone est = TimeZone.getTimeZone("EST");
exactFormat.setTimeZone(est);
System.out.println("In New York, " + exactFormat.format(now));
TimeZone japan = TimeZone.getTimeZone("Japan");
exactFormat.setTimeZone(japan);
System.out.println("In Tokyo, " + exactFormat.format(now));
which outputs:
In London, 2011.10.18 AD at 11:57:53 BST
In New York, 2011.10.18 AD at 05:57:53 EST
In Tokyo, 2011.10.18 AD at 19:57:53 JST

Exercise
Output what time it is in Honolulu (unless you are in Honolulu, in which case, what time it is in
London).
The GregorianCalendar class
The whole problem with Date is that there are several different calendars in use across the world.
That situation is modelled in OOP by having a class hierarchy, with a base class that establishes the
common features which all calendars would have, and sub-classes which model actual calendars.
This is how it works. Calendar is the base class, and offers common features but it is abstract, so you
cannot instantiate it. The standard subclass is GregorianCalendar, which models the most common
calendar in use across the world today. The no-args constructor creates an object modelling the
current time in the current locale. getTime() retrieves the underlying moment, as a Date:
GregorianCalendar gc = new GregorianCalendar();
System.out.println(gc.getTime());
A GregorianCalendar object again represents a moment in time, but unlike Date (which in effect it
wraps) it also has fields for day, month, year and so on. When these are changed, it recalculates the
underlying time instant (when it needs to).
There are three kinds of methods on these fields - set, add and roll. Set is simplest - it sets the given
field to the given value:
GregorianCalendar gc = new GregorianCalendar();
System.out.println(gc.getTime());
gc.set(Calendar.MONTH, 0);
System.out.println(gc.getTime());
gc.set(Calendar.MONTH, 13);
System.out.println(gc.getTime());
Tue Oct 18 15:15:16 BST 2011
Tue Jan 18 15:15:16 GMT 2011
Sat Feb 18 15:15:16 GMT 2012
As the above shows, in 'lenient mode', if you try to set an invalid date, it fixes it, so month 13 is
month 2 in the following year.
The add functions add the given amount to the given field. If for example you are adding days, and
you go beyond the end of the month, it goes into the next month:
Java
Page 118 - Copyright 2012 Walter Milner - all rights reserved
GregorianCalendar gc = new GregorianCalendar();
// Tue Oct 18 15:20:21 BST 2011
gc.add(Calendar.DAY_OF_MONTH, 1);
// Wed Oct 19 15:20:21 BST 2011
gc.add(Calendar.DAY_OF_MONTH, 13);
// Tue Nov 01 15:20:21 GMT 2011
The roll functions are like add, but you don't roll forward:
GregorianCalendar gc = new GregorianCalendar();
// Tue Oct 18 15:24:31 BST 2011
gc.roll(Calendar.DAY_OF_MONTH, 1);
// Wed Oct 19 15:24:31 BST 2011
gc.roll(Calendar.DAY_OF_MONTH, 13);
// Sat Oct 01 15:24:31 BST 2011
Exercise
Check the Calendar API for changing the lenient mode. Use it to validate a date.
Date Calculations
Suppose we want to work out something like the point in time three fifths of the way between 1 Jan
1900 and 12 August 1973. Why? Maybe because you are drawing a graph with time as the x axis.
One way to do it is
1. Make Calendar objects of those two dates.
2. Extract the Date, then the underlying long
integer, from those two
3. Do arithmetic on the longs
4. Convert the result back into a Date, then a
Calendar:
GregorianCalendar gc1 = new GregorianCalendar(1900,0,0 );
GregorianCalendar gc2 = new GregorianCalendar(1973,7,11 );
Date date1 = gc1.getTime();
Date date2 = gc2.getTime();
long point1=date1.getTime();
long point2=date2.getTime();
long answer = point1 + (point2-point1)*3L/5L;
Date d =new Date();
d.setTime(answer);
GregorianCalendar gc3= new GregorianCalendar();
gc3.setTime(d);
System.out.println(gc3.getTime());
// Wed Mar 01 14:48:00 BST 1944

Exercise
Find out when you were half your current age.
Java
Page 119 - Copyright 2012 Walter Milner - all rights reserved
Interfaces
The idea of an interface is abstract and subtle - you might want to read this now, and again later.
A class can implement an interface. This means that the class can do the things the interface says it
can. Interface is a Java keyword.
An interface is a set of method signatures (headers, declarations) without method bodies. The class
'implements' an interface by providing a body for each of the methods.
What is the point of that? We often give an object the role of performing some task involving a set
of actions. This enables the compiler to check whether the object belongs to a class which can
actually do those actions.
As an example, we might want something which will respond to mouse actions on a GUI component
like a window. The MouseListener interface has methods for the mouse entering the component,
leaving, a mouse button depression, release and click. We might program a class called
MyMouseListener which implements that interface - in other words, actually defines those five
methods. Then we code the window that an instance of MyMouseListener will deal with mouse
actions. The compiler can check that MyMouseListener actually does implement MouseListener.
We can also think of an interface as a contract. This is like a contract of employemnt - it says the
employee will do certain things. It does not say how they will be done, it simply lists the tasks. It is
up to the employee to actually do it. The MouseListener is a contract of five tasks. Any class which
gets this job must fulfill that contract.
Example - the Comparable Interface
Suppose we have a class of objects consisting of a pair of integers, x and y, and we want to sort an
array of such objects. We will name the class Pair. The class Arrays (in the java.util package) has a
method called sort which will do that for us. But it can only sort objects which implement the
Comparable interface. This is because it is often not obvious what it means for one object to be
'more than' another. We will say that a Pair object is more than another if the sum of x and y is
more than the sum of the other objects x and y.
The Comparable interface has just one method, compareTo. This should return a positive int if the
object is more than the other, zero if it is equal, and a negative int if it is less.
So we must code our Pair class to do this method:
Java
Page 120 - Copyright 2012 Walter Milner - all rights reserved

class Pair implements Comparable {

int x, y; // a pair of ints

Pair(int a, int b) { // the constructor
x = a;
y = b;
}

void show() { // display values
System.out.println(x + " " + y);
}

public int compareTo(Object ob) {
// implements the Comparable method
Pair other = (Pair) ob;
if ((x + y) > (other.x + other.y)) {
return 1;
}
if ((x + y) == (other.x + other.y)) {
return 0;
}
return -1;
}
Code to create and sort the array is:
Pair[] data = new Pair[3]; // make an array
data[0] = new Pair(3, 2); // put 3 elements in
data[1] = new Pair(2, 2);
data[2] = new Pair(1, 2);
Arrays.sort(data); // sort
// see what we've got
for (int i = 0; i < data.length; i++) {
data[i].show();
}
The output is:
1 2
2 2
3 2
Exercise
Change the compareTo implementation so that one Pair is more than another if the average of x and
y is greater. Test it.

Java
Page 121 - Copyright 2012 Walter Milner - all rights reserved
Event handling
This section shows more examples of using classes and objects, and the event-handling mechanism
in Swing.
This makes a window with a button:
import javax.swing.JButton;
import javax.swing.JFrame;

public class Main extends JFrame {

JButton myButton;

public Main() {
super("Hello world!");
setBounds(50, 50, 300, 200);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
setLayout(null);
myButton=new JButton("Click me");
add(myButton);
myButton.setBounds(10,10,100,30);
}

public static void main(String[] args) {
Main myWindow = new Main();
}
}
This produces:
JButton is the Swing class modelling a button on the screen.

The line
JButton myButton;
declares a reference to a JButton object. This means every Main window object will have a JButton
object in it.
In the constructor, it says
myButton=new JButton("Click me");
Because of the word new, this invokes the constructor of JButton. In other words, this actually
makes a JButton object.
add(myButton);
This places the button on the window we are constructing.
myButton.setBounds(10,10,100,30);
This sends a message to the myButton object telling it to do its setBounds method, to set its position
and size. This is just like the setBounds method of the window.
We have to say
Java
Page 122 - Copyright 2012 Walter Milner - all rights reserved
setLayout(null);
to tell the window to not use a layout manager. This allows us to control the position of the button
directly.
As yet, the new button does nothing when clicked. We need an event handler.
Event handling
The next version is:
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;

public class Main extends JFrame implements ActionListener {

JButton myButton;

public Main() {
super("Hello world!");
setBounds(50, 50, 300, 200);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
setLayout(null);
myButton=new JButton("Click me");
add(myButton);
myButton.setBounds(10,10,100,30);
myButton.addActionListener(this);
}

public static void main(String[] args) {
Main myWindow = new Main();
}

public void actionPerformed(ActionEvent e) {
System.exit(0);
}
}
Now when the button has been constructed, we say
myButton.addActionListener(this);
This tells the button that when it is clicked, it should send a message to this - that is the window we
are constructing. We have to program the window to respond as we want.
The compiler will only allow that if the window is programmed with the correct method, which is the
actionPerformed method. It checks this by checking if the class implements the ActionListener
interface:
public class Main extends JFrame implements ActionListener

This interface has only one method - actionPerformed. We program this as:
public void actionPerformed(ActionEvent e) {
System.exit(0);
}
This method is executed when the button is clicked. It is an event handler - it handles the event of
the button being clicked. In this example, we tell the System to exit - in other words we tell the Java
runtime to end.
Java
Page 123 - Copyright 2012 Walter Milner - all rights reserved

Exercise
Try this out.
Replace the System.exit with code so that
when the button is clicked a new window is
constructed. This will be on top of the first so
you'll have to move it. You should be able to
get something like this.

Java
Page 124 - Copyright 2012 Walter Milner - all rights reserved
Defining a new class
We have seen how we can create new classes by extending existing classes.
We can also define new classes which do not extend others (except Object).
As an example we will start a stock control system as might be used in a shop. The things for sale are
modelled as StockItem objects. We want to be able set up new stock items, sell them, deliver new
stock, and find out the current stock level. Here is some code:
class Test {

public static void main(String args[]) {
StockItem item1 = new StockItem(20, "Tins of Beans");
item1.sell(10);
item1.deliver(5);
item1.show();
StockItem item2 = new StockItem(10, "Bags of flour");
item2.sell(2);
item2.deliver(5);
item2.show();
}
}

class StockItem {

int stockLevel;
String description;

StockItem(int s, String d) {
stockLevel = s;
description = d;
}

void deliver(int howMany) {
stockLevel += howMany;
}

void sell(int howMany) {
stockLevel -= howMany;
}

void show() {
System.out.println(description + " : Stock level = " + stockLevel);
}
}
Firstly, we have defined two classes, Test and StockItem, like this:
class Test {

public static void main(String args[]) {
..
}
}

class StockItem {

..
}
This is all in one file, called Test.java. The only purpose of the Test class is for main, where execution
starts. This is not a typical way to do it, but it works.
The class which models stock items is named StockItem. Classes should start with a capital letter.

Java
Page 125 - Copyright 2012 Walter Milner - all rights reserved
The definition begins with the declaration of two data members:
class StockItem {

int stockLevel;
String description;

..
}
That means each StockItem object (every instance of the StockItem class) will have a stocklevel and a
description.
We then have the constructor:
class StockItem {
..

StockItem(int s, String d) {
stockLevel = s;
description = d;
}
..
}
We know it is the constructor because it has the same name as the class. This is not a method, an dit
has no return type. It takes two parameters which are used to initialise the stock level an
description. We would use this like
StockItem item1 = new StockItem(20, "Tins of Beans");

Then there are three methods:

void deliver(int howMany) {
stockLevel += howMany;
}

void sell(int howMany) {
stockLevel -= howMany;
}

void show() {
System.out.println(description + " : Stock level = " + stockLevel);
}
In main we test this out:
StockItem item1 = new StockItem(20, "Tins of Beans");
item1.sell(10);
item1.deliver(5);
item1.show();
StockItem item2 = new StockItem(10, "Bags of flour");
item2.sell(2);
item2.deliver(5);
item2.show();
which outputs
Tins of Beans : Stock level = 15
Bags of flour : Stock level = 13
Exercise
Add attributes for price in StockItem, and modify the constructor and show() to correspond.
Java
Page 126 - Copyright 2012 Walter Milner - all rights reserved
Projects and Packages
A Java application usually consists of several new class definitions. Each new class is usually defined
in a separate file with a corresponding filename. For example a class named MyClass is defined in a
file named MyClass.java.
One of those classes will contain a 'public static void main(String[] args)' method, and so this will be
where execution starts.
These several class definition files are called a 'project'. This is not a Java keyword, but IDEs invite
you to start a new 'project' and organises files and directories for you. As well as class definitions, a
project may include resources such as image and sound files.
NetBeans (and other IDEs) allows you to have several projects open at the same time, and have one
set as the 'main' project. When you hit Run, it is the main project which is compiled and executed.
This shows the stages of creating a new project in NetBeans 7.01:


Create a simple Java application Call it Demo Project parts

If we then do Run.. Clean and Build Main Project, the following folders are produced. Folder src
contains the source code .java files which
we write. The build folder contains the
.class files which the compiler produces.
The dist folder contains jar files for
distribution - jars are described later. And
the nbproject folder contains metadata
about the project itself.

Packages

A project might have a considerable number of class definition files. It might be appropriate to group
those classes into sections which are about the same activity, and it might be useful to re-use some
of those sections in other projects.
Java
Page 127 - Copyright 2012 Walter Milner - all rights reserved
These ideas are supported by the Java keyword 'package'. A
package is simply a group of related classes. For example, the
project JCartes2 draws graphs of mathematical functions. It has
two packages, in addition to the default package which contains
documentation. The package 'parsing' contains classes which
handle calculations, and the package 'gui' handles the graphical
user interface.
Syntactically, this is done using
the keyword 'package' at the start
of each class definition. For
example to place a class in the
package 'gui', simply have
package gui;

as the first line of the class file.
Packages also fix the problem of
the same name being chosen for different classes. As an example, there are two Date classes. One
deals with dates in general, and the other is for dates in databases. The first is in the package
java.util, whilst the other is in java.sql. If we just want to use the first, we can use an import
import java.util.Date;
and then through the code just refer to Date, like
Date someDate = new Date();
If we want to use both in the same file, we must use the fully-qualified class name, including the
package name - for example
java.util.Date someDate = new java.util.Date();

Java
Page 128 - Copyright 2012 Walter Milner - all rights reserved
Encapsulation
The only way for errors to occur in a program is by being put there by the author. No other mechanisms are
known. Programs can't acquire bugs by sitting around with other buggy programs. ~Harlan Mills
One of the key concepts of OOP is encapsulation. The motivation is to prevent bugs which result
from pieces of software corrupting data. As Dr. Mills' quote points out, all bugs are written by
programmers. Encapsulation is an attempt to make the language make it hard for the programmer
to write a bug.
Structured programming organised code into global shared data and sets of functions (in Java,
methods) which processed that shared data. But there was no way to ensure that the global data
could not be accidentally accessed, and unintentionally corrupted, by a function. In other words
there was no way of saying that some data should only be accessible by certain functions.
The idea of an object by itself helps with this, since it links the data members with the methods
which are supposed to process that data. But there needs to be a mechansim to prevent other code
accidentally corrupting the data in the object. This is the purpose of encapsulation and access
control. It is not intended for security purposes.
There are two parts to the mechanism - access modifiers and get/set methods.
public
There is a keyword 'public' which can be applied both to data members and methods. For example,
the main method must be named as
public static void main(String[] args)
Here 'public' is an access modifier. It means that this method can be invoked from anywhere
(instead of just from this class or from the package it is in). The method has to be public, since Java
runtime must call this method to start the application, and the runtime is outside your package.
So methods which you want 'the world' to be able to call should be made public.
Data members should not normally be made public, since that would usually mean any code can
change them to any value. An exception is if the data member is final, so it cannot be changed. A
commonly used example is Math.PI. This is a member of the Math class, representing the value of ,
so is constant. Math.PI is static (which means it is per class, not that it is constant) .
private
Data members and methods which are declared as 'private' can only be accessed from within their
class. That means that methods which are only concerned with the internal operation of the class
should be private.
no access modifier - default
Members can be declared with no access modifier. In that case, the default, they are package-
private. That means they can be accessed within their package, only, and not from outside.
Java
Page 129 - Copyright 2012 Walter Milner - all rights reserved
protected
This is like package-private, except that it can be accessed by sub-classes, which might be in other
packages.
This table tries to summarise which one to use:
data methods
private yes - use get/set methods class-internal only
default package-private constant data only if needed by package
protected constant data only if to be used in sub-class in different package
public constant data only if needed outside package

Getter/setter methods
A getter method enables the value of a private data member to be read from outside the class or
package. The idea is to make the data be private, and provide a non-private method so that there is
read-only access to it. These methods are usually named getSomething - they do not have to be.
For example, a JFrame has a getBackground() which returns the colour of the window background.
Similarly a setter method allows a field to be given a value. A JFrame has a setBackground() method
to set the background color. Setter methods are usually public.
Why make the data members private and write setter methods? Why not make the data public so
they can be set directly? Because the setter method can validate the value being set, with an if, so
that it will only allow suitable values to be given. This does not mean bugs are impossible, but it
makes it more unlikely that the programmer will accidentally set invalid values.
Class level access modifiers
The access modifiers described above apply for individual data members and methods. We can also
give an access modifier to a class as a whole. But only 'public' or the default package-private is
allowed.
In other words if you say
public class ClassA..
then ClassA can be used anywhere. But
class ClassB..
can only be accessed from within its own package. You would do this if the class was needed for the
internal operation of a package, but was not intended to be directly accessed.



Java
Page 130 - Copyright 2012 Walter Milner - all rights reserved
Writing new classes - a personnel system
As an example of how new classes are written, we will set up a personnel system. To make things
clear it will be very simple, and just handle employees and departments.
Code structure
Recall that Java code is split into separate source code files, with each public class defined in each
file. Also there will be a method called
main somewhere where execution will
start:
In an IDE this will be a new project which
we will call 'personnel'. Classes are
grouped into packages, but this simple
example only needs one package, also
called personnel. Each class definition will
start with
package personnel;
which tells the compiler which package the class is in.
Class design
In this application we will have just 3 classes:
Start - to contain main
Department - to model a department
Employee - to model an employee
The department class
The code for this is
package personnel;

class Department {
private String name;

Department(String n)
{
name=n;
}

void display()
{
System.out.println("Department : "+name);
}

String getName()
{
return name;
}
}
We will go through this first class in a lot of detail. The overall structure of this is
Java
Page 131 - Copyright 2012 Walter Milner - all rights reserved
package..
class Department
{
..data members
.. constructors and methods
}
The package statement must come as the first line. That is where the compiler will look for it.
Then we have the class definition, which starts class Whatever { and ends with the matching } .
Within that we have the data members, constructors and methods. The order of these does not
matter. These will not be executed in sequence, so the order does not matter. It is a definition of
what is in the class, not a program.
After the class header we have
private String name;
This is the only data member in the class - the name of the department. This is a String, and String is
a class, hence the capital letter. It does not say what the name is, since this will be different for each
Department object - each instance of the class. It just states that each Department object will have a
name.
Then we have the constructor:
Department(String n)
{
name=n;
}
We know it is a constructor because it has the same name as the class. It has one String argument, n,
and a single statement, which assigns the field 'name' to this argument.
For example, a department is created by
dep1 = new Department("Production");
Here the argument value "Production" is passed into the constructor as the argument n, and this is
assigned to the department's name field, so it becomes "Production". Distinguish between teh name
of the variable which referencs the object (dep1), and the name field of teh object (Production).
Next we have a method definition
void display()
{
System.out.println("Department : "+name);
}
The fragment display() means the method name is 'display', and the empty bracket shows it takes
no arguments. The void means this method does not return a value - it sends nothing back to where
it was invoked from - it just does something. What it does is to simply output the department name.
The only other method is
Java
Page 132 - Copyright 2012 Walter Milner - all rights reserved
String getName()
{
return name;
}
This does return a value, of type String. It returns the name of the department. This is an accessor
method, a get, which is needed because of access control.
Encapsulation and access control
Remember that encapsulation means sealing up data within objects so that they cannot be
corrupted by bugs. Three access levels are:
private - accessible only from this class
nothing - the default, accessible from this package.
public - accessible from anywhere
The data member is private - it is encapsulated within the class and cannot be accidentally changed
from out of it.
The constructor and method are nothing - that is, package access level. That is what we need.
The data member is private - but sometimes we need to know what the department name is, from
outside the class. We achieve this with an accessor method, a getter,
String getName()
Effectively this makes 'name' to be read-only - we can read it from the package outside the class, but
nothing outside the class can change it.
The Employee class
This is
package personnel;

class Employee {
private String name;
private int salary;
private Department department;

Employee(String name, int salary, Department department)
{
this.name=name;
this.salary=salary;
this.department = department;
}
void setSalary(int salary)
{
this.salary=salary;
}

void display()
{
System.out.println("Name: "+name + " department: "+department.getName()+" Salary:
"+salary);
}

}
Most of this is similar to Department - we just pick out the differences.
Java
Page 133 - Copyright 2012 Walter Milner - all rights reserved
The constructor has three argument, which are values for the data members. But their names are
the same as the names of the data members - which in one sense is logical, but might be confusing.
The resolution is to use the keyword this:
this.salary=salary;
this.salary means we are referring to the salary field of this object we are constructing. The other
one, just 'salary', is the value of the argument with that name. This technique means we can avoid
having to use argument names different from what they mean, such as
Employee(String n, int s, Department d)
{
name=n;
salary=s;
department = d;
}
In the display method, we say
+.." department: "+department.getName()+..
We cannot say
+ " department: "+department.name+"
and access the department name directly, because the name field is private. We have to use the
accessor method.
Counting the objects
The Employee class has a data field for a Department. Does that mean that when we create an
Employee object, we also create a new Department object?
No. The keyword new does not appear in the class definition, so no new objects are being created.
The data field 'department' is a reference to another object which already exists, not a newly
created one. The code to use these classes is like:
Department dep1 = new Department("Marketing");
..
Employee emp1 = new Employee("John Smith", 20000, dep1);
The first line creates a new Department object. Then we create a new Employee object, passing to it
a reference to the already existing object called dep1.
Do not be confused by the idea of 'name'. In the line
Employee emp1 = new Employee("John Smith", 20000, dep1);
the name of the object is emp1. Objects of that class have a data field called name. In this instance,
the value of that is "John Smith". But the object is called emp1, not "John Smith".
The Start class
This is:
Java
Page 134 - Copyright 2012 Walter Milner - all rights reserved
package personnel;

public class Start {

public static void main(String[] args) {

Department dep1 = new Department("Marketing");
Department dep2 = new Department("Production");
Department dep3 = new Department("R & D");
dep1.display();
dep2.display();
dep3.display();
Employee emp1 = new Employee("John Smith", 20000, dep1);
Employee emp2 = new Employee("Jane Jones", 22000, dep1);
Employee emp3 = new Employee("Joe Jeffs", 19000, dep2);
emp1.display();
emp2.display();
emp3.display();
emp1.setSalary(22000);
emp1.display();

}
}
This class is public, as is the main method. This has to be so, since main must be accessible from
outside the package, when the runtime system calls it to start the application.
The main method just makes some Department and Employee objects, displays them, changes
someone's salary and displays them again. The output is:
Department : Marketing
Department : Production
Department : R & D
Name: John Smith Department: Marketing Salary: 20000
Name: Jane Jones Department: Marketing Salary: 22000
Name: Joe Jeffs Department: Production Salary: 19000
Name: John Smith Department: Marketing Salary: 22000
Static and non-static
What does 'static'mean?
Static means per class

Non-static is per object
Most data fields are per object. That means, there is a separate value for each object. For example,
Employee object has a non-static field called 'name'. This is because each employee has their own
name. Similarly for the non-static field salary - each employee has their own salary.
We refer to non-static fields as
<object>.<field>
We have to say which object, since different objects have different values. For example
emp1.name
is the name field of the emp1 object.
Java
Page 135 - Copyright 2012 Walter Milner - all rights reserved
But sometimes it is useful to have some value which belongs to the class, as a whole, not to
individual objects. This is what static means. It is per class, not per object. We refer to a static field
by
<Class>.<field>
All of this applies to methods as well as data fields.
Examples of static - 1
The purpose of the main method is to provide a starting point for the application. Obviously we can
only have one starting point. We can achieve this by making main to be static. Then it is per class. It
is only in one class, so we just have one of it. If it was non-static, then we would have a main method
for each instance of the class, which does not make sense.
In our example, main is in the Start class. The full name of it is
Start.main
We have now explained all of the qualifiers of main:
public static void main(String[] args)
public so it can be accessed from outside the package, by the runtime system. static because it is per
class, so there is just one of it. void because it does not return a result, just does something.
Static example 2 - object arrays
As we have the application at the moment, we make department and employee objects, but they
just 'lie around' in main, where they are declared, one at a time. It would be better if we could refer
to all the departments, or all the employees. We could do this if we put them into arrays. But where
to put the arrays? We could declare them in main, like
static void main(String[] args)
{
Department[] departments = new Department[10];
..
but this would mean the array was local to main, and could not be referred to anywhere else, which
we might want to do.
If we declare it like
package personnel;

public class Start {
Department[] departments = new Department[10];

public static void main(String[] args) {
..
that means the array is non-static - that is there will be a different copy for each instance of the Start
class. But in this version we do not instantiate the Start class - we nowhere say
..=new Start();
But if we say
Java
Page 136 - Copyright 2012 Walter Milner - all rights reserved
package personnel;

public class Start {
static Department[] departments = new Department[10];

public static void main(String[] args) {
..
then the array is per-class - we have one version of it, linked to the class. The full name of the array
is
Start.departments.
We will do this, for employees as well, and in their constructors put the new object into the correct
array. Then we can have methods to output all departments and all employees. We need to keep
track of how many departments and employees we have:
So now Start is:
package personnel;

public class Start {

static Department[] departments = new Department[10];
static int departmentCount = 0;
static Employee[] employees = new Employee[10];
static int employeeCount = 0;

public static void main(String[] args) {
Department dep1 = new Department("Marketing");
Department dep2 = new Department("Production");
Department dep3 = new Department("R & D");
Department.displayAll();
Employee emp1 = new Employee("John Smith", 20000, dep1);
Employee emp2 = new Employee("Jane Jones", 22000, dep1);
Employee emp3 = new Employee("Joe Jeffs", 19000, dep2);
Employee.displayAll();
}
}
Employee, with a modified constructor and displayAll, is:
Java
Page 137 - Copyright 2012 Walter Milner - all rights reserved
package personnel;

class Employee {
private String name;
private int salary;
private Department department;

Employee(String name, int salary, Department department)
{
this.name=name;
this.salary=salary;
this.department = department;
Start.employees[Start.employeeCount]=this;
Start.employeeCount++;
}

static void displayAll()
{
for (int i=0; i<Start.employeeCount; i++)
Start.employees[i].display();
}
void setSalary(int salary)
{
this.salary=salary;
}

void display()
{
System.out.println("Name: "+name + " Department: "+department.getName()+" Salary:
"+salary);
}

}
and similarly with Department:
package personnel;

class Department {
private String name;

Department(String n)
{
name=n;
Start.departments[Start.departmentCount]=this;
Start.departmentCount++;

}

void display()
{
System.out.println("Department : "+name);
}

String getName()
{
return name;
}
static void displayAll()
{
for (int i=0; i<Start.departmentCount; i++)
Start.departments[i].display();
}

}
In the displayAll methods, the syntax of
Start.employees[i].display();
refers to Start.employees[i] , then tells that object to do its display() method.
Java
Page 138 - Copyright 2012 Walter Milner - all rights reserved
Static example 3 - class design
As much as possible, we want to 'de-couple' classes, which is to make them as independent as
possible. This makes it easier to re-use them in other situatuions, and lets us develop and debug
them in one place, not in a tangled web across the application.
In our example code, both Start and Employee deal to some extent with employee objects. It would
be better if Employee dealt with all aspects of the employee objects, and similarly for Departments.
We can do this by switching the arrays to their appropriate classes. Now Start looks a lot tidier:
package personnel;

public class Start {

public static void main(String[] args) {
Department dep1 = new Department("Marketing");
Department dep2 = new Department("Production");
Department dep3 = new Department("R & D");
Department.displayAll();
Employee emp1 = new Employee("John Smith", 20000, dep1);
Employee emp2 = new Employee("Jane Jones", 22000, dep1);
Employee emp3 = new Employee("Joe Jeffs", 19000, dep2);
Employee.displayAll();
}
}
Employees is:
package personnel;

class Employee {

private String name;
private int salary;
private Department department;
static Employee[] employees = new Employee[10];
static int employeeCount = 0;

Employee(String name, int salary, Department department) {
this.name = name;
this.salary = salary;
this.department = department;
employees[employeeCount] = this;
employeeCount++;
}

static void displayAll() {
for (int i = 0; i < employeeCount; i++) {
employees[i].display();
}
}

void setSalary(int salary) {
this.salary = salary;
}

void display() {
System.out.println("Name: " + name + " Department: " + department.getName() + "
Salary: " + salary);
}
}
We no longer say, for example
Start.employees[i].display();
because the employees array is no longer a static member of Start. We could say
Java
Page 139 - Copyright 2012 Walter Milner - all rights reserved
Employee.employees[i].display();
but because this code is in the Employee class, we can miss out the Employee.
Similarly Department is
package personnel;

class Department {

private String name;
static Department[] departments = new Department[10];
static int departmentCount = 0;

Department(String n) {
name = n;
departments[departmentCount] = this;
departmentCount++;
}

static void displayAll() {
for (int i = 0; i < departmentCount; i++) {
departments[i].display();
}
}

void display() {
System.out.println("Department : " + name);
}

String getName() {
return name;
}
}
Remember that
static is per class

non-static is per object
Exercise
Write an application to do stock control (inventory control) in a supermarket. Do NOT write it all in
one go them test it! Write a small section at a time and test as you go along. You should have
different Sections (like tinned fruit, frozen and household) and Goods (like peaches, peas and
dishwasher tablets). Each of the goods needs a price and a current stock level.
You should be able to -
Set up new sections and goods.
Display all sections and all goods.
Sell some items, and so reduce the stock level.
Reduce the price of all items in a given section by 10%

Java
Page 140 - Copyright 2012 Walter Milner - all rights reserved
Writing New Classes - Tic Tac Toe
This section shows how new classes can be designed and written. This will be done using the
example of the game Noughts and Crosses, also known as Tic Tac Toe. We will write this as a
character-based game, then in the next section adapt it to a GUI.
Designing new classes
We first have to identify what classes would be involved in the game. That is, we must identify the
things in the game. One way to do this is to look for the nouns in a description of the context. This is
how wiki describes it:
Tic-tac-toe, also rendered wick wack woe (in some Asian countries), or noughts and
crosses/Xs and Os as it is known in the UK, Australia and New Zealand, is a pencil-and-paper
game for two players, X and O, who take turns marking the spaces in a 33 grid. The X player
usually goes first. The player who succeeds in placing three respective marks in a horizontal,
vertical, or diagonal row wins the game.
In our version, one player will be the user, and the computer will be the other player. Here is a set of
classes:
Game. There would only be one instance of this class - just one game object. This is an example of a
singleton class. The Game class would need to let the two players alternate turns, check if someone
had won after each go, and end the game if they had. This class could contain the main method,
since we start by starting the game.
Board. This would need to have a 3X3 grid, and be able to show it. Again a singleton.
Human player. This singleton would represent the human player. It would have to provide for a
human turn, where the board was shown and the user allowed to chose where to go.
Computer player. This singleton represents the human's opponent. The key method would be to
decide where to go.
Projects and packages
An application like this, containing several classes, is a project. The source code (the class definitions)
is organised into one or more packages.
In this case our project could be called ttt, for tic tac toe, and it needs just one package, also called
ttt. We might have done this differently - say one package for the visual content, and another for the
game logic. But this is a pretty simple project so we do not.
The class definitions are now listed. Note they were not written like this and then tested. They were
written small sections at a time, and tested after each small step. This is the end result:
Java
Page 141 - Copyright 2012 Walter Milner - all rights reserved
package ttt;

public class Game {

// data fields
private Board board;
private Human human;
private Computer computer;

// play the game:
private void play() {
while (true) { // loop forever
human.go(); // human's turn
// check if they've won
if (board.checkWin('X')) {
break; // leave loop if so
}
computer.go(); // computer's turn
if (board.checkWin('O')) {
break; // leave loop if computer has won
}
board.display(); // show board and loop
}
// if leave loop, somebody's won:
System.out.println("Game over:");
board.display();
}

// constructor
private Game() {
// create the 3 objects which are part of a Game object
board = new Board();
//pass a reference to the board to the constructors of the human and computer
// this lets them refer to the board
human = new Human(board);
computer = new Computer(board);
}

public static void main(String[] args) {
Game game = new Game(); //make a game
game.play(); // play it
}
}
Then the board. It needs to be able to tell if someone has won, and it does this by brute force. There
are only 8 winning configurations - three rows, three columns and two diagonals - and it simply tests
them all.
Java
Page 142 - Copyright 2012 Walter Milner - all rights reserved
package ttt;

class Board {
// data member - an array of characters
private char cells[][] = new char[3][3];

// construct a board
Board() {
// fill the array with space characters
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
cells[i][j] = ' ';
}
}
}

// mark an 'X' or 'O'
void set(int i, int j, char c) {
// check is valid
if (i > -1 && i < 3 && j > -1 && j < 3 && (c == 'O' || c == 'X')) {
cells[i][j] = c;
}
}

char getCell(int r, int c) {
return cells[r][c];
}

// return true if someone's won, otherwise return false
boolean checkWin(char c) {
boolean result = false;
//check rows
if (cells[0][0] == c && cells[0][1] == c && cells[0][2] == c) {
result = true;
}
if (cells[1][0] == c && cells[1][1] == c && cells[1][2] == c) {
result = true;
}
if (cells[2][0] == c && cells[2][1] == c && cells[2][2] == c) {
result = true;
}
//check columns
if (cells[0][0] == c && cells[1][0] == c && cells[2][0] == c) {
result = true;
}
if (cells[0][1] == c && cells[1][1] == c && cells[2][2] == c) {
result = true;
}
if (cells[0][2] == c && cells[1][2] == c && cells[2][2] == c) {
result = true;
}
// leading diagonal
if (cells[0][0] == c && cells[1][1] == c && cells[2][2] == c) {
result = true;
}
//other diagonal
if (cells[0][2] == c && cells[1][1] == c && cells[2][0] == c) {
result = true;
}
return result;
}
// display the board
void display() {
for (int i = 0; i < 3; i++) {
// display a row
for (int j = 0; j < 3; j++) {
System.out.print("| " + cells[i][j] + " ");
}
// new line at end of row:
System.out.println("|");
}
}
}
Java
Page 143 - Copyright 2012 Walter Milner - all rights reserved
The human player:
package ttt;

import java.util.Scanner;

class Human {
private Scanner scanner=new Scanner(System.in);
private Board board;

Human(Board b)
{
board=b;
}

void go()
{
System.out.println("Enter row, column);");
int row= scanner.nextInt();
int column = scanner.nextInt();
board.set(row, column,'X');
}

}
and the computer
package ttt;

class Computer {

private Board board;

Computer(Board b) {
board = b;
}

void go() {
// at random, find a space
int row = (int) (Math.random() * 3);
int col = (int) (Math.random() * 3);
while (board.getCell(row, col) != ' ') {
row = (int) (Math.random() * 3);
col = (int) (Math.random() * 3);
}
// and put an O there
board.set(row, col, 'O');
}
}
The computer is not too bright. It chooses cells at random until it finds one which is empty, and goes
there.

Java
Page 144 - Copyright 2012 Walter Milner - all rights reserved

Objects in the application

This shows the four main objects which exist when this application is running. Execution starts at
main, and this constructs the game object. That also constructs the human, computer and board
objects.
The arrows show which objects contain references to others. The game has references to the human
and computer objects, so that it can tell them to do their go methods. It also has a reference to the
board object, so that it can tell it to do its display and checkwin methods.
The human and computer objects also have references to the board. This is possible because that
reference was passed to them in their constructors. They need it so that their go methods can use its
get method to find out what is on the board.
Access levels - encapsulation
Recall that encapsulation means sealing objects as much as possible to prevent their corruption by
bugs. This application uses 3 access modifiers
public - can be accessed from anywhere.
no keyword - access restricted to the package.
private - accessible only from that class.
These can be applied to classes or class members. Access levels are chosen here as follows
Game - the class is public. This is because it contains main, which is itself public. The runtime system
must have access to this to start everything off. All other members of game, data fields and
methods, are private. This is the 'best' - members should be private unless there is a reason why
they cannot be.
Board - the class has no access keyword, so access is restricted to the package. There is no reason
why wider access is needed. The same is true of the methods - they are needed to be accessed from
other classes in the package. But the data member, the two D array, is private. But we have get and
set methods which prvide access through them. The set method checks that the row and columns
are possible, and that the character being set if either X or O.
Java
Page 145 - Copyright 2012 Walter Milner - all rights reserved
Human - the class, constructor and go method have no keyword, so are visible to the package, as
needed. The data fields, the scanner and the reference to the board, are private, since that is
enough. The computer object is similar.
Exercise
Try this application out.
Make sure you can understand every line of it.
The computer is dumb - it always loses unless you try hard to let it win. Devise and implement a
better 'go' algorithm for the computer. This is not easy.


Java
Page 146 - Copyright 2012 Walter Milner - all rights reserved
Binary Trees
The subject of data structures and algorithms is a central part of Computer Science, and it is a large
topic - enough to fill several books, with on-going research to fill several journals. This section will
cover some key ideas, by looking at one structure - a tree.
Binary tree
Data structures are composed of elements called nodes. A node contains some data, together with
other parts, especially pointers (in Java, references) to other nodes. The data typically has a key field
to identify it, together with other fields
which we need to store and recall.
A tree data structure is named
metaphorically after a biological tree,
but it is upside down - the root is at the
'top'. Each node carries some data,
and pointers to left and right nodes. Some pointers are
null, if there are no left or right nodes.
From the root, the left node, and the nodes beneath it,
form a structure which is itself a tree. This is the left sub-
tree. Similarly we have a right sub-tree. Since trees are
made of trees, we might expect to be able to treat them recursively. The depth of a tree is how far
down from the root to the bottom.
This is a binary tree, because each node has at most 2 sub-nodes.
Trees do not have to be binary.
What would an empty tree be like? The root would be null - it has
no nodes in it.
When data is added to a tree - where to put it? One algorithm would
be to put the first item at the node, the next 2 on the second 'row',
the next 4 on the third row and so on, in the sequence shown.
Another way is for each value inserted, we start by comparing it
with the root. If it is less, we move to the left node, else (equal
or more) to the right. We do the same again, moving left if less,
and right if more or equal, until we reach a null. And we put the
data in a new node there. For example, suppose we put the
following into the tree: 50,25,75,12,80,30, 50, 51 - we get the
structure as shown.
Java
Page 147 - Copyright 2012 Walter Milner - all rights reserved
A Java implementation
To start with, we can have a class representing one of the nodes in the tree. The data at each node is
an int, but we could have any type:
class TreeNode {

int data;
TreeNode left;
TreeNode right;

TreeNode(int n) {
data = n;
right = left = null;
}
}
Then for a tree:
class BinaryTree {

TreeNode root;

BinaryTree() {
root = null;
}


}
So the tree just has a reference to its root. When we make a new (empty) tree, we just make the
root null.
How to put something in the tree? We have to
1. Make a new node
2. Work out where to put it
3. Put the node there
This will be done so the tree is left-right
ordered. So start at the root. If the value is
less, go left, otherwise go right. Repeat until
the left or right is null, and link it there. In
the following code, 'where' is the current
node, and we loop until this is null. But then
we have lost where to put it. So we also have 'lastWhere', which is the node whose left or right is
null, and we link the new node to lastNode.
We have to check the special case of an empty tree. We just point the root to a new node:
Java
Page 148 - Copyright 2012 Walter Milner - all rights reserved
void add(int n) {
TreeNode newNode = new TreeNode(n);

if (root == null) {
root = newNode;

return;
}
TreeNode where = root;
TreeNode lastWhere = where;
while (where != null) {
lastWhere = where; // where we were
if (where.data > n) { // now go left or right
where = where.left;
} else {
where = where.right;
}
}
if (lastWhere.data > n) {
lastWhere.left = newNode;
} else {
lastWhere.right = newNode;
}
}
How to go through the nodes in the tree? In other words, how to traverse it?
A method which will retrieve the data in order is an in-order traversal. This is a recursive process, as
follows:
if there is a left sub-tree (left is not null), traverse it
process the data at the node
if there is a right sub-tree (right is not null), traverse it
We start this off at the root node. 'process the data' could be anything - in our case, we will just
output it.
This is recursive - so the node will not be processed until the entire left sub-tree has been traversed.
In code:
void inOrderTraverse(TreeNode where) {
if (where.left != null) {
inOrderTraverse(where.left);
}
System.out.print(where.data + " ");
if (where.right != null) {
inOrderTraverse(where.right);
}

}
Typically for recursive procedures, this looks very simple, but needs close examination.
The other two standard types of traversal are pre-order:
process the data at the node
if there is a left sub-tree (left is not null), traverse it
if there is a right sub-tree (right is not null), traverse it
and post-order
if there is a left sub-tree (left is not null), traverse it
if there is a right sub-tree (right is not null), traverse it
process the data at the node

Java
Page 149 - Copyright 2012 Walter Milner - all rights reserved
Code to make a new tree, insert numbers into it, and traverse it, is:
int[] data = {50, 25, 75, 12, 80, 30, 50, 51};
BinaryTree tree = new BinaryTree();
for (int i = 0; i < data.length; i++) {
tree.add(data[i]);
}
tree.inOrderTraverse(tree.root);
which outputs 12 25 30 50 50 51 75 80
So in fact we have a new type of sort. How fast is it?

final int SIZE=100000;
int[] data = new int[SIZE];
Random randomGenerator = new Random();
for (int i=0; i<SIZE; i++)
data[i]=randomGenerator.nextInt(SIZE*2);

BinaryTree tree=new BinaryTree();
for (int i = 0; i < data.length; i++) {
tree.add(data[i]);
}
tree.inOrderTraverse(tree.root);
output 1 1 1 5 7 10 13 14 14 14 14 18 19 20 22 25 28 31 32 33 34 34 37 39 39 42 ..
It takes less than two seconds to generate and sort 100,000 ints.
Why is it so fast? To insert a value, it starts at the root and goes left or right until it hits 'the bottom'
where the link is null - the depth of the tree. How deep is that? The answer is roughly how many
times you can halve 10000 - or log
2
10000 16.6. So to insert each value, we only have to make up
to 16 comparisons. In general for n values we can sort them in n log n time.
This is for random values. What if the numbers are already in order?
final int SIZE=100000;
int[] data = new int[SIZE];
for (int i=0; i<SIZE; i++)
data[i]=i;
The output (after about 20 seconds) is
Exception in thread "main"
java.lang.StackOverflowError.
The tree looks as shown, and the depth of
the recursive calls to traverse it is 100,000
- too large for the usual stack space.
So this tree insertion sort is excellent for
mixed up data, but terrible on ordered
data.



Java
Page 150 - Copyright 2012 Walter Milner - all rights reserved

Exercise
1. Try this out
2. Predict what order the numbers would come out in for a pre-order traversal, then try out. The try
post-order.
3. To 'prettyprint' a tree means to print it out formatted so it looks like our diagrams. The root is at
the top in the centre. The left and right nodes are below and to each side, and so on.
Prettyprint the tree. This could be using System.out.println, or in Swing using Graphics2D and
drawString. Either way you need to add attributes to a node showing the depth of the node and how
far 'across' it is.
One approach would be to traverse the tree putting the information into an array, with the root in
the first element, the two nodes below in element 2, and so on, then go through the array to print it.
Java
Page 151 - Copyright 2012 Walter Milner - all rights reserved
Hash tables
For most data structures data is stored in it, and then some kind of search is needed to find it again.
The search may be slow.
For a hash table structure, a calculation is made to find where to store the data. When it is needed
to find it, the calculation is repeated, and located immediately. This should be fast.
The data is treated as having a key, to identify it, and associated values. We want to store key-value
pairs in the structure. Then given a key, we should be able to retrieve the value quickly.
The calculation is called a hash function. The input to this is a key value, and the output is a location
where the data is stored.
The underlying data store might be an array, and the 'location' is the index of the element in the
array.
This is a simple version of the basic idea. Various problems arise which must be handled.
Hash table in Java
The data will be a key which is an integer, and a value which is a String. The key and value types
could be anything.
The underlying data store is an array with 20 elements. Real hash tables are much bigger than this,
but we use this so we can output the whole table in a readable form.
The hashing function is (2 X key ) mod 20. So key 1 is stored at index 2. key 4 is stored at 8. We use
mod 20 so we wrap around the array.For example key 12 is stored at 4.
We need methods to insert a key-value pair, retrieve a key and its value, and remove a key.
Java
Page 152 - Copyright 2012 Walter Milner - all rights reserved
class HashTable {

final int SIZE = 20;
Record[] table;

HashTable() {
table = new Record[SIZE];
for (int i = 0; i < SIZE; i++) {
table[i] = null;
}
}

void put(Record record) {
int where = hash(record.key);
table[where] = record;
}

Record get(int key)
{
int where = hash(key);
return table[where];
}

void showTable()
{
System.out.println("Table");
for (int i=0; i<SIZE; i++)
{
if (table[i]==null) System.out.println(i+" null entry");
else
System.out.println(i+" Key:"+table[i].key+" Value:"+table[i].value);
}
System.out.println("-------------------");
}

private int hash(int n) {
return (n * 2) % SIZE;
}
}

class Record {
Integer key;
String value;
Record(Integer key, String value) {
this.key = key;
this.value = value;
}
}
We could use this like:
HashTable hashTable = new HashTable();
hashTable.put(new Record(1,"John"));
hashTable.put(new Record(3,"June"));
hashTable.put(new Record(6,"Jane"));

hashTable.showTable();
Record r = hashTable.get(1);
System.out.println(r.value);
which outputs:
Table
0 null entry
1 null entry
2 Key:1 Value:John
3 null entry
4 null entry
5 null entry
6 Key:3 Value:June
7 null entry
8 null entry
9 null entry
10 null entry
Java
Page 153 - Copyright 2012 Walter Milner - all rights reserved
11 null entry
12 Key:6 Value:Jane
13 null entry
14 null entry
15 null entry
16 null entry
17 null entry
18 null entry
19 null entry
-------------------
John // getting key 1
So key 1 went in at 2, 3 at 6, and 6 at 12.
The first problem is collisions. This is when two different keys hash to the same location. For
example, 1 goes to 2, but 11 would hash to 2 as well. Different keys would go in the same slot.
We could try to use a different hashing function - the one here is very simple but defective. But that
would never fully solve the problem. It would only be fixed if every different key went to a different
slot. That would need over 2 billion entries in the array - too much memory required.
An alternative is to store it in the next available free slot. We change to put algorithm to
1. Calculate the hash position
2. Store the data there, or in the next available free slot
We need to change put, and also the get:
void put(Record record) {
int where = hash(record.key);
while (table[where] != null) {
where = (where + 1) % SIZE;
}
table[where] = record;
}

Record get(int key)
{
int where = hash(key);
while (table[where]!=null && table[where].key != key)
where = (where + 1) % SIZE;
return table[where];
}
Test use:
HashTable hashTable = new HashTable();
hashTable.put(new Record(1,"John"));
hashTable.put(new Record(11,"First collision"));
hashTable.put(new Record(21,"Second collision"));
hashTable.put(new Record(31,"Third collision"));
hashTable.put(new Record(3,"June"));
hashTable.put(new Record(6,"Jane"));

hashTable.showTable();
Record r = hashTable.get(21);
System.out.println(r.value);
Outputs
Table
0 null entry
1 null entry
2 Key:1 Value:John
3 Key:11 Value:First collision
4 Key:21 Value:Second collision
5 Key:31 Value:Third collision
6 Key:3 Value:June
7 null entry
..
Java
Page 154 - Copyright 2012 Walter Milner - all rights reserved
19 null entry
-------------------
Second collision // getting key 21
This works, but we are starting to get a sequence of entries which we have to search through,
making insertion and retrieval slower. A different probe sequence would help. Even then, as the
array becomes more full (increased load factor), it will become slower. One approach would be to
monitor the load factor, and if it exceeds say 0.7, copy the data to a larger array (and modify the
hash function.
Exercise
1. Try this out
2. What happens if we ask to 'get' a key which is not in the table?
3. Write a remove method which takes a key and removes the corresponding key-value pair. This is
not as simple as replacing the entry with null (this is the 'second problem'). This is because it might
make a hole in a chain, and then a 'get' might conclude data was absent when it was not. For
example if we have

0 null entry
1 null entry
2 Key:1 Value:John
3 Key:11 Value:First collision
4 Key:21 Value:Second collision
5 Key:31 Value:Third collision
6 Key:3 Value:June
7 null entry
and we delete 11, to get
0 null entry
1 null entry
2 Key:1 Value:John
3 null entry
4 Key:21 Value:Second collision
5 Key:31 Value:Third collision
6 Key:3 Value:June
7 null entry
then when we get 21, we will go to 2, find a null at 3, and think 21 is absent. One solution is to have
a special 'deleted record'.
4. Maintain a 'load factor' and double the underlying array when it exceeds 0.7.








Java
Page 155 - Copyright 2012 Walter Milner - all rights reserved
Swing

The Swing toolkit is a group of packages which are used for creating GUI interfaces. With Swing you
can create windows, labels, text boxes, radio buttons, scroll bars and so on.
An alternative to Swing is the Abstract Windowing Toolkit, or AWT. This is abstract in the sense that
you use ideas like buttons, which are an abstract version of the actual buttons present on native
GUIs in Windows, Solaris and other OS's. The AWT started with JDK 1.0
AWT used OS native code to draw its widgets. Swing uses Java to do a lot of the drawing. AWT is said
to be 'heavy-weight' whereas most classes in Swing are lightweight. Swing started in JDK 1.2. In
most versions of the JDK, you cannot mix AWT and Swing.
These brief notes are intended to explain what Swing is all about, and to provide brief code snippets
to enable you to quickly write GUI interfaces which work in typical ways.They are not a complete
reference - for that, look at the online API.
Useful Link
The Oracle Swing tutorials:
http://docs.oracle.com/javase/tutorial/ui/index.html


Java
Page 156 - Copyright 2012 Walter Milner - all rights reserved
Starting a Swing application
Since Swing controls the user interface, it needs to handle keystrokes, mouse clicks and drags and so
on. These are treated as events, and you write pieces of code called event handlers to control what
happens when the user clicks a button and so on. This is described in detail later on.
When an application which uses Swing starts, an additional thread is started which receives and
dispatches events to the appropriate handler. This event dispatching thread is additional to the
initial application thread which runs main.
However Swing code is not threadsafe. This means the thread of main and the event-dispatching
thread are not synchronised, and deadlock between them is possible. This problem is solved if all
code to create and run the UI is done in the event dispatching thread. A class calledSwingUtilities has
a static method for doing this, which can be used like this, in code you would probably have in main:
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
This defines an anonymous inner class which implements the Runnable interface, and passes an
instance of that to the invokeLater method. The createAndShowGUI is a method that you write,
possibly in the class that has main. For example:
class Test {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
static void createAndShowGUI() {
MyFrame frame = new MyFrame("A Window");
}
}

class MyFrame extends JFrame {
MyFrame(String title) {
super(title);
setBounds(0, 0, 400, 200);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
}
}

In the listings which follow, we are mostly concerned with the frame constructor, and sometimes
extra methods in the MyFrame class for event-handling.
Exercise
Try this out.
Modify the frame's size and position.
Keep this as a template for Swing apps which follow.

Java
Page 157 - Copyright 2012 Walter Milner - all rights reserved
Swing event handling
A GUI is not simply appearance - it has to react to user actions. For example, we need to supply code
so that something happens when a button is clicked. This is called event handling.
We will first see how this is done for button clicks, then look at events in general.
When a button is clicked, it generates an ActionEvent object. This is dealt with as follows:
1. When we create the button, we tell it where it should send its ActionEvent objects when it is
clicked. This is done using the addActionListener method.
2. The object which receives the ActionEvents must implement the ActionListener interface.
3. That interface has just one method, called actionPerformed. The actionPerformed method will be
executed when the button is clicked, so you write there what you want to happen when the button
is clicked.
This plan can be carried out in different ways - in particular, different choices of object for step 2.
This is often done using anonymous inner classes, which is rather obscure syntax. A simpler
approach is to have the container object - the JFrame - receive the ActionEvent clicks. As follows:
class MyFrame extends JFrame implements ActionListener {
MyFrame(String title) {
.. as before..
JButton button = new JButton("OK");
add(button);
button.setBounds(5, 30, 80, 20);
button.addActionListener(this);
}

public void actionPerformed(ActionEvent e) {
System.out.println("You clicked");
}
}
Now our frame implements the ActionListener interface, which is the actionPerformed method. We
have told the button to addActionListener this - so its ActionEvents will be sent to the frame object,
and its actionPerformed method is called.
Which Button?
Suppose we have more than one button - which is usually the case. They will often call the same
actionPerformed method. How do we tell which button was clicked? The ActionEvent class has a
getSource() method to tell us who produced the event. We need to make the buttons data
members, not local:
Java
Page 158 - Copyright 2012 Walter Milner - all rights reserved
class MyFrame extends JFrame implements ActionListener {

JButton okButton, cancelButton;

MyFrame(String title) {
.. as before ..
okButton = new JButton("OK");
add(okButton);
okButton.setBounds(5, 30, 80, 20);
okButton.addActionListener(this);
cancelButton = new JButton("Cancel");
add(cancelButton);
cancelButton.setBounds(90, 30, 80, 20);
cancelButton.addActionListener(this);
}

public void actionPerformed(ActionEvent e) {
Object source = e.getSource();
if (source == okButton) {
System.out.println("OK");
}
if (source == cancelButton) {
System.out.println("Cancel");
}
}
}
Event handling in general
ActionEvent is a subclass of AWTEvent. This is a superclass with classes of types of events of
different kinds - for example, a MouseEvent, a MouseWheelEvent, a KeyEvent and a WindowEvent,
the latter happening when a window is closed, resized, restored and so on. These are all handled in a
similar way. Their events are passed to an object which implements the appropriate Listener
interface. A getSource() can distinguish events coming from different widgets.
Widgets actually maintain a list of objects to notify. So when a button is clicked, it can notify a set of
objects. This is why the method is addActionListener rather than setActionListener.
Two examples follow. The first outputs the x and y pixel positions of the mouse as it moves over the
frame:
class MyFrame extends JFrame implements MouseMotionListener {

MyFrame(String title) {
.. as before..
addMouseMotionListener(this);
}

public void mouseDragged(MouseEvent e) {

}

public void mouseMoved(MouseEvent e) {
System.out.println(e.getX()+ " "+e.getY());
}
}
Second example - when the window close button is clicked, the user must enter q to quit. This is a
useful approach, checking if the user really wants to quit, save work and so on:
Java
Page 159 - Copyright 2012 Walter Milner - all rights reserved
class MyFrame extends JFrame implements WindowListener {


MyFrame(String title) {
..as before..
setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
.. as before..
addWindowListener(this);
}


public void windowOpened(WindowEvent e) {
}

public void windowClosing(WindowEvent e) {
System.out.println("Enter q to quit");
Scanner scanner=new Scanner(System.in);
String s = scanner.nextLine();

if (s.equals("q"))
System.exit(0);
}

public void windowClosed(WindowEvent e) {
}


public void windowIconified(WindowEvent e) {
}


public void windowDeiconified(WindowEvent e) {
}

public void windowActivated(WindowEvent e) {
}

public void windowDeactivated(WindowEvent e) {
}
}

Using adapter classes
In the last example, the WindowListener interface has seven methods, and we are only doing
something in one of them. To make for less typing, we can use an instance of a sub-class of the
abstract WindowAdapter, just implementing the methods we want to. This is often done by making
the object to be an instance of an anonymous inner class - like this:
addWindowListener(new WindowAdapter() {

public void windowClosing(WindowEvent e) {
System.out.println("Enter q to quit");
Scanner scanner = new Scanner(System.in);
String s = scanner.nextLine();

if (s.equals("q")) {
System.exit(0);
}
}
});
This is in place of addWindowListener(this); and the frame no longer implements WindowListener.
Instead ..new WindowAdapter().. defines an anonymous sub-class of WindowAdapter, and creates
an instance of it to deal with the WindowEvents.
Java
Page 160 - Copyright 2012 Walter Milner - all rights reserved
Exercise
Program a JFrame with a JButton. When the button is clicked, the application should end.
Java
Page 161 - Copyright 2012 Walter Milner - all rights reserved
Swing containers
Swing provides various features to enable you to organise components in a frame as you want. We
look at JPanels as a basic building block, borders, the idea of a containment hierarchy, the top-level
containers, layout managers, tabbed panes and split panes.
JPanels and Borders

A JPanel is a rectangular area which can be used to divide a frame by adding the panels to the frame.
We can also add panels to panels, making the layout structure as intricate as is needed. We need to
take the layout manager into account - this is software which controls the size and position of
components. The default for a JFrame is BorderLayout, and for a JPanel, FlowLayout, which adds
components in rows. But this can be changed by setLayout().
Borders can also be added to JPanels - and most components. To get a border, use a method from
the static BorderFactory class. The idea is that if you use three thin blue borders in your application,
in fact only one will be constructed by the BorderFactory, and you will share the instances.
The example shows the use of a compound border, with the outer border being empty. This can be
used to establish 'padding' around components:
MyFrame(String title) {
super(title);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
// make panels
top = new JPanel();
bottom = new JPanel();
// set sizes
top.setPreferredSize(new Dimension(100, 100));
bottom.setPreferredSize(new Dimension(100, 100));
// add to frame
add(top, BorderLayout.NORTH);
add(bottom, BorderLayout.SOUTH);
// put labels in panels
top.add(new JLabel("Top"));
bottom.add(new JLabel("Bottom"));
// make and set borders
Border redBorder=BorderFactory.createLineBorder(Color.red, 1);
Border blankBorder=BorderFactory.createEmptyBorder(5,5,5,5);
Border joint = BorderFactory.createCompoundBorder(blankBorder, redBorder);
top.setBorder(joint);
pack();
}
Adding components to a JPanel
We can create a JPanel and add it to the window. Then we can create components and add them to
the panel (not the window):

Java
Page 162 - Copyright 2012 Walter Milner - all rights reserved
MyFrame(String title) {
.. as before..
// set up a panel on the left
JPanel yellow = new JPanel();
add(yellow);
yellow.setBounds(0,0,125,100);
yellow.setBackground(Color.YELLOW);
// add a label to it
JLabel label = new JLabel("Enter a number");
label.setBounds(5, 5, 100, 20);
yellow.add(label);
// set up a panel on the right
JPanel red = new JPanel();
add(red);
red.setBounds(125,0,125,100);
red.setBackground(Color.RED);
// add a textfield to it
JTextField textField = new JTextField("1234");
red.add(textField);
textField.setBounds(110, 5, 100, 20);
}
The Containment Hierarchy

In the above example, the JFrame contains two JPanels, because we have
added them. In turn, the left JPanel contains a JLabel, and the right
contains a JTextField.
Swing uses this concept in general, with all components being contained
in other components. Only at the top of each containment tree do we
find a top level container, which in this case is a JFrame.
Top level containers
There are three useful top level containers JFrame, JDialog and JApplet. The first we have already
seen. A JDialog is suitable for use as a dialog box and is described later . A JApplet will contain an
applet, normally inside a browser window.
There is a fourth, but it is usually excluded from the useful list. This is a
JWindow. This is a plain rectangle, with no title bar, re-sizing handles, nor
close minimize restore buttons. So not very useful.
On JDK 7, on some platforms, you can have translucent and non-
rectangular windows.
JRootPane and components
JFrame and the other top-level containers is actually slightly more
complicated than it appears. In detail,
A JFrame has a JRootPane
A JRootPane has glassPane and a Layered Pane
A LayeredPane has a contentPane, and maybe a MenuBar
Usually we are only interested in the contentPane -the area inside the window where things will be
shown. When we place a JLabel in a JFrame, it is added to the contentPane:
Containment hierarchy
JRootPane and elements
Java
Page 163 - Copyright 2012 Walter Milner - all rights reserved
frame.getContentPane().add(label);
Since this is so common, the add method of JFrame does this for you, so you can just say
frame.add(label);
with the same effect.
Menu bars are easy to use - they are described elsewhere.
The glassPane usually does nothing. It can be used to intercept mouse events before they reach the
frame components, and you can draw on the glassPane (and therefore over frame components),
provided you make it visible.
Using the glassPane
For example, the following gets the glassPane, and makes it intercept
mouse movements. In response it draws on the glassPane tracking
the mouse. The mouse events interception only works if the
glassPane is setVisible(); which might not be expected:
class MyFrame extends JFrame implements MouseMotionListener {

Component glassPane;

MyFrame(String title) {
..as before..
glassPane = getGlassPane();
glassPane.setVisible(true);
glassPane.addMouseMotionListener(this);
}
public void mouseDragged(MouseEvent e) {
}

int lastMouseX = -1;
int lastMouseY = -1;

public void mouseMoved(MouseEvent e) {
int mouseX = e.getX(); // where's the mouse
int mouseY = e.getY();
if (lastMouseX == -1) { // if first time, last mouse is here as well
lastMouseX = mouseX;
}
if (lastMouseY == -1) {
lastMouseY = mouseY;
}
Graphics g = glassPane.getGraphics(); // get a graphics context
g.drawLine(lastMouseX, lastMouseY, mouseX, mouseY);
lastMouseX = mouseX; //ready for next time
lastMouseY = mouseY;
}
}

This consumes the mouse event, and the underlying button does not receive it. If you want to pass it
on, you have to work out if the mouse is over the button, and if so, construct a suitable event and
send it on. See
http://download.oracle.com/javase/tutorial/uiswing/components/rootpane.html
Drawing on the glassPane
Java
Page 164 - Copyright 2012 Walter Milner - all rights reserved

Layout Managers
Previously we have used setBounds() to position components with pixel co-ordinates and sizes. This
is not recommended. The size of a pixel depends on the resolution of the display, and so your
components will be smaller on a higher resolution screen. Instead it is better to use a
LayoutManager. There is a choice of these, and they place components in different patterns - or you
can write your own. We will just look at two.
BorderLayout
This is the default for a JFrame. Components can be placed in one of five
positions, named north south east west and center. For example:
class MyFrame extends JFrame {

MyFrame(String title) {
super(title);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
JButton okButton = new JButton("OK");
add(okButton, BorderLayout.WEST);
JButton cancelButton = new JButton("Cancel");
add(cancelButton, BorderLayout.EAST);
pack();
}
}
We have not set a layout manager, so we get the default BorderLayout. We have not sized the frame
or the components, but we have called pack(). This calculates the "preferred sizes" of the
components, sizes them to that, positions them, and calculates the minimum size of the frame.
The five locations may seem to be limiting. But you can add panels to the frame, then components
to the panels, and so on.
GridBagLayout
Some say GridBagLayout is one of the more complicated layout managers,
but it is very flexible and effective. Components are placed in cells in rows
and columns. You use an instance of GridBagConstraints when you add a
component. This has fields gridx and gridy which fix which column and row
it goes in - top left cell is (0,0). You can fix the alignment with .anchor EAST or WEST and so on. For a
large component, you can make it use more than one row or column using gridWidth or gridHeight.
And you can space out components using insets. For example:
setLayout(new GridBagLayout());
GridBagConstraints gc = new GridBagConstraints();
gc.insets = new Insets(5, 5, 5, 5);// everything has a 5 pixel border
JLabel label1 = new JLabel("Name");
gc.gridx = 0; // top left
gc.gridy = 0;
gc.anchor = GridBagConstraints.EAST; // aligned right
add(label1, gc); // add it

The whole thing is:
Using BorderLayout
GridBagLayout
Java
Page 165 - Copyright 2012 Walter Milner - all rights reserved
MyFrame(String title) {
super(title);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
setLayout(new GridBagLayout());
GridBagConstraints gc = new GridBagConstraints();
gc.insets = new Insets(5, 5, 5, 5);
// top row
JLabel label1 = new JLabel("Name");
gc.gridx = 0;
gc.gridy = 0;
gc.anchor = GridBagConstraints.EAST;
add(label1, gc);
JTextField name = new JTextField("");
name.setPreferredSize(new Dimension(100, 20));
gc.gridx = 1;
gc.gridy = 0;
gc.anchor = GridBagConstraints.WEST;
add(name, gc);
// row 2
JLabel label2 = new JLabel("Date of birth");
gc.gridx = 0;
gc.gridy = 1;
gc.anchor = GridBagConstraints.EAST;
add(label2, gc);
JTextField dob = new JTextField("");
dob.setPreferredSize(new Dimension(100, 20));
gc.gridx = 1;
gc.gridy = 1;
gc.anchor = GridBagConstraints.WEST;
add(dob, gc);
JButton okButton = new JButton("OK");
gc.gridx = 0;
gc.gridy = 2;
// row 3
gc.anchor = GridBagConstraints.CENTER;
add(okButton, gc);
JButton cancelButton = new JButton("Cancel");
gc.gridx = 1;
gc.gridy = 2;
gc.anchor = GridBagConstraints.CENTER;
add(cancelButton, gc);
pack();

}
JTabbedPane

A tabbed pane produces a set of panes accessible via a 'tab'. This
means that a lot of interface can be there in a small area - though
you can't see more than one at a time.
The sequence is simply:
1. Construct a JTabbedPane
2. Construct components, and add them as tabs to the tabbed pane. These might be JPanels
3. Add the Tabbed pane to the outer container.
For example:
JTabbedPane
Java
Page 166 - Copyright 2012 Walter Milner - all rights reserved
JTabbedPane tabbedPane = new JTabbedPane(JTabbedPane.TOP);
JPanel panel1 = new JPanel();
tabbedPane.addTab("One", panel1);
JPanel panel2 = new JPanel();
tabbedPane.addTab("Two", panel2);
..
add(tabbedPane);
and of course you would add components to the panels.
As well as text labels for tabs, you can have icons as well. So if 'one' is an
ImageIcon, you can say
tabbedPane.addTab("",one, panel1);
and so on.



JSplitPane
A JSplitPane object does what the name suggests - it splits a container
into two parts, and has the functionality to allow the user to control the
split. You would typically:
1. Make the things which would be the left and right components -
typically, JPanels. You would probably add components to those two
panels.
2. Construct the JSplitPane, with the two panels as arguments.
3. Add the JSplitPane to the enclosing container - the one you are splitting.
For example - the left component will be a scroll pane enclosing a JList
JScrollPane listScroller = new JScrollPane(list);
and the right is just a JPanel:
JPanel rightPane = new JPanel();
rightPane.setBackground(Color.yellow);
JLabel lab1= new JLabel("Right pane");
rightPane.add(lab1);
Then make the split pane:
JSplitPane splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, listScroller, rightPane);
and add it - this is in the constructor of a subclassed JFrame:
add(splitPane);
Some code configures this, with obvious meaning:
Icons for tab labels
JSplitPane
Java
Page 167 - Copyright 2012 Walter Milner - all rights reserved
splitPane.setOneTouchExpandable(true);
splitPane.setDividerLocation(150);
Dimension minimumSize = new Dimension(100, 50);
listScroller.setMinimumSize(minimumSize);
rightPane.setMinimumSize(minimumSize);
For a three-way split, nest them. For example, you might split a frame vertically, then split the top
pane horizontally.
Exercise
Program a JFrame which has 2 panels, left and right. Use MouseMotionListener so the user can draw
freehand lines on the right panel. The left panel should have a JButton saying 'Clear', which when
clicked will remove the drawing on the right.

Java
Page 168 - Copyright 2012 Walter Milner - all rights reserved
Swing widgets
These are the things which are placed on the containers, and most of them react to user actions.
They include
JLabel A label - text (or image) which the user cannot change
JTextField A box in which the user can type text input
JTextArea Like a JTextField with more than one row
JButton A clickable button
JCheckBox A small box for yes or no
JRadioButton These come in groups - only one out of the group is selected
JList, JComboBox,
JTable
See later.
JLabel
For example
class MyFrame extends JFrame {

JLabel label = new JLabel("Label here");

MyFrame(String title) {
..
setLayout(null);
add(label);
label.setBounds(5, 5, 100, 20);
label.setForeground(Color.red);

}
}

JTextField and JButton
class MyFrame extends JFrame implements ActionListener {
JTextField textField = new JTextField("Type here");
JButton button = new JButton("Click me");

MyFrame(String title) {
..
setLayout(null);
add(textField);
textField.setBounds(5, 5, 100, 20);
add(button);
button.setBounds(5,30,100,20);
button.addActionListener(this);

}


public void actionPerformed(ActionEvent e) {
String text = textField.getText();
JOptionPane.showMessageDialog(null, text,"You typed..", JOptionPane.INFORMATION_MESSAGE);
}
}
This repeats how you use ActionListener and actionPerformed to respond to button clicks. Use
getText() to retrieve the text from a JTextField. JOptionPane displays a message in a dialog box.
Java
Page 169 - Copyright 2012 Walter Milner - all rights reserved

JCheckBox
For example:
class MyFrame extends JFrame implements ActionListener {

JCheckBox check = new JCheckBox("Check");

MyFrame(String title) {
..
setLayout(null);
add(check);
check.setBounds(5, 30, 100, 20);
check.addActionListener(this);
}

public void actionPerformed(ActionEvent e) {
boolean state = check.isSelected();
JOptionPane.showMessageDialog(null, "" + state, "CheckBox selected?",
JOptionPane.INFORMATION_MESSAGE);
}
}
JRadioButton
This is slightly different in that you have to add them to a ButtonGroup:
class MyFrame extends JFrame implements ActionListener {

JRadioButton but1 = new JRadioButton("One");
JRadioButton but2 = new JRadioButton("Two");
JRadioButton but3 = new JRadioButton("Three");

MyFrame(String title) {
..
setLayout(null);

add(but1);
but1.setBounds(5, 5, 100, 20);
but1.addActionListener(this);
add(but2);
but2.setBounds(5, 30, 100, 20);
but2.addActionListener(this);
add(but3);
but3.setBounds(5, 55, 100, 20);
but3.addActionListener(this);
ButtonGroup group = new ButtonGroup();
group.add(but1);
group.add(but2);
group.add(but3);

}

public void actionPerformed(ActionEvent e) {
JRadioButton but = (JRadioButton) e.getSource();
JOptionPane.showMessageDialog(null, but.getText(), "You chose..",
JOptionPane.INFORMATION_MESSAGE);
}
}
Java
Page 170 - Copyright 2012 Walter Milner - all rights reserved
Images
Swing has a class called ImageIcon which can be used to place images on
labels and other components. For example:
MyFrame(String title) {
super(title);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
ImageIcon icon = new ImageIcon("c:/temp/baby.jpg");
JLabel label = new JLabel(icon);
add(label);
pack();
}
This is very simple, but there is a problem in that an absolute pathname to the image file is given.
The code above works if the file is in the folder called temp on drive c - but in a typical deployment
of an application, you cannot place a file in a fixed folder on the user's
computer. We need to be able to somehow place the file in the application
and refer to it there.
There are three steps to this:
1. Place the image file in a suitable folder within the folder holding the
source code .java files for the relevant package. For example, this is in a
package called test, so we could place the image in a sub-folder of test called images.
2. Use a classloader to get the location relative to where the class files will be loaded from:
package test;

import ..

class Test {

public static void main(String[] args) {
..
}
..
}

class MyFrame extends JFrame {

JPanel top, bottom;

MyFrame(String title) {
super(title);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
ClassLoader cldr = this.getClass().getClassLoader();
java.net.URL imageURL = cldr.getResource("test/images/baby.jpg");
ImageIcon icon = new ImageIcon(imageURL);
JLabel label = new JLabel(icon);
add(label);
pack();
}
}
Here, cldr is the class loader which will load the MyFrame class file. Its getResource method gets a
location URL for the file named baby.jpg, in the folder called images in the package called test.
Image on label
Source code image placement in NetBeans
Folders after compiling
Java
Page 171 - Copyright 2012 Walter Milner - all rights reserved
3. When this is compiled (or Run in NetBeans), in the classes folder of the build folder, there will be
a folder named test to hold the package, and it will contain the class file, and a sub-folder called
image with the image file in it.
If this is jar'd (in NetBeans, Run Clean and Build) this produces a .jar file (in NetBeans, in the dist
folder) which contains the image file.
Images from the net
Alternatively, image files can be downloaded from the net, very simply:
class MyFrame extends JFrame {

MyFrame(String title) {
..
try {
URL imageURL = new URL("http://p.ebaystatic.com/aw/pics/logos/logoEbay_x45.gif");
ImageIcon icon = new ImageIcon(imageURL);
JLabel label = new JLabel(icon);
add(label);
}
catch (MalformedURLException ex) {
}
pack();
}
}
Exercise
Extend this to a small 'image gallery' with 3 or 4 images. One solution would be to have a
corresponding set of JLabels. 'Next' and 'Previous' buttons would change the setBounds of the labels
so the appropriate one was visible.

Image from the net
Java
Page 172 - Copyright 2012 Walter Milner - all rights reserved
Color
Color is a class, with objects representing colours. We can
construct a new colour by supplying red, green and blue
components as floats in the range 0 to 1, like
Color c = new Color(1.0f, 0.5f, 0.1f);
1.0f is a float constant, while 1.0 is type double.
Or there are a set of constant named colours, like
Color c = Color.GREEN;
Swing components have methods setBackground and setForeground to set the colours (not all
components have backgrounds and foregrounds). For example:
class MyFrame extends JFrame {

MyFrame(String title) {
.. as before ..
JLabel label = new JLabel("Enter a number");
add(label);
Color c1 = new Color(1.0f, 0.5f, 0.1f);
label.setForeground(c1);
label.setBounds(5, 5, 100, 20);
JTextField textField = new JTextField("1234");
Color c2 = Color.GREEN;
textField.setBackground(c2);
add(textField);
textField.setBounds(110, 5, 100, 20);
}
}
Exercise
A JFrame can be translucent provided-
1. The underlying OS allows it
2. The window is setUndecorated(true); before being made visible.
3. It is not full-screen
Then the opacity is set by setOpacity(float);
Try this out.
Using Color
Java
Page 173 - Copyright 2012 Walter Milner - all rights reserved
Fonts
An instance of the Font class represents a font. The main issue is that fonts are installed locally, so
there is no guarantee that a specific font will be available. This is addressed by having two kinds -
'logical' and 'physical'. The logical fonts are a basic set of generic fonts - Dialog, DialogInput,
Monospaced, Serif and SansSerif, while the physical fonts are actual fonts installed on the user's
machine. You can instantiate one of the logical fonts as in this example:
Font font = new Font("Dialog", Font.PLAIN, 12);
and then use the setFont method to apply it to a component, such as
label.setFont(font);
The same is true of the physical fonts, but you have to ensure that the font you want is actually
available. A reasonable approach is to have a set of fonts which you would prefer to use, in order,
and use a logical font as the fallback if none are present - as usual in a style sheet on a web page. For
example:
GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
String fontName = "SansSerif";
String f[] = ge.getAvailableFontFamilyNames();
String[] wantedFonts = {"Code2000","Linux Libertine","DejaVu Sans" };

boolean gotFont = false;
for (int j = 0; j < wantedFonts.length; j++) {
for (int i = 0; i < f.length; i++) {
if (f[i].equals(wantedFonts[j])) {
fontName = wantedFonts[j];
gotFont = true;
break;
}
}
if (gotFont) break;
}
Font font = new Font(fontName, Font.PLAIN, 16);
JLabel label = new JLabel(" in " + fontName);
label.setFont(font);
add(label);
This example shows two other points. Firstly, since Java uses Unicode for characters and strings, it
can display a very large set of characters - although the range of displayable characters depends on
the font.
Secondly, such characters can be used in source code for identifiers and string constants. Whether
you can see them depends on which font your editor uses in your IDE - which will be an option you
can change. Otherwise you can represent Unicode characters as constants like \u0061 for lower case
'a'.
Exercise
Try this out.
Try different fonts.
Unicode font
Java
Page 174 - Copyright 2012 Walter Milner - all rights reserved
Menus, Popups andToolbars

Making a basic menu
Follow these steps
1. Make a menubar, and add it to the frame (or whatever)
2. Make a menu, and add it to the menubar
3. Make menu items, and add them to the menu
Repeat steps two and three for as many menus as you want.
For example:
JMenuBar menuBar = new JMenuBar();
setJMenuBar(menuBar);
JMenu menu1 = new JMenu("Menu One");
menuBar.add(menu1);
JMenuItem item1 = new JMenuItem("Option One");
menu1.add(item1);
JMenuItem item2 = new JMenuItem("Option Two");
menu1.add(item2);
JMenu menu2 = new JMenu("Menu Two");
menuBar.add(menu2);
JMenuItem item3 = new JMenuItem("Option Three");
menu2.add(item3);
JMenuItem item4 = new JMenuItem("Option Four");
menu2.add(item4);
Making the menu work
JMenuItems are in fact sub-classed JButtons, and so they use the ActionListener interface and you
can treat them like ordinary buttons. This means your JMenuItems would need to be data fields not
local to the constructor, so the actionPerformed can refer to them. So we modify the above:
..
item1 = new JMenuItem("Option One");
menu1.add(item1);
item1.addActionListener(this);
..

public void actionPerformed(ActionEvent e) {
Object source = e.getSource();
if (source==item1)
.. whatever
}

Elaborating Menus
You can add menuItems to menu bars. Or you can add menus to menus,
giving submenus.
You can have icons as well as text labels in menuItems.
You can have a menu separator.
Basic menu
Elaborated menu
Java
Page 175 - Copyright 2012 Walter Milner - all rights reserved
You can have checkboxes and radio buttons in menus.
For example, where 'one' is an ImageIcon:
JMenuBar menuBar = new JMenuBar();
setJMenuBar(menuBar);
JMenu menu1 = new JMenu("Menu One");
menuBar.add(menu1);
item1 = new JMenuItem("Option One");
menu1.add(item1);
item1.addActionListener(this);
JMenuItem item2 = new JMenuItem("Option Two", two);
menu1.addSeparator();
menu1.add(item2);
JCheckBox cb = new JCheckBox("Yes or no");
menu1.add(cb);
Popup Menus
Popup menus, which appear floating somewhere in a frame (uually where the mouse was clicked)
are excellent. They involve less mouse movement than having to go up to the menu bar, and they
can be context-dependent - that is, if the user right-clicks on a particular thing, they get a menu just
relevant to that thing.
You make a popup menu and add items to it very simply:
popup = new JPopupMenu();
JMenuItem menuItem = new JMenuItem("A popup menu item");
popup.add(menuItem);
JMenuItem menuItem2 = new JMenuItem("Another popup menu item");
popup.add(menuItem2);
To make it work, you have to do two things - get the menu to pop up, and get responses to menu
selections. The first is done using a mouse listener. For example:
addMouseListener(this);
..

public void mouseClicked(MouseEvent e) {
if (e.getButton() == MouseEvent.BUTTON3) {
popup.show(e.getComponent(),
e.getX(), e.getY());
}
}
which means the popup appears if they right-click. The e.getX() and e.getY mean the menu will
appear where they clicked.
To make the menu work - the JMenuItems are subclassed JButtons, so use actionListener just as for
menu bars.
Menu design issues
Users often complain they cannot 'find' things. This happens when there is a large and complex
menu, with many levels, and items are not logically placed. For example, in Word 2003 and before
you inserted a header through View in the menu, which is hardly logical.
Some suggestions are:
Java
Page 176 - Copyright 2012 Walter Milner - all rights reserved
1. Order top level items as expected - File Edit ..Help. In File have New, Open, Save, Save as, Close
and Exit. This obviously depends on the application, but keep it as close to this - which users will
expect - as possible.
2. Use separators to group items logically.
3. If your menus are four deep - find another way.
ToolBars

Toolbars are rows of buttons, which can 'float' in their own window, or will 'dock' at the edge of a
container. Instantiate a JToolBar, make and add JButtons to it, then add the toolbar to a container
using BorderLayout. The JButtons would normally show icons, but text is possible. The JButtons use
actionPerformed. For example:
ClassLoader cldr = this.getClass().getClassLoader();
java.net.URL imageURL = cldr.getResource("test/images/Edit24.gif");
ImageIcon one = new ImageIcon(imageURL);
..
JToolBar toolBar = new JToolBar("Tools");
JButton butt1 = new JButton(one);
..
toolBar.add(butt1);
..
add(toolBar, BorderLayout.NORTH);






Initial toolbar
Docked on the left
Dragged to new window
Java
Page 177 - Copyright 2012 Walter Milner - all rights reserved
Swing and MVC
Widgets hold data. For some, the data is very simple. For a JCheckBox, it is little more than whether
it has been checked. For a textfield, it is the text in it. But for others - such as lists, comboboxes and
tables - they hold an amount of structured data. How to deal with this?
One idea is MVC : model - view - controller. The model is the underlying data which the widget has -
as distinct from how it is seen on screen. The view is the screen appearance of the widget and its
data. The controller is the coding which determines how user input alters the data and view.
There is some debate about whether Swing widgets are MVC-based. This
article from Oracle:
http://java.sun.com/products/jfc/tsc/articles/architecture/
shows that the design started as MVC, and developed from there.
JLists
A JList displays a list of items from which a choice can be made. The list
shown was produced by this code:
setLayout(null);
String[] data = {"one", "two", "three", "four", "five", "six"};
JList list = new JList(data);
list.setSelectionMode(ListSelectionModel.SINGLE_INTERVAL_SELECTION);
list.setLayoutOrientation(JList.VERTICAL_WRAP);
list.setVisibleRowCount(-1);
JScrollPane listScroller = new JScrollPane(list);
listScroller.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
add(listScroller, BorderLayout.CENTER);
listScroller.setBounds(20, 20, 100, 120);
There are three aspects to JLists:
1. How the data in the list is controlled : the model
2. How the list, and cells in it, are displayed : the view
3. How items are selected : view/controller
4. How events are handled
The JList models
It seems as if the data is somehow 'in' the list. In fact the data is held in a
separate object. If you construct the list with an array or Vector as constructor
argument, the JList makes the data model for you, as an instance of class
DefaultListModel. For example
Vector<Integer> numbers = new Vector<Integer>();
numbers.add(new Integer(1));
numbers.add(new Integer(41));
numbers.add(new Integer(1));
JList list = new JList(numbers);
A JList
Vector as model
Java
Page 178 - Copyright 2012 Walter Milner - all rights reserved
However in this simple case the model is fixed - you cannot add or remove items
from the list.
An alternative is to construct an instance of DefaultListModel, and construct the
JList with that as parameter:
DefaultListModel<String> model = new DefaultListModel<String>();
model.addElement("One");
model.addElement("Two");
model.addElement("Three");
JList list = new JList(model);
..
JScrollPane listScroller = new JScrollPane(list);
add(listScroller);
model.addElement("Four");
This shows how the data can be changed after the list is created, and the visual display is updated to
reflect the change.
Thirdly you can construct a JList based on an object which implements the ListModel interface. This
can be a sub-class of the AbstractListModel class, or your own class which implements ListModel.
For example, wrapping an ArrayList of Strings:
class MyListModel extends AbstractListModel
{
private ArrayList<String> data;
MyListModel(ArrayList<String> data)
{
this.data=data;
}
void addElement(String s)
{
data.add(s);
}
@Override
public int getSize() {
return data.size();
}
@Override
public Object getElementAt(int index) {
return data.get(index);
}
}
used as:
ArrayList<String> data = new ArrayList<String>();
data.add("One"); data.add("Two"); data.add("Three");
MyListModel model = new MyListModel(data);
JList list = new JList(model);
..
JScrollPane listScroller = new JScrollPane(list);
..
model.addElement("Four");
JList appearance and CellRenderer
There are three possible ways in which cells are laid out in a JList. The default is a simple vertical list.
VERTICAL_WRAP means list vertically, and start a new colum to the right if needed.
HORIZONTAL_WRAP means list horizontally, and start a new row if needed. These are selected by
for example
DefaultListModel
A sub-classed
AbstractListModel
Java
Page 179 - Copyright 2012 Walter Milner - all rights reserved
list.setLayoutOrientation(JList.HORIZONTAL_WRAP);


VERTICAL VERTICAL_WRAP HORIZONTAL_WRAP

It is also possible to create a cell renderer to draw cells other than in the default way. This is done by
implementing the ListCellRenderer interface. An instance of this is called by the list when it needs to
draw a cell. The renderer must return a component suitable for use as a cell.
In the example, the component is a sub-classed JLabel. The method passes in
parameters for the value of the data in the cell, its index, and whether the cell
is selected or has the focus. This means the cell can get suitable formatting. In
the example screen shot, cells 2 and 3 are selected, and cell 3 has the focus:
..
list.setCellRenderer(new MyCellRenderer());
..
class MyCellRenderer extends JLabel implements ListCellRenderer
{
static Border b= BorderFactory.createLineBorder(Color.blue, 1);
MyCellRenderer()
{
setOpaque(true);
}
@Override
public Component getListCellRendererComponent(JList list, Object value, int index,
boolean isSelected, boolean cellHasFocus) {
setText(value.toString());
setBackground(new Color(index*80%256,0,0));
if (isSelected) setBackground(Color.pink);
if (cellHasFocus)setBorder(b);
else setBorder(null);
setForeground(Color.white);
return this;
}
}
Just as the data in the list is held in a list model, those items which are selected are held by a
ListSelectionModel. You could write your own, but the interface has many methods. Instead the
default one will probably suffice. setSelectionMode controls whether the user can select one item, a
range, or several ranges. Get and setSelectedIndices allow you to get an array of indexes of items
which are selected, or to select such a set.
When the user changes the selection, a ListSelectionEvent is produced. The ListSelectionListener has
just one method, value changed. For example, to output on the console all selected items when
there is any change:
Cell renderer
Java
Page 180 - Copyright 2012 Walter Milner - all rights reserved
..
list.addListSelectionListener(this);
..

public void valueChanged(ListSelectionEvent e) {
if (e.getValueIsAdjusting() == false) {
int[] selected = list.getSelectedIndices();
for (int i = 0; i < selected.length; i++) {
System.out.println(list.getModel().getElementAt(selected[i]));
}
}
}
To explain the println,
list.getModel(). gets the data in the list
.getElementAt gets one item from the data
(selected[i])); is the index of the ith. item selected
For example, if items 0,3 and 9 were selected, the select array would have elements 0 3 and 9.
Exercise
Code and test a basic JList containing Integers
Write a cell renderer so that cells containg 10 or more are in pink, and the selected cell is red.
JList as MVC
A Jlist actually has three associated objects
(which may be defaults or ones we have written)
- the list model, the selection model and the cell
renderer. There is also likely to be a
valueChanged method somewhere which
responds to selection changes. The diagram casts
these into the MVC architecture. There is no
precision about this. The important point is that
the model holds the 'real'
underlying data, and the view
shows this on screen
JList as MVC
Java
Page 181 - Copyright 2012 Walter Milner - all rights reserved
Inheritance - a GUI Tic Tac Toe
Suppose we want to a game of Tic Tac Toe in a GUI context, like:
The user will click on a cell to 'go' there. So the cells are like buttons - but with extra, since each cell
somehow has to know which row and column it is in. The easiest way to program this is to start with
an existing class, in this case a JButton, and extend it by using the idea of inheritance. Similarly the
main window of the game will be an extension of the basic JFrame.
The idea of inheritance is to take an existing class, called the base class or super class, and extend or
subclass it to produce a modified class. The modified class inherits all members (fields and methods)
of the base class. However these can be altered, or we can add extra members. Constructors are not
inherited - we have to write our own constructor for the sub-class. However we can call super(); as
the first statement in the constructor, and this calls the constructor of the super class, doing most of
the work for us.
The idea of inheritance is to re-use code - existing code can easily be re-used and built upon.
Dynamics of GUI apps
The character-based Tic Tac Toe game illustrated how such applications execute. There is some
output, then the screen is refreshed. This loop is repeated until somehow it ends.
In a GUI app, the user expects a lot more freedom. In the middle of the game they might resize or
minimise it, or switch to a different application for a while.
This means a different approach is needed. The application needs to somehow set up an initial
screen (normally a window). It must then 'sit back' and wait for the user to do things, and respond
appropriately. In other words it must set up event-handlers to deal with user-initiated events.
Most of those (moving the window, re-sizing it, minimizing and restoring it) are handled by existing
methods in the base class (the JFrame). The event we do need to handle is a click on one of the cells.
Class design in a GUI context
The classes in this app can be a modification of those in the character-based version:
Game - to contain main, and start things off.
Board - to represent the board on which the game is played. This will be a sub-classed JFrame
Human - the human player
Computer - the computer player
Cell - a sub-classed JButton, one of the 9 cells in the game.
Java
Page 182 - Copyright 2012 Walter Milner - all rights reserved
These are all singleton classes except for Cell, which will have 9 instances.
The Game class
package GUIttt;

public class Game {

// data fields
private Board board;
private Human human;
private Computer computer;

// constructor
private Game() {
// create the 3 objects which are part of a Game object
human = new Human();
computer = new Computer();
board = new Board(human,computer);

computer.setBoard(board);
}

public static void main(String[] args) {
Game game = new Game(); //make a game
}
}
This instantiates a single Game object. This just creates the human, computer and board objects. The
board needs references to the human and the computer, so it can give them a go. The computer
needs a reference to the board so it can check which cells are free.
There is no turn-taking in this. That is effectively handled by the board.
The Board class
A key data field of the board class is a 3 by 3 array of TTTCells. These are sub-classed JButtons. When
the user clicks on one of these, the actionPerformed method is triggered. This makes one turn to
happen - the user's go is marked, we check if they've won, the computer goes, we check if they've
won. Then the turn ends.

Java
Page 183 - Copyright 2012 Walter Milner - all rights reserved
package GUIttt;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JFrame;
import javax.swing.JLabel;

class Board extends JFrame implements ActionListener {

// data members
private TTTCell cells[][] = new TTTCell[3][3];
private Human human;
private Computer computer;
private JLabel label;
private boolean gameOver;
// construct a board

Board(Human human, Computer computer) {
// construct base class
super("Tic Tac Toe");
setBounds(50, 50, 220, 230);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);

this.human = human;
this.computer = computer;
gameOver = false;
// create cell grid
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
cells[i][j] = new TTTCell();
cells[i][j].addActionListener(this);
}
}
// add and position cells
setLayout(null);
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
add(cells[i][j]);
cells[i][j].setBounds(50 * i, 50 * j, 50, 50);
}

}
label = new JLabel();
add(label);
label.setBounds(0, 150, 150, 20);
}

public void actionPerformed(ActionEvent e) {
if (!gameOver) {
human.go(e);
checkWin('X');
computer.go();
checkWin('O');
}
}

// mark an 'X' or 'O'
void set(int i, int j, char c) {
// check is valid
if (i > -1 && i < 3 && j > -1 && j < 3 && (c == 'O' || c == 'X')) {
cells[i][j].setContents(c);
}
}

char getCell(int r, int c) {
return cells[r][c].getContents();
}

// set gameOver if someone's won
void checkWin(char c) {
boolean result = false;

//check rows
Java
Page 184 - Copyright 2012 Walter Milner - all rights reserved
if (cells[0][0].getContents() == c && cells[0][1].getContents() == c &&
cells[0][2].getContents() == c) {
result = true;
}
if (cells[1][0].getContents() == c && cells[1][1].getContents() == c &&
cells[1][2].getContents() == c) {
result = true;
}
if (cells[2][0].getContents() == c && cells[2][1].getContents() == c &&
cells[2][2].getContents() == c) {
result = true;
}
//check columns
if (cells[0][0].getContents() == c && cells[1][0].getContents() == c &&
cells[2][0].getContents() == c) {
result = true;
}
if (cells[0][1].getContents() == c && cells[1][1].getContents() == c &&
cells[2][2].getContents() == c) {
result = true;
}
if (cells[0][2].getContents() == c && cells[1][2].getContents() == c &&
cells[2][2].getContents() == c) {
result = true;
}
// leading diagonal
if (cells[0][0].getContents() == c && cells[1][1].getContents() == c &&
cells[2][2].getContents() == c) {
result = true;
}
//other diagonal
if (cells[0][2].getContents() == c && cells[1][1].getContents() == c &&
cells[2][0].getContents() == c) {
result = true;
}
if (result) {
{
gameOver = true;
label.setText("Game over");

}
}

}


}
The Human class
package GUIttt;

import java.awt.event.ActionEvent;

class Human {
//invoked when human clicks a cell
void go(ActionEvent e) {
TTTCell whichCell = (TTTCell) (e.getSource());
whichCell.setContents('X');

}
}
The single method in this, go, is called when a Cell is clicked. From that event-handler, an
ActionEvent object is passed. This has a getSource method - we can use it to find out which cell was
clicked. We then set that to an X. The board checks if we have won.

Java
Page 185 - Copyright 2012 Walter Milner - all rights reserved
The Computer class
package GUIttt;

class Computer {

private Board board;

void setBoard(Board board) {
this.board = board;
}

void go() {
// at random, find a space
int row = (int) (Math.random() * 3);
int col = (int) (Math.random() * 3);
while (board.getCell(row, col) != ' ') {
row = (int) (Math.random() * 3);
col = (int) (Math.random() * 3);
}
// and put an O there
board.set(row, col, 'O');
}
}
This still uses the dumb method of going at random to a blank cell.
The Cell class
package GUIttt;

import javax.swing.JButton;

class TTTCell extends JButton {

private char contents;

void setContents(char c) {
contents = c;
setText("" + contents);
}

char getContents() {
return contents;
}

TTTCell() {
super();
contents = ' ';
setText("" + contents);

}
}
This is a sub-classed JButton, with an extra field, contents, which is just a single character. The
setText metod of a JButton sets the text displayed on the button.
There is also a getText method. So we could have done without contents, and remembered the O or
X as the text on the button. However it is preferable to store that separately as the actual data, and
have the button text reflect that data, rather than being it.

Java
Page 186 - Copyright 2012 Walter Milner - all rights reserved
Java 2D
This section is about the Java 2D classes providing support for basic graphics in 2 dimensions in a
Swing context. It also intriduces some basic graphics concepts.
Co-ordinates
Positions on a graph, or on a map, are located by co-
ordinates - how far across (x or East) and how far up (y or
North). Computer graphics usually measure x across and y
down, and this is the case for Java 2d graphics.
Care needs to be taken over where the origin (0,0) is. This
might be the top left of the screen (or printer, or in
general, device co-ordinates), or the top left of the
container you are drawing in. The units are usually pixels -
the size of which depends on the resolution.
Graphics Context
Graphics can be displayed in different colours, fonts, fill patterns, line styles and so on. One
approach would be to use parameters to specify each of these for each thing drawn. Alternatively a
data structure called a graphics context can hold the current values for these, and drawing
operations use these values. To draw a new object in a different colour, the colour of the graphics
context is used, which is applicable until it is changed again.
Because this approach is used by the underlying OS, Java also uses it. There is an abstract class called
Graphics, instances of which represent a graphics context. We will use the Graphics2D class, which is
a concrete class which extends Graphics to provide more facilities.
A First Graphics Program
public class Main extends JFrame {

Main() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(50, 50, 200, 200);
setVisible(true);
}

public void paint(Graphics g) {
Graphics2D g2=(Graphics2D) g;
Line2D.Double myLine = new Line2D.Double(0,0,100,100);
g2.draw(myLine);
}

public static void main(String[] args) {
Main main = new Main();
}
}
main constructs an instance of Main, which is a sub-classed JFrame. The constructor sets the close
operation, the frame size and position (in screen co-ordinates), and makes it visible. The paint
method (described next) gets a Graphics2D instnce, makes a line object, and draws it. The result is
shown here. Note the top left (0,0) of the line is under the JFrame title bar.
Java
Page 187 - Copyright 2012 Walter Milner - all rights reserved
Paint
Graphics on a window is usually divided into two parts - a static background and a changing
foreground. The static background has to be drawn when the window first appears, when it is
restored from minimisation, and when it is revealed after being obscured by an over-lapping
window. The changing foreground needs to be re-drawn (if ever) when the user does something, or
at short time intervals for animation.
Drawing the static background is done by the paint method, which the system invokes whenever it
needs to. Usually our program does not call paint - the system calls it when needed. This means it is
a call-back method.In the first program we have coded the paint method, so the line is drawn when,
for example, the window is restored.
Exercise
Run this program. See the line is re-drawn after a window restore.
Change it as follows
public class Main extends JFrame {

Main() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(50, 50, 200, 200);
setVisible(true);
reDraw();
}

void reDraw()
{
Graphics2D g2=(Graphics2D) getGraphics();
Line2D.Double myLine = new Line2D.Double(0,0,100,100);
g2.draw(myLine);
}

public void paint(Graphics g) {
}

public static void main(String[] args) {
Main main = new Main();
}
}
Now what happens when the window is restored?
Why?
Simple animation
The other end of the spectrum of the paint idea, which is a fixed drawing, is animation. To do this,
we need to re-draw something at frequent intervals. This requires some kind of timer which will
repeatedly trigger the drawing - like the following. This has a draw method, which just draws a line,
then alters a data member called lineEnd which changes the end of the line. The Animator object has
the timer which invokes the draw method.
Java
Page 188 - Copyright 2012 Walter Milner - all rights reserved
class Main extends JFrame {

Animator animator;
int lineEnd=50;
Main() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(50, 50, 200, 200);
setVisible(true);
animator = new Animator(this);
}

void draw()
{
Graphics2D g2 = (Graphics2D)getGraphics();
Line2D.Double myLine = new Line2D.Double(0, 0, lineEnd, 100);
g2.draw(myLine);
lineEnd++;
}

public static void main(String[] args) {
Main main = new Main();
}
}
The Animator class is:
class Animator implements ActionListener {

Main main;

Animator(Main main) {
this.main = main;
Timer timer=new Timer(100, this);
timer.start();
}

public void actionPerformed(ActionEvent evt) {
main.draw();
}
}
This centers around the Timer class (part of Swing - there are other Timer classes). The constructor
of a Timer object takes two parameters. The first is a time delay in milliseconds, which is how often
the timer triggers. The second is a reference to an object which implements the ActionListener
interface - often used as a button event-listener. In this situation, the actionPerformed method is
called every time the timer triggers. Here that method just calls the draw method of the window
object.
Exercise
Run this program.
Experiment with the animation, including changing the time delay.
Can you add buttons to the window to start, stop and reset the animation? Main would need to
implement ActionListener as well.
The Java 2D API
The Java 2D API covers
Drawing graphics primitives such as points, lines, rectangles and ellipses, controlling the
outline and fill.
Displaying text
Displaying images
Java
Page 189 - Copyright 2012 Walter Milner - all rights reserved
We will just look at some of the first set.
Firstly - the content pane of the JFrame. This is the part of a
JFrame that is normally used for content, and so excludes the
border and title bar. A JFrame has a method for obtaining a
reference to the content pane. If we get a graphics context on
that, we can draw with the origin (0,0) at the top left, and we do
not have to worry about adjusting for the title bar. For example:
void draw() {
Container pane = getContentPane();
Graphics2D g2 = (Graphics2D) pane.getGraphics();
Line2D.Double myLine = new Line2D.Double(0, 0, 100, 100);
g2.draw(myLine);
}
Next, one primitive is a rectangle:
void draw() {
Container pane = getContentPane();
Graphics2D g2 = (Graphics2D) pane.getGraphics();
Rectangle2D.Double myRect = new Rectangle2D.Double(10, 20, 200, 100);
g2.setColor(Color.red);
g2.draw(myRect);
}
This also introduces the Color class. Instances of the Color class can be constructed by for example
new Color(50,100,255); where the three parameters are values for red, green and blue components
in the range 0 to 255. The class also has some standard colours like Color.red.
Next, the idea of stroke - how the line of the shape is drawn:
void draw() {
Container pane = getContentPane();
Graphics2D g2 = (Graphics2D) pane.getGraphics();
Rectangle2D.Double myRect = new Rectangle2D.Double(10, 20, 50, 100);
g2.setColor(new Color(50,100,200));
BasicStroke stroke=new BasicStroke(6);
g2.setStroke(stroke);
g2.draw(myRect);
}
The parameter in the constructor of the stroke object is the line width in pixels.
Finally we can fill in the insides:
void draw() {
Container pane = getContentPane();
Graphics2D g2 = (Graphics2D) pane.getGraphics();
Rectangle2D.Double myRect = new Rectangle2D.Double(10, 20, 50, 100);
// draw outline
BasicStroke stroke=new BasicStroke(6);
g2.setStroke(stroke);
g2.setColor(Color.green);
g2.draw(myRect);
// fill inside
g2.setPaint(Color.blue);
g2.fill(myRect);
}
or we can fill it in with a color gradient instead of a solid colour:
Java
Page 190 - Copyright 2012 Walter Milner - all rights reserved
void draw() {
Container pane = getContentPane();
Graphics2D g2 = (Graphics2D) pane.getGraphics();
Rectangle2D.Double myRect = new Rectangle2D.Double(10, 20, 50, 100);
GradientPaint gradient = new GradientPaint(10,20, Color.red,
50,100,Color.blue);
g2.setPaint(gradient);
g2.fill(myRect);
}
Exercise
Try this stuff out.
Try using the Ellipse2D.Double to draw ovals.
Overloading
Overloading means having more than one version of a constructor or method. The different versions
have the same name, but different numbers or types of parameters.
For example, look at the BasicStroke class. We have seen one constructor:
void draw() {
Container pane = getContentPane();
Graphics2D g2 = (Graphics2D) pane.getGraphics();
Rectangle2D.Double myRect = new Rectangle2D.Double(10, 20, 50, 100);
BasicStroke stroke = new BasicStroke(6);
g2.setStroke(stroke);
g2.draw(myRect);
}
The constructor with one argument takes that as the width of the stroke. But we could also use the
constructor with no arguments, which uses default values:
BasicStroke stroke = new BasicStroke();
Or one with three arguments which specify how lines end and join:

BasicStroke stroke = new BasicStroke(10, BasicStroke.CAP_ROUND,
BasicStroke.JOIN_BEVEL);



Or one with six arguments for dashed lines:

float dash1[] = {10, 15, 5};
BasicStroke stroke = new BasicStroke(3.0f,
BasicStroke.CAP_BUTT,
BasicStroke.JOIN_MITER, 10.0f, dash1, 0f);
This is a matter of convenience - we can use the constructor which gives us the
degree of control we want. They must differ in argument number or type, or otherwise the compiler
cannot determine which one we want.
Java
Page 191 - Copyright 2012 Walter Milner - all rights reserved
If you look through the Java API, you will see countless examples of oveloaded constructors and
methods.

Java
Page 192 - Copyright 2012 Walter Milner - all rights reserved
More OOP

This part covers further aspects of object-oriented programming.
Java
Page 193 - Copyright 2012 Walter Milner - all rights reserved
abstract
This section looks at inheritance and abstract in some depth. The basic idea is to reuse the code in a
base class or superclass and extend it to give more capabilities in a subclass.
Rules of inheritance
A subclass extends a superclass (base class)
The subclass inherits all the data fields and methods from the superclass.
Constructors are not inherited
The subclass can add more data fields and methods.
The subclass can have a different version of an inherited method with the same name. The
subclass method over-rides the superclass version.
The subclass can itself be extended to another level. This results in a class hierarchy.
At the top of all class hierarchies is the class Object. In other words all classes extend Object.

super
Constructors are not inherited - in the base class, constructors need to be written. However it is
possible for the base class constructor to invoke the super class constructor, by
super();
for the constructor with no arguments (the 'no-arg constructor') or something like
super(x,y,z);
to invoke a constructor with arguments.
If there is a call to super, it must be the first statement in the constructor.
If you do not call super, the compiler will in effect insert one. In other words the compiler will
generate bytecode so that the base constructor first calls the super constructor.
The super notation can also be used to refer to superclass fields and methods where they have been
over-ridden. For example suppose we have a base class Base with a method someMethod, and a
sub-class Sub has its own version of someMethod. This will over-ride the base class version, so inside
Sub,
someMethod();
invokes Sub's version. But if we need to we can say
super.someMethod();
and it will invoke the base class version.


Java
Page 194 - Copyright 2012 Walter Milner - all rights reserved
Class hierarchy design
Much Java programming involves just using existing classes, or possibly sub-classing one class to give
an adapted version. However we may sometimes need to design a hierarchy with several levels. In
this case:
Common features go in the base class
Features which are logically required by all go in the base class
A specialisation is a subclass of a base class.
Classes towards the top of the hierarchy may be so general that they cannot logically be
instantiated. This can be controlled by declaring them to be abstract.

Example - a Shape hierarchy
We will use the Java 2D Graphics API to set up the following

What do all shape objects have in common? A position and size, a graphics context to be drawn in,
line and fill colours (ignoring gradients), and a method to draw it on the screen. These will therefore
go in the Shape class. A circle is a specialisation of an oval, with width and height equal, and a square
is a special oblong. We cannot actually draw a Shape, not knowing what shape it is. We can ensure
this by making Shape an abstract class.
Base classes do not have to be abstract. For example Oval is a base class for Circle, but it is not
abstract.
The definition of Shape is:
Java
Page 195 - Copyright 2012 Walter Milner - all rights reserved
abstract class Shape {

Color lineColor;
Color fillColor;
Graphics2D graphicsContext;
int width;
int height;
int top;
int left;

Shape(Graphics2D g) {
graphicsContext = g;
}

abstract void show();
}
Oval is:
class Oval extends Shape {
Ellipse2D.Double oval;

Oval(Graphics2D g)
{
super(g);
width=50;
height=70;
top=0;
left=0;
oval=new Ellipse2D.Double(left,top, width, height);
}

Oval(Graphics2D g, int top, int left, int width, int height, Color lineColor, Color
fillColor)
{
super(g);
this.width=width;
this.height=height;
this.top=top;
this.left=left;
this.lineColor = lineColor;
this.fillColor=fillColor;
oval=new Ellipse2D.Double(left,top, width, height);
}

void show()
{
graphicsContext.setPaint(fillColor);
graphicsContext.fill(oval);
graphicsContext.setColor(lineColor);
graphicsContext.draw(oval);
}
}
Circle is just:
class Circle extends Oval {
Circle(Graphics2D g, int top, int left, int radius, Color lineColor, Color fillColor)
{
super(g, top, left, radius, radius, lineColor, fillColor);
}
}
Code to use these classes could be
Java
Page 196 - Copyright 2012 Walter Milner - all rights reserved
Container pane = getContentPane();
Graphics2D g2 = (Graphics2D) pane.getGraphics();
Oval oval1 = new Oval(g2);
oval1.show();
Oval oval2 = new Oval(g2, 50,50,80,30, Color.red, Color.blue);
oval2.show();
Circle circle = new Circle(g2, 0, 80, 30, Color.green, Color.yellow);
circle.show();
Shape has a simple constructor to establish the graphics context, and an abstract show method. This
means that all non-abstract sub-classes of Shape must implement the show() method, and that we
cannot accidentally instantiate a Shape object - the compiler will stop us.
The Oval class has two constructors - this is overloading. The one with just one argument calls the
constructor of Shape (through super) to establish the graphics context, and gives some default
values to the width and so on. The other constructor is similar, but also passes in values for width,
colour and so on. The Oval class defines show, so we can instantiate it and it is not abstract.
Why does Oval not declare top, left and the other fields? Because they are inherited from Shape.
The Circle class is very similar to Oval. The difference is worked by the constructor, whose radius
parameter is passed to the width and height parameters of the underlying Oval.
Why does Circle not have a show method defined? Because it inherits show from Oval.
Exercise
Run this application.
Accessor methods would be getHeight, setHeight, getTop, setTop and so on. In which class or classes
would you define them? Do it and use them.
Define the Oblong and Square classes and use them.
Multiple inheritance
Suppose we want a class to extend two base classes, because we want it to develop the functionality
of two classes. We could try
class MyClass extends ClassA, ClassB ..
but the compiler will not let you. Java does not allow multiple inheritance in this way (C++ does).
But you can do this by using inheritance by composition. This means having a data field in the class
which is an instance of the second class. This would be
class MyClass extends ClassA
{
ClassB bObject;
..
Now the bOject knows how to do ClassB methods, and so MyClass has both ClassA and ClassB
features.
The graphics classes show this. How can Oval actually draw an oval shape? We could have tried to
draw ovals 'from scratch' in the definition of Oval, but the Ellipse2D.Double class already knows how
to do this. So we started Oval with:
Java
Page 197 - Copyright 2012 Walter Milner - all rights reserved
class Oval extends Shape {
Ellipse2D.Double oval;
which means Oval inherits from Shape and knows how to do Ellipse2D.Double methods.
This is not full multiple inheritance, since we cannot over-ride the methods of the composed class.
For example, Oval cannot alter the methods of Ellipse2D.Double. But it can use them in different
ways, which is very close.
These example classes show another case of inheritance by composition, with the Shape class
containing a Graphics2D object. It is this which actually knows how to outline and fill an ellipse,
which we use in
void show()
{
graphicsContext.setPaint(fillColor);
graphicsContext.fill(oval);
graphicsContext.setColor(lineColor);
graphicsContext.draw(oval);
}
Check your understanding
What does inheritance mean?
What is the Object class?
What is the difference between overriding and overloading?
What is gained by declaring a class abstract?
What does 'inheritance by composition' mean?
Java
Page 198 - Copyright 2012 Walter Milner - all rights reserved
Annotations
An annotation provides some information about the program - meta-data about the program.
Annotations do not directly influence execution, but they might indirectly. Annotations started to be
introduced in Java 5.
Three annotations are built-in to the language - Deprecated, SuppressWarnings and Override
@Deprecated
A method is said to be deprecated if it has
been replaced by better alternatives. This
might be just documented. But using the
@Deprecated annotation means the compiler
will also issue a warning if a deprecated
method is used.
In NetBeans, the editor will strike-through
methods which have this annotation, and if
this code is compiled, the output is :
Compiling 1 source file to
C:\Users\walter\Documents\NetBeansProj
ects\Test\build\classes
C:\Users\walter\Documents\NetBeansProjects\Test\src\test\Test.java:7: warning:
[deprecation] someMethod() in Base has been deprecated
b.someMethod();
1 warning
In NetBeans, this only works if the 'compile on save' option is de-selected.
@SuppressWarnings
This is used to stop compiler warnings of a given type. For example
class Test {

@SuppressWarnings("deprecation")
public static void main(String[] args) {
Base b = new Base();
b.someMethod();
}
}

class Base {
@Deprecated
void someMethod() {
}
}
does not generate the warning.
@Override
This signals that a method is intended to override a base class method. For example:
Java
Page 199 - Copyright 2012 Walter Milner - all rights reserved
class Base {

void someMethod() {
}
}

class SubClass extends Base
{
@Override
void someMethod()
{

}
}
But what is the point? Because this might happen:
We thought we were overriding someMethod, but we spelt it somemethod. Using the @Override
annotation means the compiler can detect the error and tell us. This is another example of having a
language feature chosen so that the compiler can tell us about errors, rather than us having to figure
it out.
In addition to these built-in annotations, it is also possible to define your own, and to write
annotation processor tools which will deal with them - such as by inserting source code before
compilation.

Java
Page 200 - Copyright 2012 Walter Milner - all rights reserved
Nested Classes
It is possible to define one class inside another class. These are called nested classes, and come in
several flavours:
An inner class, where a class is defined inside another class
A local class, defined inside a method
An anonymous class, which has no name
A static nested class
A static nested class is not an inner class.
Inner classes
For example:
class Test {

public static void main(String[] args) {
Outer outer = new Outer();
outer.x = 5;
Outer.Inner inner = outer.new Inner();
inner.y = 5;

}
}

class Outer {

int x = 2;

class Inner {
int y = 3;
}
}
So here we have an Outer class enclosing an Inner class.
Here is a variation, where we add a method to the inner class to return a reference to the enclosing
class instance. We then instantiate two inner class objects, then set the outer class member from
one, and retrieve it from the other:
Java
Page 201 - Copyright 2012 Walter Milner - all rights reserved
class Test {

public static void main(String[] args) {
Outer outer = new Outer();
outer.x = 5;
Outer.Inner inner = outer.new Inner();
Outer.Inner inner2 = outer.new Inner();
inner.getOuter().x = 3;
System.out.println(inner2.getOuter().x);
}
}

class Outer {

int x = 2;

class Inner {
int y = 3;
Outer getOuter() {
return Outer.this;
}
}
}
This means the structure of the objects is as shown. So there is a difference between
The class definition structure - one class defined inside another (lexical structure)
The object structure - two inner instances inside one outer
Private inner classes
If we make the inner class private, it cannot be referenced from outside the outer class. For
example:
class Outer {

Inner inner;

Outer()
{
inner=new Inner();
}

private class Inner {

}
}
This means we have a structure for the class definitions, and also for the objects created - each
Outer object will have just one Inner object in it. When we instantiate an Outer class, the
constructor instantiates just one Inner class. Because the class is private, it cannot be instantiated
from outside.
The main reason for making a class inner is if the functioning of the outer class requires another
class, and the other class is not useful elsewhere. So we have the other class as a private inner class.
This encapsulates things, and the inner is not visible from outside - it is part of the hidden
implementation of the outer class.
For example, suppose we want to implement a linked list. This will need something to represent a
node in the list - so as well as the LinkedList, we need a LinkNode. But LinkNode is unlikely to be
useful elsewhere, so make it a private inner class:
Java
Page 202 - Copyright 2012 Walter Milner - all rights reserved
class LinkedList {
private LinkNode head = null;
private LinkNode last=null;

void add(int n)
{
LinkNode node = new LinkNode(n);
if (last==null)// empty list
{
head=last=node;
}
else
{
last.next=node;
last=node;
}
}

void traverse()
{
LinkNode where = head;
while (where!=null)
{
System.out.println(where.data);
where=where.next;
}
}
private class LinkNode
{
int data;
LinkNode next;
LinkNode(int n)
{
data=n;
next=null;
}
}
}
used by for example:
LinkedList list = new LinkedList();
list.add(2); list.add(4); list.add(3);
list.traverse(); // 2 4 3
Local classes
This is a class defined inside a method, rather than in a class outside a method. This is useful where
an inner class is needed, but is only relevant to one method.
For example, suppose we want to have a reverse() method on our linked list. One way to do this is
with a stack - go through the list pushing everything onto the stack, then replace the list with what
you get popping entries off the stack. But only the reverse method would use the stack class, so
make it local. So we add the following:
Java
Page 203 - Copyright 2012 Walter Milner - all rights reserved
void reverse() {
class Stack { // start definition of local class

ArrayList<Integer> data = new ArrayList<>();

void push(int n) {
data.add(n);
}

Integer pop() {
if (data.isEmpty()) {
return null;
} else {
return data.remove(data.size() - 1);
}
}
} // end local class definition
Stack stack = new Stack(); // make a stack
LinkNode where = head; // starting from the head
while (where != null) { // push everything onto the stack
stack.push(where.data);
where = where.next;
}
head = last = null; // re-start with nothing
Integer i;
while ((i = stack.pop()) != null) // and pop from stack into list
add(i);
}

}
for example:

LinkedList list = new LinkedList();
list.add(2);
list.add(4);
list.add(3);
list.traverse(); // 2 4 3
list.reverse();
list.traverse(); // 3 4 2
A local class is like a local variable, in that its scope is limited to that method. It therefore cannot be
made private or any other access modifier.
Anonymous classes
This is used like
new SomeClass() { someMethod(){..} }
This does two things:
1. It defines a new class, as a subclass of SomeClass, with someMethod() added or overridden.
The new class has no name.
2. It creates a new instance of that new class
These are commonly used for event listeners in Swing GUI apps. We want an object which will listen
and react to some user event. But it will only be useful for that individual event, so it would not be a
useful class defined in the usual way. So, for example:
Java
Page 204 - Copyright 2012 Walter Milner - all rights reserved
JButton button=new JButton();
add(button)
button.addActionListener( new ActionListener() { public void actionPerformed(ActionEvent e){
.. }} );
The last line is explained as follows:
ActionListener() { public void actionPerformed(ActionEvent e){.. }}
define an anonymous subclass of ActionListener, with actionPerformed overridden to do what we
want the button to do,
new ActionListener() { publi..
make an instance of this anonymous class,
button.addActionListener( new ActionListener() {..
tell the button that this object will listen for clicks.
Static nested classes
Like static elsewhere, this is per class not per object:

class Test {

public static void main(String[] args) {
Outer.StaticClass obj = new Outer.StaticClass();
obj.x = 3;

}
}

class Outer {

static class StaticClass {
int x = 4;
}
}
A static nested class is not an inner class. This is because it does not have instance scope:
class Outer {
int y;
static class StaticClass {
StaticClass()
{
y=2; // no good - OK if not static
}
}
}
Exercise
1. There are four types of nested class - what are they?
2. Why does a static nested class not have instance scope?

Java
Page 205 - Copyright 2012 Walter Milner - all rights reserved
Generics
Generics means using type parameters. Constructors and methods usually take formal parameters,
representing data passed into them which control what they do. A type parameter is similar, except
that it represents a type, not a data value. We can have generic types (classes and interfaces) and
generic methods.
The idea is that often the code handling different types - the class structure and algorithms used - is
the same, no matter what data type it uses. But Java is a strongly typed language - all variables and
expressions must have a type determined at run-time. Without generics, we would have to duplicate
code for different types.
Writing generic classes and methods is not simple, and neither is this section. But using the generics
in the Java Collections framework of data structures is very easy, as another section shows.
Useful Links
Angelika Langer Generics FAQ
http://www.angelikalanger.com/GenericsFAQ/JavaGenericsFAQ.html
Generics and type safety
Suppose you had a data structure containing Objects, and you use it to store Strings in. When you
recall an element, you need a typecast to tell the compiler that the Object is actually a String:
String string = (String) data.getOne();
You know this will work, since you know as the programmer that everything you put in the data
structure was really a String.
Having to put the cast there is annoying - but more importantly, there might be an error such that
objects are put in which cannot be cast to a String, which would result in a runtime
ClassCastException.
Generics ensures type safety. The compiler inserts type checks such that you can be sure only one
type can be placed in it, and no cast is needed on the retrieval.
A generic Linked List
For example, the data structure known as a linked list has the same structure, and the same
algorithms, no matter what data type it contains. So how can we model that in a strongly-typed
language?
In fact the Collections framework already has a linked list implemented for us. But it uses generics,
so we can better understand it if we first look at how generics works.
The class definition starts:
class LinkedList <T> {
Here the < > signals a type parameter - this will be a linked list containing data type T. Through the
class code we then use T as if it were a type. Like this:
Java
Page 206 - Copyright 2012 Walter Milner - all rights reserved
class LinkedList <T> {
private LinkNode head = null;
private LinkNode last=null;

void add(T n) // n is type T
{
LinkNode node = new LinkNode(n);
if (last==null)// empty list
{
head=last=node;
}
else
{
last.next=node;
last=node;
}
}
..
LinkNode is an inner class which uses the type parameter:
..
private class LinkNode
{
T data; // data is type T
LinkNode next;
LinkNode(T n) // type T in constructor
{
data=n;
next=null;
}
}
}
Some of the methods do not need to refer to the type:
..
void traverse()
{
LinkNode where = head;
while (where!=null)
{
System.out.println(where.data);
where=where.next;
}
}
..
When we use this class, we must supply an actual type:
LinkedList<String> strings = new LinkedList<>();
strings.add("One");
strings.add("Two");
strings.add("Three");
strings.traverse(); // One Two Three
LinkedList<Integer> numbers = new LinkedList<>();
numbers.add(1); / autoboxing - really numbers.add(new Integer(1));
numbers.add(2);
numbers.add(3);
numbers.traverse(); // 1 2 3
Sub-classes and generics
If we say
LinkedList<String> strings = new LinkedList<>();
LinkedList<Object> objects = strings;
the second line is a compile error.
Java
Page 207 - Copyright 2012 Walter Milner - all rights reserved
It might be thought that since a String is an Object, a list of Strings would be a list of Objects. But it is
not.
The reason is that otherwise, we could add an Object to 'objects', then get it back from 'strings', and
find that it was an Object, not a String. We must be sure that the elements of 'strings' are actually
Strings, or type safety is lost.
In general, a generic class of a base class is not a supertype of a generic class of a subclass.
Generic methods
As well as generic classes, we can have methods which take a type parameter.
Suppose we want something to transfer the elements of an array into a linked list. The type of the
array elements could be anything - we should get a linked list containing the same type. Here it is:
static <E> LinkedList<E> arrayToLinkedList(E[] array) {
LinkedList<E> list = new LinkedList<>();
for (int i = 0; i < array.length; i++) {
list.add(array[i]);
}
return list;
}
The first line is parsed as:
This is used as
String[] stringArray = {"one", "two", "three"};
LinkedList<String> strings = LinkedList.arrayToLinkedList(stringArray);
strings.traverse();
Wildcards
Suppose we want a static method to traverse and output the elements of a list passed as a
parameter. The method code would be:
LinkNode where= list.head;
while (where != null) {
System.out.println(where.data);
where = where.next;
}
This does not mention the type of the elements in the list. So how would the method header be
written?
Java
Page 208 - Copyright 2012 Walter Milner - all rights reserved
static void printAll(LinkedList< what goes here? > list)
{..
The type is 'any' or 'unknown'. We can use the ? wildcard for this:
static void printAll(LinkedList<?> list) {
LinkNode where = list.head;
while (where != null) {
System.out.println(where.data);
where = where.next;
}
}

Generic interfaces
An interface can also have type parameters.
Suppose we want a method to add up arrays. Not all arrays contain elements which can be 'added
up'. The first step would be to define what that means. The elements would need to belong to a
class which implemented a suitable interface:
interface Addable<T> {
T add(T other);
}
So an addable class has a method where you add the instance to another instance of the class, and
the result is a third instance. Such as:
class MyInt implements Addable<MyInt> {

int val; // it wraps an int

MyInt(int i) {
val = i;
}

public MyInt add(MyInt other) { // Addable implementation
return new MyInt(val + other.val);
}

public String toString() {
return "" + val;
}
}
We could use this class like
MyInt n1 = new MyInt(5);
MyInt n2 = new MyInt(6);
MyInt n3 = n1.add(n2);
then a method to add up an array would be:
static <T extends Addable<T>> void addUp(T[] values) {
T t = values[0];
for (int i = 1; i < values.length; i++) {
t = t.add(values[i]);
}
System.out.println(t);
}
}
The header says that this method has a type parameter T, and that T is a type which is or extends a
class which implements the Addable interface on the type T. The method takes as formal parameter
an array of type T elements.
Java
Page 209 - Copyright 2012 Walter Milner - all rights reserved
To show the power of this - we could add an array of vectors. A vector in physics has 3 components,
usually called x y and z, and vectors are added by adding their components. Here is our vector class:
class MyVector implements Addable<MyVector> {

double x,y,z;

MyVector(double x, double y, double z) {
this.x=x; this.y=y; this.z=z;
}

public MyVector add(MyVector other) {
return new MyVector(x + other.x, y+other.y, z+other.z);
}

public String toString() {
return x+", " +y+", "+z;
}
}
Then we can use this like:
MyVector v1=new MyVector(1,2,3);
MyVector v2=new MyVector(1,1,1);
MyVector v3=new MyVector(2,2,2);

MyVector[] data = {v1, v2, v3};
addUp(data); // 4.0, 5.0, 6.0

Type erasure
Type parameters cannot be used with the freedom of data parameters. For example, type
parameters cannot be instantiated. Neither can arrays of generic types be instantiated. The reason
for this is type erasure, which is how generics are implemented in Java.
For example in our addUp method, it is usual to initialise a running total with zero, by instantiating a
zero value:
static <T extends Addable<T>> void addUp(T[] values) {
T t = new T(0); // will not compile
for (int i = 0; i < values.length; i++) {
t = t.add(values[i]);
}
System.out.println(t);
}
}
There is an issue as to whether the actual type has such a constructor - but we cannot do this
anyway.
In C++, generic source code is written as a template, and the compler generates different copies of it
for each version with a different actual type. But in Java, the compiler produces only one version,
with the type parameters removed. The following happens:
1. When a generic class or interface or method is compiled, any occurence of a type parameter is
replaced by its upper bound, or Object if there is no bound
2. When a generic type is instantiated, the actual type parameter is removed, leaving the raw type
(so if you wrote List<String>, it becomes just List ).
Java
Page 210 - Copyright 2012 Walter Milner - all rights reserved
3. Types are checked and casts are generated by the compiler if required.
We started off saying
"Suppose you had a data structure containing Objects, and you use it to store Strings in. When you
recall an element, you need a typecast to tell the compiler that the Object is actually a String:
String string = (String) data.getOne();"
Type erasure in effect does this for you.
Arrays of generic types
Type erasure means this is not allowed directly. We can get around this by wrapping an Object array,
and type casting insertions and references. The following example does this, and shifts the index so
that it does not have to start at zero.
class MyArray<T> {

private final int first, last;
private Object[] array;

MyArray(int first, int last) {
this.first = first;
this.last = last;
array = new Object[last - first + 1];
}

@SuppressWarnings("unchecked")
public T get(int index) {
return (T) array[index - first];
}

void put(int index, T value) {
array[index - first] = value;
}
}
This is used for example:
MyArray<String> stringArray = new MyArray<>(100, 200);
stringArray.put(100, "One");
stringArray.put(101, "Two");
stringArray.put(102, "Three");
stringArray.put(200, "Last");
System.out.println(stringArray.get(100));
// stringArray.put(201, "Three"); array index out of bounds exception
The line
MyArray<String> stringArray = new MyArray<>(100, 200);
creates an array with first element index 100, and last is 200.

Java
Page 211 - Copyright 2012 Walter Milner - all rights reserved
The Collections Framework

The Java Collections framework is a set of implementations of computer science data structures. An
array is an example of a data structure. Arrays are good for many purposes, but they are limited -
most notably, the number of elements in an array is fixed at compile-time. Other data structures
(lists, stacks, queues, trees, maps) are sometimes more effective. Because data structures are such a
fundamental aspect of computing, it is sensible that there are foundation classes for them.
Each data structure characteristically has a set of associated algorithms, to add data to it, remove
data, search and so on, and these naturally translate into OOP methods.
These algorithms are indifferent to the type of data in the structure. For example, searching a tree
does not depend on the type of data in it. However, Java is a strongly-typed language - each variable
must have a fixed and known type. So, how to have the same algorithm irrespective of type, when
the code must say what type it is?
That problem is solved by generics. The structures have a type parameter, so when we we can create
a list, for example, we supply a parameter which specifies what the type in the list will be. Solved,
very simply.
The Collections framework also shows a lot of abstraction. Each one is an implementation of a data
structure. How is the implementation done? We don't know, and we don't care. The collection will
specify what methods are available (insert, remove etc), and how fast they are (in big O notation -
google it). We decide which to use on that basis - not on how they work internally. In fact the
implementation might change, but it will make no difference to us.
Useful Link
The Oracle Collections Trail
Example
Suppose we want to have an array of Strings - but we do not know how many there will be. An
ArrayList does it:
ArrayList<String> list = new ArrayList();
list.add("One");
list.add("Two");
list.add("Three");
for (String s : list) {
System.out.println(s);
}
When we declare 'list', we have to supply the <String> type parameter to say we want a list of
Strings. Then we can just add and remove them. Note also the convenient for-each loop. It can be
read as 'for each String in list, calling it s, do ....'.
Interfaces and implementations
The framework has a set of interfaces (how you might want to use the data structure) and classes
(implementations of those interfaces). This diagram shows the main interfaces, in black, and the
most commonly used implementations, in red:
Java
Page 212 - Copyright 2012 Walter Milner - all rights reserved

HashSet
A HashSet is like a mathematical set. It has no order, and no duplicates. For example:
class Test {

public static void main(String[] args) {
HashSet<MyClass> set = new HashSet();
MyClass mc1 = new MyClass(1, 1);
MyClass mc2 = new MyClass(1, 2);
MyClass mc3 = new MyClass(2, 2);
MyClass mc4 = new MyClass(1, 2);
set.add(mc1);
set.add(mc2);
set.add(mc3);
set.add(mc1);
set.add(mc4);
for (MyClass c : set) {
c.display();
}
}
}

class MyClass {
int x, y;
MyClass(int x, int y) {
this.x = x;
this.y = y;
}
void display() {
System.out.println(x + " " + y);
}
public int hashCode() {
int hash = 3;
hash = 79 * hash + this.x;
hash = 79 * hash + this.y;
return hash;
}
public boolean equals(Object other) {
return (x == ((MyClass) other).x && y == ((MyClass) other).y);
}
}
The output is:
1 1
1 2
2 2
So a HashSet contains no duplicates. If we try to add the same object twice, it is only present once.
Nor can we add a different object if it .equals an object already there.
A HashSet uses a hash code of its elements to determine where to store them. This is the hash
function used in the underlying hash table.
Java
Page 213 - Copyright 2012 Walter Milner - all rights reserved
ArrayList

An ArrayList is very like an array which can grow and shrink. It is ordered in the sense that it tracks
the first item, second and so on, as a sequence. This not the same as sorted. Elements can be added
at the end, or at a given index. Elements at an index, or a given instance can be removed. If the type
in the ArrayList implements Comparable, then Collections.sort can sort the list. For example, using
objects of type Record:
class Record implements Comparable<Record>
{
int key;
String value;
Record(int key, String value)
{
this.key=key;
this.value=value;
}
public String toString()
{
return "Key: "+key+" Value:"+value;
}
public int compareTo(Record other)
{
if (key>other.key) return 1;
if (key==other.key) return 0;
return -1;
}
}
We can have an ArrayList of them:
ArrayList<Record> list = new ArrayList<>();
list.add(new Record(4,"Four")); // added at the end
Record rec = new Record(5,"Remove");
list.add(rec);
list.add(new Record(6,"Six"));
list.add(2, new Record(7,"Added at 2")); // added as index 2
list.remove(rec);
for (Record r: list)
System.out.println(r); // get 4 7 6
Collections.sort(list);
for (Record r: list)
System.out.println(r); // get 4 6 7

An ArrayList in effect wraps an array with a certain capacity. Adding an element takes a constant
average time, and causes the capacity to automatically grow.
LinkedList
The LinkedList class is an implementation of the corresponding
data structure, consisting of nodes with pointers to the next
node, with nodes maybe not next to each other in memory. It is
doubly-linked, so that as well as a pointer from a node to the
next, there is a pointer to the previous, and the list can be
traversed in either direction.
A linked list can be used like an ArrayList:
Java
Page 214 - Copyright 2012 Walter Milner - all rights reserved
LinkedList<Record> list = new LinkedList<>();
list.add(new Record(1,"One"));
Record rec = new Record(2,"Two");
list.add(rec);
list.add(new Record(3,"Six"));
list.add(2, new Record(4,"Added at 2"));

for (Record r: list)
System.out.println(r); // get 1 2 4 3

But, the time to access elements is
different. An ArrayList is backed by an array,
and to access the nth element this works
directly, so the time to do this does not
depend on n. But for a linked list, the
system must follow the links from the head
(or the tail) so it gets slower for longer lists,
as shown.
So a linked list is not suitable where fast
access to a given element is needed.
But it does work well as a stack (LILO) or a
queue (FIFO) . For example:
LinkedList<Record> queue = new LinkedList<>();
Record rec1 = new Record(1,"Test");
Record rec2 = new Record(2,"Test");
Record rec3 = new Record(3,"Test");
queue.addFirst(rec1);
queue.addFirst(rec2);
queue.addFirst(rec3);
while (queue.peekLast()!=null)
{
Record rec =queue.removeLast();
System.out.println(rec); // 1 2 3
}
TreeMap
A HashMap provides a structure in which key-value pairs can be stored and retrieved, and unlike a
HashSet, it allows for duplicates.
But more fun is a TreeMap. This is like an ordered binary tree implemented in another section,
except that it is based on a red-black tree, which has an insertion algorithm such that it remains
balanced. A TreeMap is therefore good if you need to maintain the data ordered:
TreeMap<String, String> treeMap = new TreeMap<>();
treeMap.put("D", "One"); // put = insert a key, value pair
treeMap.put("B", "Two");
treeMap.put("E", "Three");
treeMap.put("C", "Four");
treeMap.put("A", "Five");
for (String key: treeMap.keySet())
System.out.println(key+" : "+ treeMap.get(key)); // get A B C D E
The for is the new 'foreach' loop introduced in Java 5. The keySet is the set of keys in the tree. So the
loop effectively says 'for each key in the tree,...show me the key and its associated value.'
Java
Page 215 - Copyright 2012 Walter Milner - all rights reserved
Exercise
1. Write code to measure the time to access the central node in a LinkedList of different sizes, as
shown in the graph.
2. Do the same for an ArrayList.
3. Write code to show a LinkedList being used as a stack.




Java
Page 216 - Copyright 2012 Walter Milner - all rights reserved
Enums
An enum is a small set of symbolic constants. Enums were introduced in Java 5.
For example, suppose we are writing an on-line theatre ticket booking system. A customer would
choose a seat which is free, enter their credit card details, and buy the ticket. We must ensure that
someone else does not book the ticket while they are entering their card details, or we will sell it
twice.
We can do this by having three states a ticket can be in - free, locked or purchased. We could code
the state as an int of magic numbers - 0=free, 1=locked, 2=purchased, like
class Ticket
{
char row;
int number;
int state;
Ticket(char row, int number)
{
this.row=row;
this.number=number;
state=0; // free
}
}
Enums offer a much better way:
enum TicketState
{
FREE, LOCKED, PURCHASED
}

class Ticket
{
char row;
int number;
TicketState state;
Ticket(char row, int number)
{
this.row=row;
this.number=number;
state=TicketState.FREE;
}
}
This says that a TicketState is one of FREE, LOCKED or PURCHASED - in capitals, since they are
constants. The 'state' attribute of a Ticket object has type TicketState.
Enums versus Magic Numbers
1. Enums say what they mean (like LOCKED, not 0) in code
2. Enums also say what they mean in println output (LOCKED not 0)
3. They have a compile-time check on domain errors (in other words you cannot say state=3;
which you could if 'state' was an int)
Enums as classes
Many languages have an equivalent of enum. For example the C version of the TicketState enum
would look identical to the Java version. But C enums and ints can be interchanged - losing the
advantages of enums over magic numbers.
Java
Page 217 - Copyright 2012 Walter Milner - all rights reserved
In fact a Java enum is a special type of class. This means it can have constructors, methods and fields,
and so the properties of a thing can be modelled in code:
enum Season { // start an enum - a special class definition

// allowed values - in effect, constructor calls:
SPRING("Spring"),
SUMMER("Summer"),
AUTUMN("Autumn"),
WINTER("Winter");

String name; // a data field

Season(String name) { // the constructor
this.name = name;
}

public String toString() { // a method, over-riding toString - nicer than capitals
return name;
}

Season next() { // method returning a Season - the next one
switch (this) { // can use switch on an enum
case SPRING:
return SUMMER;
case SUMMER:
return AUTUMN;
case AUTUMN:
return WINTER;
case WINTER:
return SPRING;
}
return null; // never get here
}
}
Then we can use the enum like:
Season season = Season.SPRING;
System.out.println(season); // Spring
System.out.println(season.next()); // Summer
An enum can have constructors, but they cannot be instantiated in code, like
Season newOne = new Season("Weird"); // compile-error
The compiler generates constructor calls as it encounters the list of allowed values (
SPRING("Spring"), SUMMER.. ).
An enum may only be relevant to one class, in which case it is appropriate to make it inner:
class Ticket {

private enum TicketState {
FREE, LOCKED, PURCHASED
}
char row;
int number;
TicketState state;

Ticket(char row, int number) {
this.row = row;
this.number = number;
state = TicketState.FREE;
}
}

Java
Page 218 - Copyright 2012 Walter Milner - all rights reserved
Exceptions
An exception is an unusual situation which will affect the normal execution of a program.
For example:
class Test {

public static void main(String[] args) {
int y = 0;
int x;
Scanner scanner = new Scanner(System.in);
System.out.println("Enter an integer");
y=scanner.nextInt();
x = 12 / y;
}
}
Usually this inputs an integer and divides 12 by it. But what if the user inputs 0? This happens:
Enter an integer
0
Exception in thread "main" java.lang.ArithmeticException: / by zero
at test.Test.main(Test.java:13)
Java Result: 1
The program 'throws' an exception and terminates abruptly.
The Java language has been designed to provide the programmer with tools to deals with situations
like these.
Types of exceptions
1. Program bugs. While a bug will often produce an exception, the language design cannot cope with
these. Exception handling will not fix program bugs. It is illogical to suppose that program code could
solve errors in program code.
2. Invalid input data
The first example showed this. Input values might come from a user at a keyboard, read from a data
file, from a web server or whatever. The values which your program inputs may be invalid.
Exception-handling can help here.
3. I/O communications failure
For example your program tries to read a file which does not exist. Or you try to write to a file and
the disc is full, or the file is read-only. Or you are receiving data from a remote server and the
network connection is lost. Exception-handling can help here.
4. System failure
The machine runs out of memory, or the JVM breaks (almost unknown). Recovery from such
situations is usually impossible.
Java
Page 219 - Copyright 2012 Walter Milner - all rights reserved

try.. catch
A try..catch statement is often used in relation to exceptions. The idea is..

try
{
.. some code which might go wrong
}
catch (the exception)
{
.. do this instead when it goes wrong
}
For example in our first program:
class Test {

static void doMethod() {
int y = 0;
int x;
Scanner scanner = new Scanner(System.in);
System.out.println("Enter an integer");
y = scanner.nextInt();
try {
x = 12 / y;
System.out.println("12 / " + y + " = " + x);
} catch (ArithmeticException ex) {
System.out.println("Its gone wrong");
System.out.println(ex.getMessage());
ex.printStackTrace();

}
}

public static void main(String[] args) {
doMethod();
System.out.println("Program ends normally");
}
}
Now when 0 is input, this happens:
Enter an integer
0
Its gone wrong in the catch clause
/ by zero this is the getMessage()
java.lang.ArithmeticException: / by zero start of the stack trace
Program ends normally
at test.Test.doMethod(Test.java:14)
at test.Test.main(Test.java:25)
Now our exception has been caught, execution proceeds, and the program ends normally. The
getMessage method outputs a descriptive message about the exception, and the stack trace shows
which line it occured in and which method, and which method called that, and so on - often to
considerable depth.
Exception and exceptions
An exception is a concept, an idea, and an event. Exception (capital letter) is a Java class, and
instances of that class are also called exceptions, or exception objects. Exception has many
subclasses. ArithmeticException is one of those. It inherits the getMessage() and printStackTrace()
methods.
Java
Page 220 - Copyright 2012 Walter Milner - all rights reserved
The hierarchy
The base class is Throwable, which has the getMessage and printStackTrace methods. This has two
subclasses - Error and Exception.
Instances of Error and its subclasses are serious and an application could not be expected to recover
from one - a JVM error is an example.
An Exception instance is less serious and might be recovered from.
Exception and most of its subclasses are checked exceptions. That means that if you use a method
which might throw a checked exception, the compiler will require that the exception is dealt with
somehow - maybe by catching it. For example:
Here we are opening a file called 'textfile.txt' for input. But the compiler signals that this might
produce a FileNotFoundException, and our code must deal with that.
The class RuntimeException, and its subclasses, are not checked. An example is
ArrayIndexOutOfBoundsException, like this:
Java
Page 221 - Copyright 2012 Walter Milner - all rights reserved
package test;

class Test {

public static void main(String[] args) {
int[] data = new int[100];
System.out.println(data[100]);
}
}
which produces:
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 100
at test.Test.main(Test.java:10)
Java Result: 1
These usually result from programming errors (as this does) and we have already said we cannot
expect to deal with programming errors with program code - so forcing them to be handled would
be pointless. Also, accessing array elements is so common that forcing the programmer to deal with
a possible exception would clutter and obscure normal program code.
Catching exceptions
There are two ways to deal with an exception - catch it or throw it. Firstly, catching it.
As an example we use code to read and display a text file. Full explanation of i/o is in another
section. There are problems with the following code:
class Test {

public static void main(String[] args) {
try {
// open file
FileInputStream fstream = new FileInputStream("c:/temp/test.txt");
DataInputStream in = new DataInputStream(fstream);
BufferedReader br = new BufferedReader(new InputStreamReader(in));
String str;
// read file
while ((str = br.readLine()) != null) {

System.out.println(str);
}
// close file
in.close();
} catch (Exception e) {

}

}
}
The first problem is that it has a catch block, so the compiler is happy. But there is nothing in the
catch block. We should at least do something. If reading that file was essential to the application, we
must end it - and hopefully tell the user why:
catch (Exception e) {
System.out.println("Cannot read the important file");
System.exit(1);
}
Secondly, we are catching an Exception. Because of the way a try catch works, this will catch an
instance of Exception, and any subclass - pretty much anything. The catch should be as specific as
possible:
Java
Page 222 - Copyright 2012 Walter Milner - all rights reserved
catch (FileNotFoundException fnf) {
System.out.println("Cannot find the important file");
System.exit(1);
}
Now this is thrown by the FileInputStream constructor. But the readLine method throws an
IOException as well (for example if the drive fails part way through reading the file) . No problem -
we can have additional catch blocks..
catch (FileNotFoundException fnf) {
System.out.println("Cannot find the important file");
System.exit(1);
}
catch (IOException iox) {
System.out.println("Error when reading file");
System.exit(2);
}
After the last catch you can also have a finally block, like
try
{
.. something..
}
catch (some exception)
{
.. try to recover..
}
finally
{
.. this executes with or without error
}
But in our example we do not recover from the error, just stop, so a finally would be pointless.
Throwing an error
So you can deal with an exception by catching it. You can also throw it. Suppose we put our file read
in a method:
static void readFile() throws FileNotFoundException, IOException
{
FileInputStream fstream = new FileInputStream("c:/temp/test.txt");
DataInputStream in = new DataInputStream(fstream);
BufferedReader br = new BufferedReader(new InputStreamReader(in));
String str;
// read file
while ((str = br.readLine()) != null) {

System.out.println(str);
}
// close file
in.close();
}
So we have declared readFile to throw those two exceptions. That means that in turn, anything
which calls that method must catch them (or throw them again). For example:
Java
Page 223 - Copyright 2012 Walter Milner - all rights reserved
public static void main(String[] args) {
try {
readFile();
} catch (FileNotFoundException fnf) {
System.out.println("Cannot find the important file");
System.exit(1);
} catch (IOException iox) {
System.out.println("Error when reading file");
System.exit(2);
}
}
It is a design issue to decide if code should deal with an exception itself, or pass it up the execution
chain for other code to deal with.
Defining your own exceptions

When writing methods in your own classes, you may realise an exception might occur, but there is
no subclass of Exception which is appropriate - this is usually the case. The solution is to write your
own. This would be a subclass of Exception if you want it to be checked, or of RuntimeException for
unchecked.

For example, suppose you defined a Pixel class. This would need red, green, blue and alpha
(transparency) components, each in the range 0 to 1. But what if code attempted to instantiate a
pixel with a component out of range? One solution would be to define and throw a
BadPixelException:


class Pixel {

double red, green, blue, alpha;

Pixel(double red, double green, double blue, double alpha) throws BadPixelException {
if (red < 0 || red > 1) {
throw new BadPixelException();
}
if (green < 0 || green > 1) {
throw new BadPixelException();
}
if (blue < 0 || blue > 1) {
throw new BadPixelException();
}
if (alpha < 0 || alpha > 1) {
throw new BadPixelException();
}
this.red = red;
this.green = green;
this.blue = blue;
this.alpha = alpha;
}
}

class BadPixelException extends Exception {

public String getMessage() {
return "Bad pixel";
}
}
This might be used like:

Java
Page 224 - Copyright 2012 Walter Milner - all rights reserved
public static void main(String[] args) {
Pixel pixel = null;
try {
pixel = new Pixel(1.5, 0.5, 0.5, 0);
} catch (BadPixelException bpe) {
System.out.println(bpe.getMessage());
}
}

Java
Page 225 - Copyright 2012 Walter Milner - all rights reserved
Multi-threading
What is concurrency?
In a quick phrase, the computer doing several things at once.
Background
In 1957 the UNIVAC II computer was on sale, from Remington Rand. It had 2k to 10k memory and
could do 5236 additions in a second. The average installation cost $1 240 000, and it took 18 to 24
months to deliver. This was one of
the most powerful models then
available.
With such a high price and limited
power, attention was paid to how
best to use such machines. One
idea was time-sharing. The
machine was connected to many
terminals - keyboards and teletype
printers, so that many people
could use it. Each user in turn got
a timeslice of a few milliseconds.
From their point of view, it appeared they had exclusive use of a million dollar computer.
This had to be managed by the operating system. Each user's program and data had to be kept
separate from the others, and at the start of the timeslice it had to somehow continue from where it
was paused at the end of the previous timeslice.
This was the start of multi-processing - one computer doing several tasks at the same time.
Modern multi-processing
The user of a PC or laptop or smartphone today now takes it for granted that they will be able to
have wordprocessing and a spreadsheet and an email client running at the same time. We now have
one user and one OS, but several applications, background processes and maybe several processors
in use. The OS will manage the memory allocations for this, and the time scheduling. These are
known as heavyweight processes. Heaveyweight processes usually do not share memory or data.
Heavyweight processes
Java
Page 226 - Copyright 2012 Walter Milner - all rights reserved
We are only concerned with the JVM, running our Java application. The OS sees this as a single
heavyweight process, but the JRE can run the app as several threads. When it starts main executing,
this runs in one thread. But other threads can also be started, if our program makes that happen.
The runtime schedules the time management of these threads, and they will usually share data
values in common memory:

Running a new thread
When a Java application starts, it has a single thread. The runtime will also run many other threads,
but the application just has one. How do we start an extra thread in our application? There are two
methods.
Sub-classing Thread
There is a class called Thread, which has a method called run(), which is what happens when the
thread executes. We can subclass Thread and override run() to make our thread do what we want.
We start the thread by calling its start() method:
class Test {
public static void main(String[] args) {
MyThread thread = new MyThread();
thread.start();
}
}

class MyThread extends Thread
{
public void run()
{
System.out.println("Thread has run");
}
}
The thread ends when the run method ends.
Implementing Runnable
The second, and better, method is to write a class which implements the Runnable interface. This
interface has just one method, which is run(), in which you put what you want the thread to do. You
instantiate this class to create a Runnable object, then make a new Thread, passing the Runnable
object to its constructor. Then you start the new Thread:
Java lightweight threads
Java
Page 227 - Copyright 2012 Walter Milner - all rights reserved
class Test {
public static void main(String[] args) {
Runner runner = new Runner(); // make a Runner
Thread newThread = new Thread(runner); // make a Thread linked to the Runner
newThread.start(); // start the new Thread
}
}
class Runner implements Runnable
{
public void run()
{
System.out.println("Thread has run");
}
}
This method is better than subclassing Thread. This is because if your class subclasses Thread, it
cannot subclass anything else. But your class that implements Runnable can subclass anything, and
can also implement additional interfaces.
Threads are not function calls
It is tempting to think of a thread as a method invocation or function call, but it is not. For example,
if we run three threads:
class Test {

public static void main(String[] args) {
Runner runner1 = new Runner(1);
Runner runner2 = new Runner(2);
Runner runner3 = new Runner(3);
Thread newThread1 = new Thread(runner1);
Thread newThread2 = new Thread(runner2);
Thread newThread3 = new Thread(runner3);
newThread1.start();
newThread2.start();
newThread3.start();
}
}

class Runner implements Runnable
{
int id;
Runner(int id)
{
this.id=id;
}
public void run()
{
System.out.println("Thread ID:"+id);
}
}
you might think that
newThread1.start();
starts and completes, and then
newThread2.start();
starts and completes, then
newThread3.start();
But if you run this code, the output is sometimes
Thread ID:1
Thread ID:3
Thread ID:2
Java
Page 228 - Copyright 2012 Walter Milner - all rights reserved
but not always. Sometimes the sequence is 1 2 3, which is what you probably expected. These three
threads run at the same time. The runtime schedules the execution of the threads, in an
unpredictable sequence. This means concurrent programming introduces a completely new element
- execution can be indeterminate. The output is not the same every time it is run.
Why Use Threads?
Because
1. They make more efficient use of processor time, because if the application must wait for some
external event to happen, the processor can do the waiting in one thread, while executing other
code in another thread.
2. It is natural to think of the application doing more than one thing at a time. For example, in Tetris
the blocks should fall down at the same time as the user presses keys.
For example, suppose we have an application which should monitor a folder for the presence of
some file, and process it when it arrives. Meanwhile it should do something else. The following code
will wait for the appearance of 'test.txt' in folder c:/temp. When it finds it, it processes it and deletes
it. Meanwhile the main thread will run until the user enters 'q', at which point the file watcher stops,
if it is still running, and the application stops.
The run() of the thread uses Thread.sleep(1000); which makes the current thread go to sleep for
1000 milliseconds or 1 second (during which time main is doing something). A sleeping thread can be
interrupted - in this case, the file watcher then stops.
The loop
while (!file.exists())
{
could have been in main, with no extra thread. But with that structure, the application can do
nothing except wait for the file. Here is main, which starts the other thread, then takes keyboard
input, until it gets "q", in which case it interrupts the other thread:
class Test {
public static void main(String[] args) {
Thread thread = new Thread(new FileWatcher());
thread.start();
Scanner scanner = new Scanner(System.in);
String key;
while (true)
{
key=scanner.nextLine();
if (key.equals("q"))
{
thread.interrupt();
return;
}
}
}
}
Here is the second thread:
Java
Page 229 - Copyright 2012 Walter Milner - all rights reserved
class FileWatcher implements Runnable
{
File file = new File("C:////temp//test.txt");
public void run()
{
while (!file.exists())
{
try
{
Thread.sleep(1000);
}
catch (InterruptedException ie)
{
System.out.println("Ended with no file");
return;
}
}
System.out.println("Got file");
// process file..
file.delete();

}
}
Data shared between threads
Consider this:
class Test {

public static void main(String[] args) {
Process p = new Process();
Thread thread1 = new Thread(p);
Thread thread2 = new Thread(p);
thread1.start();
thread2.start();
System.out.println(p.c);
}
}

class Process implements Runnable {
long c = 0;
public void run() {
c += 1;
System.out.println("Finished");
}
}
We only have one Process object, and we run two threads on it, both of which change c. The run()
method increments c, so we might get the output Finished Finished
2, if the sequence is as shown.
But we might also get 0 Finished Finished, if main finishes before
thread1 or thread2:
We can also get Finished 1 Finished, if thread1 completes first, then
main, then thread2.
Harder to explain is Finished Finished 1, which is also possible. How
can thread1 and thread2 complete, yet c is only 1?
It happens because of c+=1. Execution of this involves three steps:
thread1, thread2 and main
main, thread1 then thread2
Java
Page 230 - Copyright 2012 Walter Milner - all rights reserved
get the value of c, add 1 to c, and store the result back in c. The sequence might be:
thread1 gets the value of c =0
thread2 gets the value of c=0
thread1 calculates c+1 = 1
thread2 calculates c+1 = 1
thread1 stores 1 in c
thread2 stores 1 in c
so the threads have executed c+=1 twice, but c is only 1.
This is equivalent to database sharing problems. Two users read the same database, then both
update it. But the update of the first is overwritten by the upate of the second.
The database problem is solved by some kind of locking so that only one user can use the database
at a time.
The point is that shared data will be processed in an unpredictable way, unless thread sequencing
has some kind of co-ordination.
The Thread class
We can pass a name to a Thread in its constructor, and a thread's toString will use it:
Thread thread = new Thread("My thread");
System.out.println(thread);
The output from this is Thread[My thread,5,main] - the name of the thread, its priority level ( 1 to
10, which the scheduler uses when choosing which thread to run when), and its threadgroup -
discussed later.
We can make a thread a daemon. Usually an application will run until System.exit() is called, or all
threads, including main, have ended. Threads normally end when their run() method has ended. So
an application with a thread with an endless loop in the run will not end:
..
Thread thread = new Thread(new Process());
thread.start();
..

class Process implements Runnable {
public void run() {
while (true);
}
}
But daemon threads do not count - an application will end even if daemon threads are still running
(and they will then be stopped). So
thread.setDaemon(true);
means this stops when main ends. The idea is that a daemon thread can provide services to other
threads, but we do not need to remember to end them.
Sleep and interrupt
Thread has an interrupt method. A thread can invoke the interrupt method of another thread. This is
useful if the thread carries out some long process, such as reading a file across a network. We want
to set the thread on this task, and be alerted (by an interrupt) when it has finished.
Java
Page 231 - Copyright 2012 Walter Milner - all rights reserved
What does the calling thread do while it waits for the service thread? It can go into an endless loop
as it waits to be interrupted - but this wastes processor power. Better is to invoke the sleep method,
which puts the current method to sleep for a length of time - with the expectation that the service
will interrupt the sleep when it completes and interrupts.
So what happens is
the service thread is started
we go to sleep for a length of time
maybe we are interrupted by the service completing in the set time - we carry on
if we are not (service took too long) we carry on without the service

Why must the service provider be a thread? Why can't it be a normal class, with a suitable method
call, and we just have a return from that method? Because we expect the service to take a long time,
maybe waiting for another computer on the network. If its a normal method call, our machine halts
waiting for the network. If its a thread - on our machine other threads will still run, and we will not
waste processor time waiting.
For example - suppose we have a Service thread that fetches a file. We will allow a maximum of 20
milliseconds to complete it. When the Service thread finishes, it must interrupt the thread that
called it. So we need to pass a reference to the current thread to it, so it knows what to interrupt.
Thread.currentThread() gives us that. Here is the main thread:
class Test {
public static void main(String[] args) {
Thread mainThread=Thread.currentThread();
Thread thread = new Thread(new Service(mainThread));
thread.start();
try
{
Thread.sleep(20);
System.out.println("Service timed out");
}
catch (InterruptedException ie)
{
System.out.println("Service completed");
}
}
}
And here is the service thread. It has a do-nothing loop to simulate the activity which it must do, like
fetching a file:
Java
Page 232 - Copyright 2012 Walter Milner - all rights reserved
class Service implements Runnable {
Thread whatToInterrupt;
Service(Thread t)
{
whatToInterrupt=t;
}
public void run() {
// simulate time taken for the service
for (int i=0; i<10000000; i++);
whatToInterrupt.interrupt();
}
}
Perils of multi-threading
Habits of thought which develop after conventional single-threaded programming experience lead
to pitfalls when multi-threading.
We look at this with an example. Suppose we have an online eCommerce app. We have a stock level
of items for sale. A customer can log on and choose to buy. We need to check there are goods in
stock, and if so, sell one an dreduce the stock level by one.
Since it is online, we may have 100 customers at the same time. We simulate this by having a Selling
class, instances of which are a thread which does the selling process, and we run 100 threads at the
same time. Here is main:
class Test {

Stock stock = new Stock();

public static void main(String[] args) {
Test test = new Test();
Selling[] seller = new Selling[100];
for (int i = 0; i < 100; i++) {
seller[i] = new Selling(test);
seller[i].start();
}

System.out.println(test.stock.level);
}
}
The Stock class is just:
class Stock {
int level = 100;
}
and the Selling thread is:
Java
Page 233 - Copyright 2012 Walter Milner - all rights reserved
class Selling implements Runnable {

Thread thread;
Test owner;

Selling(Test owner) {
thread = new Thread(this);
this.owner = owner;
}

void start() {
thread.start();
}

synchronized void sell() {
}

public void run() {

for (int i = 0; i < 1000; i++) {
// got any in stock?
if (owner.stock.level > 0) {
// customer thinks about it
for (int j = 0; j < 10000; j++);
// and buys one
owner.stock.level--;
}
}
}
}
Is this correct? No.
The first problem is thinking of a thread start as a function call, which will not return until after
completion. So in main:

Selling[] seller = new Selling[100];
for (int i = 0; i < 100; i++) {
seller[i] = new Selling(test);
seller[i].start();
}

System.out.println(test.stock.level);
It looks like we run 100 threads, and then output the stock level. But in fact we just start 100 threads
then output the stock level - possibly before all 100 threads have completed.
How to fix this? We could count the completed threads, and not go onto the print in main until 100
have completed:
class Test {

Stock stock = new Stock();
int completedThreadCount = 0;

public static void main(String[] args) {
.. start 100 threads
while (test.completedThreadCount < 100)
{
try{Thread.sleep(10);} // pause for 10 milliseconds
catch (InterruptedException ie)
{System.out.println(ie);}
}
System.out.println(test.stock.level);
}
}
and
Java
Page 234 - Copyright 2012 Walter Milner - all rights reserved
class Selling implements Runnable {

..

public void run() {

..
owner.completedThreadCount++;
System.out.println(owner.completedThreadCount + " threads completed");
..
}
}
Is this correct? Usually - but here is some sample output:
94 threads completed
95 threads completed
90 threads completed
99 threads completed
89 threads completed
87 threads completed
-3
100 threads completed
97 threads completed
98 threads completed
96 threads completed
93 threads completed
Before reading on, try to work out how this could come about.
The -3 is the final stock level. We will come back to why it is negative. This output comes as 100
threads are completed. But how come 97 are completed after 100, when each thread just
increments the completed count?
The problem is:
owner.completedThreadCount++;
This reads the current value of
completedThreadCount, adds one, and
stores the result. But during the
execution of that statement, other
threads are also executing. The
sequencing of those threads is
controlled by the JRE. What has
happened, among other things, is as
shown.
What we need is some way to ensure
that during this statement, no other
thread can 'but in.'
Synchronized statement
This is a Java keyword which we can apply to a statement. We say:
Thread sequence
Java
Page 235 - Copyright 2012 Walter Milner - all rights reserved
synchronized (someObject)
<statement> ;
Then first the object is locked, the statement executes, with exclusive access to the object, then the
lock is released. First in, some other thread might hold the lock, in which case our thread must wait
until the other thread releases it. The statement might be a block.
In our example, we need to say
synchronized (owner) {
owner.completedThreadCount++;
System.out.println(owner.completedThreadCount + " threads completed");
}
completedThreadCount is an attribute of the 'owner' object, so getting a lock on this fixes the
problem, and the thread count goes up to 100 as expected, every time.
This code may require one thread to wait on another, so it is slower - but it is thread-safe : that is, it
works correctly with several threads running.
But we still have the problem that we can get a negative stock level, even though every thread
checks there is some in stock before selling one:
97 threads completed
98 threads completed
99 threads completed
100 threads completed
-3
But now we know why - after one thread has checked the stock level is >0, another thread does the
same, sells one, then the first thread sells one also. We can fix that again using synchronized:

synchronized (owner) {
for (int i = 0; i < 1000; i++) {
// got any in stock?
if (owner.stock.level > 0) {
// customer thinks about it
for (int j = 0; j < 10000; j++);
// and buys one
owner.stock.level--;
}
}
}
Synchronized method
As well as making a statement synchronized, we can also apply that to a whole method.
In that case, the lock is acquired on the object executing the method. In our case, the lock needs to
be on the stock level, so we need to switch the selling method into the Stock class:
Java
Page 236 - Copyright 2012 Walter Milner - all rights reserved
class Stock {

int level = 100;

synchronized void sell() {
for (int i = 0; i < 1000; i++) {
// got any in stock?
if (level > 0) {
// customer thinks about it
for (int j = 0; j < 10000; j++);
// and buys one
level--;
}
}
}
}
and the Selling thread run has to say:
public void run() {

owner.stock.sell();
..
}
It could be argued this approach is less logical, since the sell method is concerned with the sell
thread, not the stock object.

Java
Page 237 - Copyright 2012 Walter Milner - all rights reserved
Classes and types
Earlier we said 'a class is a type of object'. That was an attempt to provide a simple idea of what a
class is, to a beginner. It does not work for purely static classes. Neither does it correspond to a more
precise idea of 'type'.
Suppose we say
Object obj = "Hello";
We are declaring obj to be an Object, but we are assigning a String to it. Can we do that? Yes.
What about
String obj = new Object();
No. We get a compile-time error - "Incompatible types".
It depends on the class hierarchy. We can say
<base class> ref = new <subclass>
but not
<subclass> ref = new <baseclass>
How come? Because of the way inheritance works, a subclass instance will be able to do everything
a base class can, so the compiler can be happy that in the first case, if we tell ref to do one of its
methods, the subclass object will be able to do so. But a subclass may have methods which the base
class did not have, so in the second case we may ask ref to do a method which the base object does
not possess. For example
String obj = new Object();
char c = obj.charAt(0);
will not work, since Object does not have a charAt method.
How about
Object obj = "Hello";
char c = obj.charAt(0);
Another fail - cannot find symbol - method charAt. We have told the compiler that obj is an Object,
and Object does not have a charAt method. But we know that a String does. How about
Object obj = "Hello";
char c = ( (String) obj).charAt(0);
No problem, at compile-time or run-time. How about
Object obj = new Integer(2);
char c = ( (String) obj).charAt(0);
No compile-time error. But when we run it, a ClassCastException is thrown - an Integer cannot be
cast to a String (and this is an unchecked exception so it might come as a surprise). Why is there no
compile-time error? We have told the compiler that ref is an Object. Then can an Object be cast to a
String? Sometimes, as the previous example showed. But that was when it was actually a String. In
this case obj is actually a Integer, and it is impossible to cast an Integer to a String.
Java
Page 238 - Copyright 2012 Walter Milner - all rights reserved
"Variables have types, objects have classes."
The Java Language Specification says
In the Java programming language, every variable and every expression has a type
that can be determined at compile-time. The type may be a primitive type or a
reference type. Reference types include class types and interface types. Reference
types are introduced by type declarations, which include class declarations (8.1)
and interface declarations (9.1). We often use the term type to refer to either a
class or an interface.
In the Java virtual machine, every object belongs to some particular class: the class
that was mentioned in the creation expression that produced the object (15.9), or
the class whose Class object was used to invoke a reflective method to produce the
object, or the String class for objects implicitly created by the string concatenation
operator + (15.18.1). This class is called the class of the object. An object is said
to be an instance of its class and of all superclasses of its class.
For example
Object ref = new Integer(3);
The variable is 'ref'. The type of 'ref' is Object, since that was how it was declared - its 'compile-time
type'.
There is also an object here - the one created by the 'new Integer(3)'. The class of that object is
Integer, since that was mentioned in the 'creation expression'. A reference is a hidden pointer, so
the situation can be shown as:

Suppose we have
Object obj = new Integer(3);
obj = "Hello";
Then after this the situation is:
Java
Page 239 - Copyright 2012 Walter Milner - all rights reserved

The type of ref is still Object. Its value is an object with a different class - a String. The Integer object
might be garbage collected if appropriate.
Interfaces
The JLS says:
Even though a variable or expression may have a compile-time type that is an
interface type, there are no instances of interfaces. A variable or expression whose
type is an interface type can reference any object whose class implements (8.1.5)
that interface.
So that you cannot say:
ActionListener listener = new ActionListener();
This makes sense, since an interface has no method implementations, so 'listener' would not 'know'
how to do the required methods. But we can say:

ActionListener listener = new MyListener();

..

class MyListener implements ActionListener {

public void actionPerformed(ActionEvent e) {
//whatever
}
}
Here the type of the variable listener is ActionListener, which is an interface not a class. But the
value of 'listener' (what it refers to) is an object, with class MyListener, which implements the
ActionListener interface.
Automatic conversions and casts
A change of type is either an automatic conversion, like
Object obj = new Integer(3);
or an explicit typecast like
Object obj = (Object) new Integer(3);
Some conversions are allowed, some are not. Some produce compile-time errors, some runtime
exceptions. Here we go. Suppose we have (with Base extending Object)
Java
Page 240 - Copyright 2012 Walter Milner - all rights reserved
class Base
{}

class Sub extends Base
{}
Firstly automatic conversions:
Base a = new Base(); // OK
Base b = new Sub(); // OK - can convert to a base class
Base c = new Object(); // compile-time Incompatible types.
// Can't convert to a subclass
Integer j = "wwww"; // compile-time Incompatible types
// Can't convert to an unrelated class
This make sense. We can convert to a base class, because a subclass can do everything a base class
can. You cannot convert to a subclass, since a subclass may have methods which a base class cannot
do. You cannot convert between unrelated classes (where one is not a subclass of the other) for the
same reason. These are all compile-time errors so there is little to worry about.
For explicit casts, you might get compile-time or run-time, and it might be because the cast fails, or
the assignment:

Base d = (Base) new Sub(); // OK - cast to a base class
a) Base e = (Base) new Object(); // run-time class cast exception
b) Object f = (Base) new Object(); // runtime
Object g=(Object) new Base(); // OK - cast to a base class
c) Base h=(Object) new Base(); //No compile time Incompatible types
d) Sub i= (Object) new Base(); // no compile time
(a) fails because you cannot convert a base class to a subclass, since the subclass might have
members which the base class does not.
(b) fails for the same reason - the conversion not the assignment, so it does not matter what you
assign to.
(c) fails because of the assignment - you cannot assign a base class to a subclass.
(d) fails for the same reason



Java
Page 241 - Copyright 2012 Walter Milner - all rights reserved
Input and Output
Java treats all of the following as examples of I/O
reading input from the keyboard
writing characters to the screen
reading or writing a file
reading or writing through a Socket to another computer, possibly using http, possibly over
the internet.

Files differ in content and structure. A text
file is a sequence of characters, some of
which are newline, so the file can be thought
of as a series of lines of text. A file might
instead contain other primitive types, in
binary format. It might be a mixture of these,
perhaps in a format like a Word file or a jpg
image file. It might contain some Java
objects.
The file might be located on a local drive like
'drive c' on Windows, or on a USB stick
looking like a drive letter. The drive might be
mapped to the network, so the file might be
located on another computer.
There is a hierarchy of classes to deal with
this, with appropriate methods. These are
mirrored - a set of classes for input, and a
corresponding set for output.
A new set of I/O classes, called NIO, was
introduced in Java 1.4, and another set as
NIO2 in Java 7. These are covered elsewhere.
Reading and writing bytes

A FileOutputStream has methods for writing bytes to a file. Of course all data consists of one or
more bytes, but FileOutputStream can write a byte explicitly.
In the following, a stream is opened when the FileOutputStream is constructed. It is important that
after use, the stream is also closed, as quickly as possible. Otherwise system resources are used
wastefully - and if a buffer is used, data may never actually be written.
Not quite so new
Java
Page 242 - Copyright 2012 Walter Milner - all rights reserved
byte a = 1;
byte b = 2;
byte c = 3;
// write data
FileOutputStream out = null;
try {
out = new FileOutputStream("c:/temp/out.dat");
out.write(a);
out.write(b);
out.write(c);
out.close();
} catch (FileNotFoundException fex) {
System.out.println("File not found");
} catch (IOException fex) {
System.out.println("Error writing");
}
// read data
FileInputStream in = null;
try {
in = new FileInputStream("c:/temp/out.dat");
int d;
while ((d = in.read()) != -1) {
System.out.println(d);
}
out.close();
} catch (FileNotFoundException fex) {
System.out.println("File not found");
} catch (IOException fex) {
System.out.println("Error reading");
}

The read() method returns an int, when it actually reads byte. This is so that it can return -1 if it is
told to read, and the end of the file has been reached. Normally the byte read is the least significant
of the 4 bytes in the int.
In
out = new FileOutputStream("c:/temp/out.dat");
If the file already exists, it would first be deleted. Another constructor:
out = new FileOutputStream("c:/temp/out.dat", true);
instead appends data to an existing file.

Reading and Writing Characters

For reading and writing characters into a file, the FileReader and FileWriter are more appropriate.
You could split chars into 2 bytes and write them as such, but FileWriter alows you to write a String
at a time:
Java
Page 243 - Copyright 2012 Walter Milner - all rights reserved
String line1 = "Line one";
String line2 = "Line two";
// write data
FileWriter out = null;
try {
out = new FileWriter("c:/temp/out.chars");

out.write(line1);
out.write("\n");
out.write(line2);
out.write("\n");
out.close();
} catch (FileNotFoundException fex) {
System.out.println("File not found");
} catch (IOException fex) {
System.out.println("Error writing");
}
// read data
FileReader in = null;
try {
in = new FileReader("c:/temp/out.chars");
int d;
while ((d = in.read()) != -1) {
System.out.print((char) d);
}
in.close();
} catch (FileNotFoundException fex) {
System.out.println("File not found");
} catch (IOException fex) {
System.out.println("Error reading");
}

}
Note how we have written new line characters '\n' after each 'line'.
A primitive char is always a 16-bit Unicode, but characters written to a file may have a different
character set. FileReader/Writer uses the default - which you can find by:
Charset def = Charset.defaultCharset();
System.out.println(def);
on the machine this is being written on, that is UTF-8. To use a specific charset, you must use
OutputStreamWriter or InputStreamReader, such as:
try {
FileOutputStream fos = new FileOutputStream("c:/temp/test.txt");
Charset charSet = Charset.forName("UTF-16LE");
OutputStreamWriter osw = new OutputStreamWriter(fos, charSet);
osw.write("AB"); // A B and Arabic beh = Unicode 0628
osw.close();
FileInputStream fis = new FileInputStream("c:/temp/test.txt");

InputStreamReader isr = new InputStreamReader(fis, charSet);

int i;
while ((i = isr.read()) != -1) {
System.out.println(Integer.toHexString(i) + " " + (char) i);
}
isr.close();

} catch (Exception e) {
System.out.println(e);
}
output:
41 A
42 B
628
Java
Page 244 - Copyright 2012 Walter Milner - all rights reserved
UTF-16LE is 16 bit, with LE meaning LittleEndian - the lower order byte is stored first. See the API for
more details.
Buffered streams
Reading and writing single bytes or characters to a device is very inefficient compared to using a
buffer. The idea is that an area of memory called a buffer is used. Data to be written is placed in the
buffer, and the buffer is only actually written to the device when the buffer is full (or it is 'flushed').
This greatly reduces the number of I/O operations with their associated overheads.
We can do this simply using a BufferedReader/Writer object, constructed by wrapping a
FileReader/Writer:
String line1 = "Line one";
String line2 = "Line two";
// write data
BufferedWriter out = null;
try {
out = new BufferedWriter(new FileWriter("c:/temp/out.chars"));

out.write(line1);
out.write("\n");
out.write(line2);
out.write("\n");
out.close();
} catch (FileNotFoundException fex) {
System.out.println("File not found");
} catch (IOException fex) {
System.out.println("Error writing");
}
// read data
BufferedReader in = null;
try {
in = new BufferedReader(new FileReader("c:/temp/out.chars"));
int d;
while ((d = in.read()) != -1) {
System.out.print((char) d);
}
in.close();
} catch (FileNotFoundException fex) {
System.out.println("File not found");
} catch (IOException fex) {
System.out.println("Error reading");
}


Reading and Writing Primitives
We can do I/O with the other primitive types using a DataInputStream and DataOutputStream.
There is an issue with this, since readInt() cannot return -1 to signal the end of file, since -1 might be
a valid data value. One approach to this is read until an end of file exception, but it is not
straightforward to distinguish between this and an unexpected end of file, say because the drive has
failed in the middle of a read.
The approach used here is to preceed the actual int writes by a count of how many there will be.
Then the read first reads that number, then continues to iterate the reading of that number of actual
data ints. This way an end of file exception could only be caused by some kind of failure:

Java
Page 245 - Copyright 2012 Walter Milner - all rights reserved
int[] data = {1, 2, 3, 4, 5};
// write data
DataOutputStream out = null;
try {
out = new DataOutputStream(new FileOutputStream("c:/temp/out.int"));
out.writeInt(data.length); // write record count
for (int i = 0; i < data.length; i++) {
out.writeInt(data[i]);
}
out.close();
} catch (FileNotFoundException fex) {
System.out.println("File not found");
} catch (IOException fex) {
System.out.println("Error writing");
}
// read data
DataInputStream in = null;
try {
in = new DataInputStream(new FileInputStream("c:/temp/out.int"));
int recordCount = in.readInt(); // read record count
int d;
for (int i = 0; i < recordCount; i++) {
d = in.readInt();
System.out.println(d);
}
} catch (FileNotFoundException fex) {
System.out.println("File not found");
} catch (EOFException fex) {
System.out.println("Unexpected end of file");
} catch (IOException fex) {
System.out.println("Error writing");
}
}

Reading and Writing Objects

An ObjectOutputStream can be used to write objects of any class. For this, the class has to declare
that it implements Serializable. In fact this is just a 'marker interface' with no methods. It just
enables the compiler to check that you will read and write objects of a class which should be.
Having constructed an ObjectOutputStream, you can just writeObject() into it, and readObject in
reverse.
You can also write primitives into an ObjectOutputStream, so it is possible to use the technique of
writing the number of objects, followed by the actual objects.
Java
Page 246 - Copyright 2012 Walter Milner - all rights reserved
class Test {

public static void main(String[] args) {
MyClass obj1 = new MyClass(5, "Testing");
// write data
ObjectOutputStream out = null;
try {
out = new ObjectOutputStream(new BufferedOutputStream(new
FileOutputStream("c:/temp/out.objects")));
out.writeObject(obj1);

out.close();
} catch (FileNotFoundException fex) {
System.out.println("File not found");
} catch (IOException fex) {
System.out.println("Error writing");
}
// read data
MyClass obj2 = null;
ObjectInputStream in = null;
try {
in = new ObjectInputStream(new BufferedInputStream(new
FileInputStream("c:/temp/out.objects")));
obj2 = (MyClass) in.readObject();

out.close();
obj2.display();
} catch (ClassNotFoundException c) {
System.out.println("Class not found");
} catch (FileNotFoundException fex) {
System.out.println("File not found");
} catch (IOException fex) {
System.out.println("Error writing");
}
}
}

class MyClass implements Serializable {

int x;
String s;

MyClass(int x, String s) {
this.x = x;
this.s = s;
}

void display() {
System.out.println(s + " " + x);
}
}
class Test {

public static void main(String[] args) {
MyClass obj1 = new MyClass(5, "Testing");
// write data
ObjectOutputStream out = null;
try {
out = new ObjectOutputStream(new BufferedOutputStream(new
FileOutputStream("c:/temp/out.objects")));
out.writeObject(obj1);

out.close();
} catch (FileNotFoundException fex) {
System.out.println("File not found");
} catch (IOException fex) {
System.out.println("Error writing");
}
// read data
MyClass obj2 = null;
ObjectInputStream in = null;
try {
in = new ObjectInputStream(new BufferedInputStream(new
FileInputStream("c:/temp/out.objects")));
Java
Page 247 - Copyright 2012 Walter Milner - all rights reserved
obj2 = (MyClass) in.readObject();

out.close();
obj2.display();
} catch (ClassNotFoundException c) {
System.out.println("Class not found");
} catch (FileNotFoundException fex) {
System.out.println("File not found");
} catch (IOException fex) {
System.out.println("Error writing");
}
}
}

class MyClass implements Serializable {

int x;
String s;

MyClass(int x, String s) {
this.x = x;
this.s = s;
}

void display() {
System.out.println(s + " " + x);
}
}
When the object is written to the file, the name of the class is written, followed by the value of the
fields. When the object is read, there is a check that the class is known - which might fail. This is why
a ClassNotFound exception needs to be caught.
A MyClass object has a String field, which is itself an object. So we might be saving an object which
contains several other objects, each of which contains several other objects and so on. This means
that in general a graph of objects needs to be written. This will work, provided each class is declared
to implement the Serializable interface.
Command line I/O

The class System represents the system the application is executing on. It has a static data field
name 'out', which is an instance of PrintStream, which is a subclass of OutputStream. A PrintStream
has a method println - hence the familar
System.out.println("Hello world");
It also has the less familiar printf:
double x=3;
System.out.printf("x = %f \n", x);
which imitates the corresponding C function in stdio.h
There is also the standard error stream:
System.err.println("It's all gone wrong");
but this normally maps to standard out.
Java
Page 248 - Copyright 2012 Walter Milner - all rights reserved
For input, there is System.in, but this takes some work to actually input something. In Java 5 the
Scanner class was introduced. An instance of this parses an input stream, separating it into
primitives and strings - like
Scanner scanner = new Scanner(System.in);
int x;
x=scanner.nextInt();
Java
Page 249 - Copyright 2012 Walter Milner - all rights reserved
Reflection
The idea of Reflection is to programmatically get information relating to classes.
Typically we have code like
String s = "Hello";
and we know what class s is by looking at the code. But if we cannot do that - how could we find out
about the s object using Java code? That is what the Reflection API is.
We start with the Class object, which represents a class (Class is a class, instances of which
represents classes. Concentrate.)
There are two common ways to get a Class - getClass and forName()

String s="Hello";
Class c = s.getClass();
System.out.println(c); // class java.lang.String
try
{
c=Class.forName("java.lang.Integer");
System.out.println(c); // class java.lang.Integer
}
catch (ClassNotFoundException cnf)
{
System.out.println("We've lost Integer");
}
Note the forName must be the fully qualified name - Integer is not found.
Once we have a Class, we can get information about it:

try
{
Class c = Class.forName("javax.swing.plaf.basic.BasicBorders");
Class d=c.getSuperclass();
System.out.println(d); // class java.lang.Object
Class[] e = c.getClasses();
for (Class f:e)
System.out.println(f); // ButtonBorder, FieldBorder, MarginBorder...
Method[] methods = c.getDeclaredMethods();
for (Method f:methods)
System.out.println(f); // getButtonBorder, getInternalFrameBorder, getMenuBarBorder.
}
catch (ClassNotFoundException cnf)
{ System.out.println("Class not found");}

getClass returns the runtime class of the object, not the compile-time type of the variable. For
example:
Java
Page 250 - Copyright 2012 Walter Milner - all rights reserved
class Test {

public static void main(String[] args) {
Base b = new Sub(); // automatic conversion
Class c = b.getClass();
System.out.println(c); // get Sub not Base
}
}

class Base {
}

class Sub extends Base {
}

Using Reflection
Usually we would only store a single type in a collection - say an ArrayList of Strings. We woudl do
this with a type parameter:
ArrayList<String> strings = new ArrayList<String>();
Suppose for some reason we want to store 2 types in the same list - a mixture of Strings and Integers
say. The problem is that when we retrieve them, how do we know which type it is? Use reflection:
ArrayList list = new ArrayList();
list.add("One");
list.add("Two");
list.add("Three");
list.add(new Integer(1));
list.add(new Integer(2));
list.add(new Integer(3));
try {

for (Object obj : list) {
if (obj.getClass() == Class.forName("java.lang.String")) {
System.out.println("String : " + obj);
}
if (obj.getClass() == Class.forName("java.lang.Integer")) {
System.out.println("Integer : " + obj);
}
}
} catch (ClassNotFoundException cnf) {
}
outputs:
String : One
String : Two
String : Three
Integer : 1
Integer : 2
Integer : 3
Java
Page 251 - Copyright 2012 Walter Milner - all rights reserved
Networking - UDP
Protocols
When you answer a phone call, you probably say your name, or 'Hello', or something similar. The
caller expects this - it tells them the call has been picked up. This is an example of a protocol - a set
of rules about how communication will take place.
Digital communication is based on protocols. A very common one is HTTP - hyper-text transfer
protocol. This is the basis for the operation of the 'world-wide web'. FTP is file transfer protocol.
And so on.
TCP/IP and UDP
The internet and most LANs use a set of protocols called TCP/IP, the Internet protocol suite.
One of those is UDP - User Datagram Protocol. This is very simple. The sender constructs a packet of
up to 64k of data, and sends it.The packet includes the IP address of the source and the destination.
The reciever checks for packets whose destination matches their address, and picks up the data.
That's it.
So this is very much like sending something by postal mail - you just put the address on it and send
it.
This is simple but limited. The sender does not know if the packet is received. The sender might reply
with an acknowledgement, but this is not part of the UDP protocol.
Since 64k is not much (for a graphics image, say), so you might send a set of packets. But there is no
guarantee they will arrive in the same sequence they are sent. You could put sequence numbers in
the packets, and the receiver could then check they are all there and re-arrange them if they are out
of sequence - but again this is not part of the UDP protocol.
There are Java Foundation classes for sending and receiving UDP packets.
Ports
A port is just a number (0 to 65535). The purpose is to send different message streams over the
same cable (or wireless channel or other link). Different message streams use different port
numbers. This is a form of multiplexing.
The use of ports is controlled by an organisation called IANA. Port numbers 0 to 1023 are the 'well-
known ports'. For example, http normally runs on port 80. SMTP email transfer is on port 25.
Ports 1024 to 49151 are the registered ports - registered with IANA, mostly by commercial
organisations - for example, 2967 Syantec anti-virus.
49152 to 65535 cannot be registered, and so can be used for temporary purposes.
When we send a UDP packet, we must choose a port number to use (one not already in use). The
receiver needs to listen on that port.
Java
Page 252 - Copyright 2012 Walter Milner - all rights reserved
Sockets

A socket is a software construct for the end-point of a communication - send or recieve. A socket has
an IP address and a port number. Our software to use UDP must make a socket to send packets
through. Java has a set of classes to model sockets.
UDP example
To start with we will have two programs showing UDP send and receive, as simple as possible. Do
this as follows:
Run the two programs on different machines on the same network.
Start the receiver first. It waits to receive a packet. Then start the sender. The receiver
should show the data it receives.
You need to know the IP address of the reciever. ( ipconfig on Windows, /sbin/ifconfig on
Linux)
You may need to stop firewalls
The sender is:
try {
DatagramPacket packet;
DatagramSocket socket = new DatagramSocket(); // make a UDP socket
int port = 49152; // port to use
byte[] buf = "Hello".getBytes(); // convert string to array of bytes
// the receiver has IP address 172.16.1.37
InetAddress address = InetAddress.getByAddress(new byte[]{(byte) 172, 16, 1, 37});
// construct the packet
packet = new DatagramPacket(buf, buf.length,address, port);
socket.send(packet); // send it
} catch (Exception ex) {
System.out.println(ex);
}
This just makes a packet and sends it. The receiver is:
byte[] buffer = new byte[256]; // to receive data
try {
int port = 49152; // matching port
DatagramSocket socket = new DatagramSocket(port); // make a socket
// prepare a packet with this buffer
DatagramPacket packet = new DatagramPacket(buffer, buffer.length);
System.out.println("Listening");
// listen (forever) for a packet to this IP address on this port
socket.receive(packet);
System.out.println("Received : " + new String(buffer));

} catch (Exception ex) {
System.out.println(ex);
}
This needs to be run first - it just waits until it receives an appropriate packet.
Multicast sockets
The above is not very useful, since we do not usually know the IP address of the computer receiving
the message. We can overcome this by using a MulticastSocket, which can send a UDP packet which
can be received by any address looking in the same 'group':
Java
Page 253 - Copyright 2012 Walter Milner - all rights reserved
int port = 49155;
socket = new MulticastSocket(port);
group = InetAddress.getByName("224.0.0.2");
socket.joinGroup(group);
DatagramPacket packet;
packet = new DatagramPacket(buf, buf.length, group, port);
socket.send(packet);
..
socket.leaveGroup(group);
The group is identified by a Class D IP addresses are in the range 224.0.0.1 to 239.255.255.255,
inclusive.
We can use this as follows
One machine broadcasts its own IP address, then listens for a reply for 1 second
This is repeated until it gets a reply
The other machine listens for as multicast in this group. When it gets one, it sends back its
own IP address
After this, both machines have discovered the IP address of the other. Here is the code for the frist
machine. The listen process is:
static boolean listen() {
DatagramSocket socket = null;
byte[] buffer = new byte[4]; // to receive data
try {
int port = 49157; // matching port
socket = new DatagramSocket(port); // make a socket
socket.setSoTimeout(1000); // timeout after 1 second
// prepare a packet with this buffer
DatagramPacket packet = new DatagramPacket(buffer, buffer.length);
System.out.println("Listening");
// listen for 1 second for a packet to this IP address on this port
socket.receive(packet);
InetAddress ad= InetAddress.getByAddress(buffer);
System.out.println("Received from IP address " + ad);
socket.close();

} catch (SocketTimeoutException so) {
socket.close();
System.out.println("No answer");
return false;
} catch (Exception ex) {
socket.close();
System.out.println(ex);
}
return true;
}
We use this from main:
Java
Page 254 - Copyright 2012 Walter Milner - all rights reserved

public static void main(String[] args) {

MulticastSocket socket = null;
boolean answer = false;
byte[] buf = new byte[4];
// Get this machine's IP address
try {
InetAddress addr = InetAddress.getLocalHost();
byte[] ipAddr = addr.getAddress();
System.arraycopy(ipAddr, 0, buf, 0, 4);
} catch (UnknownHostException e) {
System.out.println("Can't get IP address");
}

InetAddress group = null;
try {
int port = 49155;
socket = new MulticastSocket(port);
group = InetAddress.getByName("224.0.0.2");
socket.joinGroup(group);
DatagramPacket packet;
packet = new DatagramPacket(buf, buf.length, group, port);
while (!answer) {
socket.send(packet);
System.out.println("Broadcasting");
answer = listen();
}
socket.leaveGroup(group);

} catch (Exception ex) {
System.out.println(ex);
} // end of broadcast and listen
} // end of main
The code for the other machine is:
public static void main(String[] args) {
byte[] buffer = new byte[4 ];
try {
int port = 49155;
MulticastSocket socket = new MulticastSocket(port);
InetAddress group = InetAddress.getByName("224.0.0.2");
socket.joinGroup(group);
DatagramPacket packet = new DatagramPacket(buffer, buffer.length);
System.out.println("Listening");
socket.receive(packet);
// buffer now contains IP address of other machine
System.out.println("Received : ");
reply(buffer);
socket.leaveGroup(group);
socket.close();

} catch (IOException ex) {
System.out.println("In main: "+ex);
}

}
and reply() is:
Java
Page 255 - Copyright 2012 Walter Milner - all rights reserved

static void reply(byte[] buffer) {
DatagramSocket socket = null;
try {
int port = 49157;
socket = new DatagramSocket(port);
// form address of other machine
InetAddress address = InetAddress.getByAddress(buffer);
byte[] buf = new byte[4];
try
{ // get our address into buf
InetAddress add = InetAddress.getLocalHost();
buf =add.getAddress();
}
catch (UnknownHostException uh)
{
System.out.println("Can't get address");
}
// send our address back
DatagramPacket packet = new DatagramPacket(buf, buf.length, address,port);
socket.send(packet);
socket.close();
} catch (IOException ex) {
System.out.println(ex);

}
}
The logic of this could be modified to turn the first machine into a server, finding clients on the
network. Typically a new thread would be started to 'talk' to each client.
Java
Page 256 - Copyright 2012 Walter Milner - all rights reserved
Networking - TCP
We have seen that UDP is like postal mail. You make a packet, write the address on it, and post it. It
might reach its destinantion.
TCP (Transmission Control Protocol) is like a phone call. You dial the number, and a connection is
established. You can talk and listen, then you hang up and the connection is closed.
TCP packets will be received in the order they are sent, and a missing packet can be detected.
TCP classes
Java has a Socket class to model a TCP socket. This has getInputStream and getOutputStream
methods to get i/o streams so that sockets can be written to and read from.
But how to start up? There is a need for a mechanism whereby a machine can wait for a connection,
and then i/o between the sockets can proceed. The ServerSocket class can do this.
ServerSocket example
In the following example, one machine (client) can take keyboard input and send it over a TCP
connection to another (server).
The server first creates a ServerSocket and waits for a connection from a client:

ServerSocket serverSocket = null;
try { // make a ServerSocket on port 50000
serverSocket = new ServerSocket(50000);
} catch (IOException e) {
System.out.println(e);
System.exit(1);
}
Socket clientSocket = null;
try { // wait for a connection
clientSocket = serverSocket.accept();
} catch (IOException e) {
System.out.println(e);
System.exit(2);
}
It then repeatedly reads input from it and displays it. If the input is 'bye' the connection is closed:
try {
BufferedReader in =
new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
String inputLine;
while ((inputLine = in.readLine()) != null) {
System.out.println(inputLine);
if (inputLine.equals("bye")) {
break;
}
}
serverSocket.close();
clientSocket.close();
} catch (IOException ioe) {
System.out.println(ioe);
}
The client firstly needs to create a TCP connection with the server machine (name "WALTER-HP") on
the same port, and get an output stream to it:
Java
Page 257 - Copyright 2012 Walter Milner - all rights reserved
Socket socket = null;
PrintWriter out=null;
try {
socket = new Socket("WALTER-HP", 50000);
out = new PrintWriter(socket.getOutputStream(), true);
} catch (UnknownHostException e) {
System.err.println(e); // can't find computer
System.exit(1);
} catch (IOException e) {
System.err.println(e); // can't connect
System.exit(2);
}
It then gets an input stream from the keyboad, and in a loop reads from it and sends to teh output
stream, until 'bye' is entered:
BufferedReader stdIn = new BufferedReader( new InputStreamReader(System.in));
String userInput;
try {
while ((userInput = stdIn.readLine()) != null) {
out.println(userInput);
if (userInput.equals("bye")) break;
}
out.close();
stdIn.close();
socket.close();
} catch (IOException ioe) {
System.out.println(ioe);
}
This only handles one client, but several can be dealt with at the same time by repeatedly waiting for
an accept and starting a new thread to communicate with the client.
This code requires the client to know the machine name of the server. This can be fixed by having
the server do a UDP multicast, so the client can first discover any available server on the network,
then proceed to connect and communicate.
Java
Page 258 - Copyright 2012 Walter Milner - all rights reserved
Networking - URLs
Here is an idea. A client could run a program (call it a 'user agent', UA) which can display a file. The
UA can establish a TCP connection with a server, and request a file held on the server. The server can
find the file, saved locally, and send it back, and the UA can display it. The file could contain special
'tags' indicating links to other files, possibly on other servers. When the user clicks on the link, a new
file is fetched and displayed.
That idea is the hyper-text transfer protocol http, and most UAs are called browsers. That could all
be programmed with TCP sockets. But because it is so common, Java offers a higher-level class called
URL which already implements the lower level communication for you.
Reading a webpage
The URL class makes it extremely easy to read a web page:
try{
URL url = new URL("http://www.google.com/");
BufferedReader in = new BufferedReader( new InputStreamReader(url.openStream()));
String inputLine;
while ((inputLine = in.readLine()) != null)
System.out.println(inputLine);
in.close();
}
catch (Exception e)
{
System.out.println(e);
}
CGI and URLs
The HTTP protocol is very simple. A 'command' is sent to the server. The most common command is
GET - in other words, get me a web page. Several of the others are usually disabled for obvious
security reasons - PUT to upload and web page, and DELETE.
Sometimes we need to supply data to the server, and expect a response, normally in the form of an
html document. This happens when we fill in a form on a web page. Data in the form is sent to the
server, a server-side script collects the data and processes it, and outputs a web page containing the
response.
The 'Common Gateway Interface' CGI provides two ways of uploading data - GET and POST. Here we
use GET.
This method puts the data in a query string which is appended to the URL, in the form of name value
pairs. For example, in
waltermilner.com/add.php?x=2&y=4
the start of the query string is marked by the ? and uploads a name x with a value 2, and a name y
with a value 4.
This is being sent to the script add.php in the domain waltermilner.com. This is a very simple
technique - but the fact that the data is visible in the URL means it cannot be used where there are
security concerns.
Java
Page 259 - Copyright 2012 Walter Milner - all rights reserved
Usually CGI access comes from a web page in a browser. Can we do it from a Java program? Simple:
try {
URL url = new URL("http://www.waltermilner.com/add.php?x=2&y=4");
BufferedReader in = new BufferedReader(
new InputStreamReader(url.openStream()));
String result = "";
String inputLine;
while ((inputLine = in.readLine()) != null) {
result += inputLine;
}
in.close();
System.out.println(result);
} catch (Exception e) {
System.out.println(e);
}
which outputs 6.
The server-side script for this is in PHP:
<?php
$x=$_GET['x'];
$y=$_GET['y'];
$z=$x+$y;
echo $z;
?>
$_GET lets us get the values of variables supplied in the query string, and echo outputs something -
which the web server sends back to us. Variables in PHP are preceded by a $.
HttpURLConnection and POST
In the POST method, names and values are sent in a data block which appears at the server as
'environment variables'. To do this from Java we can use the HttpURLConnection class. This is a
concrete subclass of the abstract URLConnection, with appropriate features for http transfers. First
create the connection and do the request:
URL url;
String params="x=2&y=4";
HttpURLConnection connection = null;
try {
//Create connection
url = new URL("http://waltermilner.com/add.php");
connection = (HttpURLConnection)url.openConnection();
connection.setRequestMethod("POST");
connection.setDoOutput(true); // want to output to connection.
// input is true by default

// Send request
DataOutputStream wr = new DataOutputStream (
connection.getOutputStream ());
wr.writeBytes (params);
wr.close ();
}
catch (Exception ex)
{
System.out.println(ex);
System.exit(0);
}
then get the response:
Java
Page 260 - Copyright 2012 Walter Milner - all rights reserved
try{
//Get Response
InputStream is = connection.getInputStream();
BufferedReader rd = new BufferedReader(new InputStreamReader(is));
String line;
String result="";
while((line = rd.readLine()) != null) {
result+=line;
}
rd.close();
connection.disconnect();
System.out.println(result);
} catch (Exception e) {
System.out.println(e);
}
The corresponding script is changed to expect the data in POST:
<?php
$x=$_POST['x'];
$y=$_POST['y'];
$z=$x+$y;
echo $z;
?>

Das könnte Ihnen auch gefallen