Java Concepts
Java Concepts
Contents
1
Computer basics
1.1
Computer basics:
1.2
Computer basics:
1.3
Computer basics:
1.4
Computer basics:
1.5
Computer basics:
1.6
Computer basics:
1.7
Computer basics:
1.8
Computer basics:
1.9
Computer basics:
1.10
Computer basics:
1.11
Computer basics:
1.12
Computer basics:
1.13
Computer basics:
Java tools
2.1
2.2
2.3
2.4
2.5
Java tools:
Java tools:
Java tools:
Java tools:
Java tools:
hardware (page 3) . . . . . . . . . . . . .
hardware: processor (page 3) . . . . . . . .
hardware: memory (page 3) . . . . . . . .
hardware: persistent storage (page 3) . . .
hardware: input and output devices (page 3)
software (page 3) . . . . . . . . . . . . . .
software: machine code (page 3) . . . . . .
software: operating system (page 4) . . . .
software: application program (page 4) . .
data (page 3) . . . . . . . . . . . . . . . .
data: files (page 5) . . . . . . . . . . . . .
data: files: text files (page 5) . . . . . . . .
data: files: binary files (page 5) . . . . . .
Operating environment
3.1
Operating environment:
3.2
Operating environment:
3.3
Operating environment:
3.4
Operating environment:
3.5
Operating environment:
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
Class
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
15000
15000
15000
15000
15001
15001
15001
15001
15001
15002
15002
15002
15002
15003
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
15003
15003
15003
15004
15004
15005
.
.
.
.
.
15006
15006
15006
15006
15006
15006
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
15007
15000
CONTENTS
4.1
4.2
4.3
4.4
4.5
4.6
4.7
4.8
4.9
4.10
4.11
4.12
4.13
4.14
Class:
Class:
Class:
Class:
Class:
Class:
Class:
Class:
Class:
Class:
Class:
Class:
Class:
Class:
Method
5.1
5.2
5.3
5.4
5.5
5.6
5.7
5.8
5.9
5.10
5.11
5.12
5.13
5.14
5.15
5.16
5.17
5.18
5.19
5.20
5.21
5.22
5.23
5.24
5.25
5.26
5.27
5.28
5.29
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
15007
15007
15007
15007
15008
15008
15009
15009
15009
15010
15010
15011
15011
15012
15012
Method (page 118) . . . . . . . . . . . . . . . . . . . . . . . . . . . 15012
Method: main method: programs contain a main method (page 17) . 15012
Method: main method: is public (page 17) . . . . . . . . . . . . . . 15012
Method: main method: is static (page 17) . . . . . . . . . . . . . . . 15013
Method: main method: is void (page 17) . . . . . . . . . . . . . . . 15013
Method: main method: is the program starting point (page 17) . . . . 15013
Method: main method: always has the same heading (page 18) . . . 15013
Method: private (page 118) . . . . . . . . . . . . . . . . . . . . . . 15014
Method: accepting parameters (page 118) . . . . . . . . . . . . . . . 15014
Method: accepting parameters: of a class type (page 164) . . . . . . 15015
Method: accepting parameters: of an array type (page 297) . . . . . 15015
Method: calling a method (page 119) . . . . . . . . . . . . . . . . . 15016
Method: void methods (page 120) . . . . . . . . . . . . . . . . . . . 15016
Method: returning a value (page 122) . . . . . . . . . . . . . . . . . 15017
Method: returning a value: of a class type (page 176) . . . . . . . . 15017
Method: returning a value: multiple returns (page 196) . . . . . . . . 15018
Method: returning a value: of an array type (page 312) . . . . . . . . 15019
Method: changing parameters does not affect arguments (page 124) . 15019
Method: changing parameters does not affect arguments: but referenced objects can be ch
Method: constructor methods (page 159) . . . . . . . . . . . . . . . 15020
Method: constructor methods: more than one (page 203) . . . . . . . 15021
Method: class versus instance methods (page 166) . . . . . . . . . . 15021
Method: a method may have no parameters (page 173) . . . . . . . . 15023
Method: return with no value (page 206) . . . . . . . . . . . . . . . 15023
Method: accessor methods (page 207) . . . . . . . . . . . . . . . . 15023
Method: mutator methods (page 207) . . . . . . . . . . . . . . . . . 15024
Method: overloaded methods (page 237) . . . . . . . . . . . . . . . 15024
Method: that throws an exception (page 354) . . . . . . . . . . . . . 15024
Method: that throws an exception: RuntimeException (page 358) . . 15025
15026
15001
CONTENTS
6.1
6.2
6.3
6.4
7
Type
7.1
7.2
7.3
7.4
7.5
7.6
7.7
7.8
7.9
7.10
7.11
7.12
7.13
7.14
7.15
7.16
7.17
7.18
7.19
7.20
7.21
7.22
7.23
7.24
7.25
7.26
7.27
Standard API
8.1
Standard API: System:
8.2
Standard API: System:
8.3
Standard API: System:
8.4
Standard API: System:
8.5
Standard API: System:
8.6
Standard API: System:
8.7
Standard API: System:
8.8
Standard API: System:
8.9
Standard API: System:
8.10
Standard API: System:
8.11
Standard API: System:
8.12
Standard API: System:
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
15027
15027
15028
15028
15028
15028
15029
15029
15030
15030
15031
15032
15032
15032
15032
15033
15033
15033
15033
15034
15034
15034
15035
15035
15036
15036
15036
15037
15037
out.println() (page 18) . . . . . . . . . . . . 15037
out.println(): with no argument (page 98) . . 15037
out.print() (page 98) . . . . . . . . . . . . . 15038
out.printf() (page 126) . . . . . . . . . . . . 15039
out.printf(): zero padding (page 140) . . . . . 15040
out.printf(): string item (page 289) . . . . . . 15040
out.printf(): fixed text and many items (page 289)15041
out.printf(): left justification (page 300) . . . 15042
in (page 187) . . . . . . . . . . . . . . . . . 15042
getProperty() (page 195) . . . . . . . . . . . 15042
getProperty(): line.separator (page 195) . . . 15042
currentTimeMillis() (page 262) . . . . . . . . 15043
15002
CONTENTS
8.13
8.14
8.15
8.16
8.17
8.18
8.19
8.20
8.21
8.22
8.23
8.24
8.25
8.26
8.27
9
Statement
9.1
9.2
9.3
9.4
9.5
9.6
9.7
9.8
9.9
9.10
9.11
9.12
9.13
9.14
9.15
9.16
9.17
9.18
9.19
9.20
9.21
9.22
10
Error
10.1
10.2
10.3
10.4
10.5
10.6
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
15043
15043
15043
15044
15044
15044
15045
15045
15045
15046
15047
15048
15049
15050
15050
15051
Statement (page 18) . . . . . . . . . . . . . . . . . . . . . . . . . . 15051
Statement: simple statements are ended with a semi-colon (page 18) 15051
Statement: assignment statement (page 37) . . . . . . . . . . . . . . 15052
Statement: assignment statement: assigning a literal value (page 37) 15052
Statement: assignment statement: assigning an expression value (page 38)15052
Statement: assignment statement: updating a variable (page 70) . . . 15052
Statement: assignment statement: updating a variable: shorthand operators (page 87)1505
Statement: if else statement (page 60) . . . . . . . . . . . . . . . . . 15054
Statement: if else statement: nested (page 62) . . . . . . . . . . . . 15054
Statement: if statement (page 64) . . . . . . . . . . . . . . . . . . . 15055
Statement: compound statement (page 66) . . . . . . . . . . . . . . 15056
Statement: while loop (page 71) . . . . . . . . . . . . . . . . . . . . 15057
Statement: for loop (page 77) . . . . . . . . . . . . . . . . . . . . . 15057
Statement: for loop: multiple statements in for update (page 136) . . 15058
Statement: statements can be nested within each other (page 92) . . . 15059
Statement: switch statement with breaks (page 107) . . . . . . . . . 15059
Statement: switch statement without breaks (page 110) . . . . . . . 15060
Statement: do while loop (page 112) . . . . . . . . . . . . . . . . . 15061
Statement: for-each loop: on arrays (page 293) . . . . . . . . . . . . 15062
Statement: try statement (page 344) . . . . . . . . . . . . . . . . . . 15064
Statement: try statement: with multiple catch clauses (page 347) . . 15065
Statement: throw statement (page 350) . . . . . . . . . . . . . . . . 15067
15003
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
15067
15067
15068
15068
15068
15068
15069
CONTENTS
11
Execution
11.1
11.2
11.3
11.4
11.5
11.6
12
Code clarity
12.1
Code clarity:
12.2
Code clarity:
12.3
Code clarity:
12.4
Code clarity:
12.5
Code clarity:
12.6
Code clarity:
13
14
15069
Execution: sequential execution (page 23) . . . . . . . . . . . . . . 15069
Execution: conditional execution (page 60) . . . . . . . . . . . . . . 15069
Execution: repeated execution (page 70) . . . . . . . . . . . . . . . 15070
Execution: parallel execution threads (page 253) . . . . . . . . . . 15070
Execution: parallel execution threads: the GUI event thread (page 254)15070
Execution: event driven programming (page 254) . . . . . . . . . . 15071
15071
15071
15072
15072
15073
15073
15074
Design
13.1
13.2
13.3
13.4
13.5
13.6
13.7
13.8
Design:
Design:
Design:
Design:
Design:
Design:
Design:
Design:
Variable
14.1
14.2
14.3
14.4
14.5
14.6
14.7
14.8
14.9
14.10
14.11
14.12
14.13
14.14
14.15
14.16
14.17
14.18
14.19
14.20
15079
Variable (page 36) . . . . . . . . . . . . . . . . . . . . . . . . . . . 15079
Variable: int variable (page 37) . . . . . . . . . . . . . . . . . . . . 15079
Variable: a value can be assigned when a variable is declared (page 42)15080
Variable: double variable (page 54) . . . . . . . . . . . . . . . . . . 15080
Variable: can be defined within a compound statement (page 92) . . 15080
Variable: local variables (page 124) . . . . . . . . . . . . . . . . . . 15081
Variable: class variables (page 124) . . . . . . . . . . . . . . . . . . 15081
Variable: a group of variables can be declared together (page 129) . . 15082
Variable: boolean variable (page 133) . . . . . . . . . . . . . . . . . 15082
Variable: char variable (page 145) . . . . . . . . . . . . . . . . . . . 15083
Variable: instance variables (page 159) . . . . . . . . . . . . . . . . 15084
Variable: instance variables: should be private by default (page 175) 15084
Variable: of a class type (page 161) . . . . . . . . . . . . . . . . . . 15085
Variable: of a class type: stores a reference to an object (page 162) . 15085
Variable: of a class type: stores a reference to an object: avoid misunderstanding (page 17
Variable: of a class type: null reference (page 192) . . . . . . . . . . 15087
Variable: of a class type: holding the same reference as some other variable (page 216)15
Variable: final variables (page 194) . . . . . . . . . . . . . . . . . . 15091
Variable: final variables: class constant (page 205) . . . . . . . . . . 15091
Variable: final variables: class constant: a set of choices (page 308) . 15091
15004
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
15074
15074
15074
15075
15075
15076
15076
15076
15078
CONTENTS
14.21
14.22
15
Variable: final variables: class constant: a set of choices: dangerous (page 308)15092
Variable: of an array type (page 287) . . . . . . . . . . . . . . . . . 15092
Expression
15.1
15.2
15.3
15.4
15.5
15.6
15.7
15.8
15.9
15.10
15.11
15.12
15.13
16
Package
16.1
16.2
16.3
15100
Package (page 187) . . . . . . . . . . . . . . . . . . . . . . . . . . 15100
Package: java.util (page 188) . . . . . . . . . . . . . . . . . . . . . 15100
Package: java.awt and javax.swing (page 245) . . . . . . . . . . . . 15101
17
GUI API
17.1
17.2
17.3
17.4
17.5
17.6
17.7
17.8
17.9
17.10
17.11
17.12
17.13
17.14
17.15
17.16
17.17
17.18
17.19
17.20
17.21
17.22
17.23
15101
GUI API: JFrame (page 245) . . . . . . . . . . . . . . . . . . . . . 15101
GUI API: JFrame: setTitle() (page 246) . . . . . . . . . . . . . . . . 15101
GUI API: JFrame: getContentPane() (page 246) . . . . . . . . . . . 15102
GUI API: JFrame: setDefaultCloseOperation() (page 247) . . . . . . 15102
GUI API: JFrame: pack() (page 247) . . . . . . . . . . . . . . . . . 15102
GUI API: JFrame: setVisible() (page 248) . . . . . . . . . . . . . . 15103
GUI API: Container (page 246) . . . . . . . . . . . . . . . . . . . . 15103
GUI API: Container: add() (page 246) . . . . . . . . . . . . . . . . 15103
GUI API: Container: add(): adding with a position constraint (page 268)15103
GUI API: Container: setLayout() (page 250) . . . . . . . . . . . . . 15103
GUI API: JLabel (page 246) . . . . . . . . . . . . . . . . . . . . . . 15104
GUI API: JLabel: setText() (page 258) . . . . . . . . . . . . . . . . 15104
GUI API: LayoutManager (page 249) . . . . . . . . . . . . . . . . . 15104
GUI API: LayoutManager: FlowLayout (page 249) . . . . . . . . . 15104
GUI API: LayoutManager: FlowLayout: alignment (page 278) . . . 15104
GUI API: LayoutManager: GridLayout (page 251) . . . . . . . . . . 15105
GUI API: LayoutManager: BorderLayout (page 267) . . . . . . . . 15106
GUI API: Listeners (page 254) . . . . . . . . . . . . . . . . . . . . 15107
GUI API: Listeners: ActionListener interface (page 257) . . . . . . . 15108
GUI API: Listeners: ActionListener interface: actionPerformed() (page 258)15109
GUI API: JButton (page 256) . . . . . . . . . . . . . . . . . . . . . 15109
GUI API: JButton: addActionListener() (page 256) . . . . . . . . . 15109
GUI API: JButton: setEnabled() (page 266) . . . . . . . . . . . . . . 15109
15005
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
15093
15093
15093
15093
15094
15094
15094
15095
15095
15097
15097
15097
15099
15099
CONTENTS
17.24
17.25
17.26
17.27
17.28
17.29
17.30
17.31
17.32
17.33
17.34
17.35
17.36
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
15110
15110
15110
15110
15110
15110
15111
15111
15111
15111
15111
15112
15112
18
Interface
18.1
15112
Interface (page 257) . . . . . . . . . . . . . . . . . . . . . . . . . . 15112
19
Array
19.1
19.2
19.3
19.4
19.5
19.6
19.7
19.8
19.9
19.10
19.11
19.12
19.13
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
15113
15113
15113
15114
15114
15115
15115
15116
15116
15117
15118
15118
15118
15119
Exception
20.1
20.2
20.3
20.4
20.5
20.6
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
15121
15121
15121
15121
15122
15122
15123
20
15006
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
1 Computer basics
1.1 Computer basics: hardware (page 3)
The physical parts of a computer are known as hardware. You can see them, and touch them.
15008
some image displaying or editing software, but even this isnt showing you the actual data that
makes up the picture. The names and addresses of your friends is another example of data.
2 Java tools
2.1 Java tools: text editor (page 5)
A text editor is a program that allows the user to type and edit text files. You may well
have used notepad under Microsoft Windows; that is a text editor. More likely you have
used Microsoft Word. If you have, you should note that it is not a text editor, it is a word
processor. Although you can save your documents as text files, it is more common to save
15009
them as .doc files, which is actually a binary file format. Microsoft Word is not a good tool
to use for creating program source code files.
If you are using an integrated development environment to support your programming, then
the text editor will be built in to it. If not, there are a plethora of text editors available which
are suited to Java programming.
will produce the byte code version of it in the file HelloWorld.class. Like machine code
files, byte code is stored in binary files as numbers, and so is not human readable.
This makes the central processing unit run the interpreter or virtual machine java, which
itself then executes the program named as its first argument. Notice that the suffix .java is
needed when compiling the program, but no suffix is used when running it. In our example
here, the virtual machine finds the byte code for the program in the file HelloWorld.class
which must have been previously produced by the compiler.
this is achieved by the implementer of the class writing doc comments in the code, and then
processing them with the javadoc program. This tool produces a web page which describes
the class from the information in the doc comments and from the structure of the class itself,
and this page is linked to the pages for other classes as appropriate. For example, the heading of
each public method is documented on the web page, with the description of the method being
taken by javadoc from the doc comment which the implementer supplied for the method.
The resulting user documentation produced by javadoc can be placed anywhere we wish on
a web server for example. Meanwhile the source of that documentation is kept with the source
code for the class, indeed it is inside the same file. This excellent idea makes it easy for the
programmer to maintain information on how to use the class as he or she alters the code, but
without restricting where the final documentation can be put.
A doc comment starts with the symbol /** and ends with */. These are written in certain
places as follows.
A comment before the start of the class (after any import statements) describing its
purpose.
A comment before each public variable describing the meaning of that variable.
A comment before each public method describing what it does, its method parameters
and return value.
Optionally, a comment before each private variable and method. This is less useful than
documentation for public items as normal users of the class do not have access to the
private ones. So, many programmers do not write doc comments for these (although
of course they do write ordinary comments!). On the other hand, some take the view
that anybody who needs to maintain the class is, in effect, a user of both the public and
private parts, and so user documentation of the whole class is of benefit.
The implementer writes user documentation text as appropriate inside the doc comments. The
emphasis is on how to use the features, not on how they are implemented. He or she also
includes various doc comment tags to help the javadoc program process the text properly.
Here are some of the most commonly used tags.
Tag
@author author name(s)
@param parameter description
@return description
Meaning
State the author of the code.
Describe a method parameter.
Describe a method result.
Where used
Before the class starts.
Before a method.
Before a method.
Most doc comments use more than one line, and it is conventional (but not essential) to start
continuation lines with an asterisk (*) neatly lined up with the first asterisk in the opening
comment symbol. The first sentence should be a summary of the whole thing being documented
these are copied to a summary area of the final documentation.
15011
For a doc comment tag to be recognized by javadoc, it must be the first word on a line of the
comment, preceded only by white space, or an asterisk.
Doc comments are sometimes (but wrongly) called javadoc comments.
3 Operating environment
3.1 Operating environment: programs are commands (page 7)
When a program is executed, the name of it is passed to the operating system which finds and
loads the file of that name, and then starts the program. This might be hidden from you if you
are used to starting programs from a menu or browser interface, but it happens nevertheless.
15012
4 Class
4.1 Class: programs are divided into classes (page 16)
In Java, the source text for a program is separated into pieces called classes. The source
text for each class is (usually) stored in a separate file. Classes have a name, and if the
name is HelloWorld then the text for the class is saved by the programmer in the text file
HelloWorld.java.
One reason for dividing programs into pieces is to make them easier to manage programs to
perform complex tasks typically contain thousands of lines of text. Another reason is to make
it easier to share the pieces between more than one program such software reuse is beneficial
to programmer productivity.
Every program has at least one class. The name of this class shall reflect the intention of the
program. By convention, class names start with an upper case letter.
text for a public class definition starts with the reserved word public. A reserved word is one
which is part of the Java language, rather than a word chosen by the programmer for use as,
say, the name of a program.
15014
{
return halfWayPoint(new Point(0, 0));
} // halfThisPoint
{
return new Point(0, 0).halfWayPoint(this);
} // halfThisPoint
to) another object as its method parameter, and returns an int. A result of 0 indicates the
two objects are equivalent, a negative value indicates this object is less than the other, and a
positive value indicates this object is greater than the other.
Point
Point
Point
Point
topLeft
bottomLeft
topRight
bottomRight
=
=
=
=
new
new
new
new
Point(-20, 40);
Point(-20, -40);
Point(20, 40);
Point(20, -40);
This declares four variables, of type Point and creates four instances of the class Point representing the four corners of a rectangle. The four variables each contain a reference to one of
the points. This is illustrated in the following diagram.
15016
A Point object
Point topLeft
A Point object
private double x
20
private double y
40
Point topRight
private double x
20
private double y
40
A Point object
Point bottomLeft
private double x
20
private double y
40
A Point object
Point bottomRight
private double x
20
private double y
40
All four Point objects each have two instance variables, called x and y.
import java.util.Scanner;
...
Scanner inputScanner = new Scanner(System.in);
If we wish, we can import all the classes in a package using a * instead of a class name.
import java.util.*;
15017
Many programmers consider this to be lazy, and it is better to import exactly what is needed, if
only to help show precisely what is used by the class. There is also the issue of ambiguity: if
two different packages have classes with the same name, but this class only needs one of them,
then the lazy approach would cause an unnecessary problem.
However, every Java program has an automatic import for every class in the standard package java.lang, because these classes are used so regularly. That is why we can refer to
java.lang.System and java.lang.Integer, etc. as just System and Integer, etc.. In other
words, every class always implicitly includes the following import statement for convenience.
import java.lang.*;
This means that all instances of HelloWorld have the properties that any instance of JFrame
would have, but also have all the properties that we additionally define in the HelloWorld
class. It is a way of adding properties to a class without actually changing the class the new
class is an extension of the other one.
15018
5 Method
5.1 Method (page 118)
A method in Java is a section of code, dedicated to performing a particular task. All programs
have a main method which is the starting point of the program. We can have other methods
too, and we can give them any name we like although we should always choose a name which
suits the purpose. By convention, method names start with a lower case letter. For example,
System.out.println() is a method which prints a line of text. Apart from its slightly strange
spelling, the name println does reflect the meaning of the method.
5.2 Method: main method: programs contain a main method (page 17)
All Java programs contain a section of code called main, and this is where the computer will
start to execute the program. Such sections of code are called methods because they contain
instructions on how to do something. The main method always starts with the following
heading.
public static void main(String[] args)
15019
5.6 Method: main method: is the program starting point (page 17)
The starting part, or main method, of the program is always called main, because it is the main
part of the program.
public static void main
5.7 Method: main method: always has the same heading (page 18)
The main method of a Java program must always have a heading like this.
public static void main(String[] args)
This is true even if we do not intend to use any command line arguments. So a typical single
class program might look like the following.
public class MyFabulousProgram
{
public static void main(String[] args)
The text inside the brackets is the declaration of the parameters. A method can have any
number of parameters, including zero. If there is more than one, they are separated by commas
(,). Each parameter consists of a type and a name. For example, the following method is given
two parameters, a double and an int.
System.out.println("At age " + age + ", height per year ratio is "
+ height / age);
} // printHeightPerYear
You should think of parameters as being like variables defined inside the method, except that
they are given initial values before the method body is executed. For example, the single
parameter to the main method is a variable which is given a list of strings before the method
begins execution, these strings being the command line arguments supplied to the program.
The names of the parameters are not important to Java as long as they all have different
names! The names only mean something to the human reader, which is of course important.
The above method could easily have been written as follows.
System.out.println("At age " + howOld + ", height per year ratio is "
+ howTall / howOld);
} // printHeightPerYear
You might think the first version is subjectively nicer than the second, but clearly both are better
than this next one!
15021
And that is only marginally better than calling the parameters, say x and y. However, Java does
not care it is not clever enough to be able to, as it can have no understanding of the problem
being solved by the code.
printHeightPerYear(1.6, 14);
When we call a method we supply a method argument for each method parameter, separating them by commas (,). These argument values are copied into the corresponding parameters
15022
of the method the first argument goes into the first parameter, the second into the second, and
so on.
The arguments passed to a method may be the current values of variables. For example, the
above code could have been written as follows.
printHeightPerYear(personHeight, personAge);
As you may expect, the arguments to a method are actually expressions rather than just literal
values or variables. These expressions are evaluated at the time the method is called. So we
might have the following.
{
double fahrenheitValue = celsiusValue * 9 / 5 + 32;
15023
return fahrenheitValue;
} // celsiusToFahrenheit
The method is declared with a return type of double, by writing that type name before the
method name.
The return statement is how we specify what value is to be returned as the result of the
method. The statement causes the execution of the method to end, and control to transfer back
to the code that called the method.
The result of a non-void method can be used in an expression. For example, the method above
might be used as follows.
The return statement takes any expression after the reserved word return. So our method
above could be implemented using just one statement.
{
return celsiusValue * 9 / 5 + 32;
} // celsiusToFahrenheit
{
double newX = (x + other.x) / 2;
double newY = (y + other.y) / 2;
return new Point(newX, newY);
} // halfWayPoint
15024
The method creates a new object and then returns a reference to it. This might be used as
follows.
Point p1 = new Point(3, 4);
Point p2 = new Point(45, 60);
Point halfWayBetweenP1AndP2 = p1.halfWayPoint(p2);
The reference to the new Point returned by the instance method, is stored in the variable
halfWayBetweenP1AndP2. It would, of course, be the point (24, 32). This is illustrated in the
following diagram.
A Point object
A Point object
private double x
private double y
private double x
45
private double y
60
A Point object
private double x
24
private double y
32
There is no path through the method that does not end with a return statement.
There is no code in the method that can never be reached due to an earlier occurring
return statement.
15025
5.18 Method: changing parameters does not affect arguments (page 124)
We can think of method parameters as being like variables defined inside the method, but
which are given their initial value by the code that calls the method. This means the method
can change the values of the parameters, like it can for any other variable defined in it. Such
changes have no effect on the environment of the code that called the method, regardless of
where the method argument values came from. An argument value, be it a literal constant,
taken straight from a variable, or the result of some more complex expression, is simply copied
into the corresponding parameter at the time the method is called. This is known as call by
value.
5.19 Method: changing parameters does not affect arguments: but referenced objects can be changed (page 208)
All method parameters obtain their values from the corresponding method argument using the call by value principle. This means a method cannot have any effect on the calling
environment via its method parameters if they are of a primitive type.
However, if a method parameter is of a reference type then there is nothing to stop the code
in the method following the reference supplied as the argument, and altering the state of the
object it refers to (if it is a mutable object). Indeed, such behaviour is often exactly what we
want.
In the abstract example below, assume that changeState() is an instance method in the class
SomeClass which alters the values of some of the instance variables.
15026
At the end of the above code, the change caused by the first line of the method has had an
impact outside of the method, whereas the second line has had no such effect.
x = requiredX;
y = requiredY;
} // Point
This says that in order to construct an object which is an instance of the class Point, we
need to supply two double values, the first will be placed in the x instance variable, and the
second in the y instance variable. Constructor methods are called in a similar way to any other
method, except that we precede the method call with the reserved word new. For example,
the following code would create a new object, which is an instance of the class Point, and in
which the instance variables x and y have the values 7.4 and -19.9 respectively.
new Point(7.4, -19.9);
We can create as many Point objects as we wish, each of them having their own pair of instance
variables, and so having possibly different values for x and y. These next four Point objects
are the coordinates of a rectangle which is centred around the origin of a graph, point (0, 0).
new
new
new
new
Point(-20, 40);
Point(-20, -40);
Point(20, 40);
Point(20, -40);
15027
A Point object
A Point object
private double x
20
private double x
20
private double y
40
private double y
40
A Point object
A Point object
private double x
20
private double x
20
private double y
40
private double y
40
All four Point objects each have two instance variables, called x and y.
Of course, the virtual machine does not really make copies of the code of instance methods,
but it behaves as though it does, in the sense that when an instance method is executed, it runs
in the context of the instance that it belongs to.
For example, suppose we have a Point class with instance variables x and y. We might wish
to have an instance method which takes no method parameters,
but returns the distance of a
p
2
point from the origin. Pythagoras[18] tells us that this is x + y2 . (We can use the sqrt()
method from the Math class.)
{
return Math.sqrt(x * x + y * y);
} // distanceFromOrigin
A class method can be accessed by taking the name of the class, and appending a dot (.) and
then the name of the method. Math.sqrt is a handy example right now.
An instance method belonging to an object can be accessed by taking a reference to the object
and appending a dot (.) and then the name of the method. For example, if the variable p1
contains a reference to a Point object, then the code p1.distanceFromOrigin() invokes the
instance method distanceFromOrigin(), belonging to the Point referred to by p1.
The following code would print the numbers 5 and 75.
Point p1 = new Point(3, 4);
Point p2 = new Point(45, 60);
System.out.println(p1.distanceFromOrigin());
System.out.println(p2.distanceFromOrigin());
When the method is called via p1 it uses the instance variables of the object referred to by p1,
that is the values 3 and 4 respectively. When the method is called via p2 it uses the values 45
and 60 instead.
For another example, we may wish to have a method which determines the distance between a
point and a given other point.
{
double xDistance = x - other.x;
double yDistance = y - other.y;
return Math.sqrt(xDistance * xDistance + yDistance * yDistance);
} // distanceFromPoint
15029
...
} // charAt
As another example, suppose in some program we have a class which provides mutable objects representing customer details. An instance of the class is allowed to have the customer
name changed, but the new name is not allowed to be empty.
{
private String familyName, firstNames;
...
public void setName(String requiredFamilyName, String requiredFirstNames)
throws IllegalArgumentException
{
if (requiredFamilyName == null || requiredFirstNames == null
15031
|| requiredFamilyName.equals("") || requiredFirstNames.equals(""))
throw new IllegalArgumentException("Name cannot be null or empty");
familyName = requiredFamilyName;
firstNames = requiredFirstNames;
} // setName
...
} // class Customer
Generally, every exception that possibly can be thrown by a method, either directly by a throw
statement or indirectly via another method, etc., must either be caught by the method, or it must
say in its throws clause that it throws the exception. However, Java relaxes this rule for certain
kinds of exception known as RuntimeException. These represent common erroneous situations which are usually avoidable and for which we typically write code to ensure they do not
happen. The java.lang.RuntimeException class is a kind of Exception, and examples of
more specific classes which are kinds of RuntimeException include ArrayIndexOutOfBoundsException,
IllegalArgumentException, NumberFormatException, ArithmeticException and NullPointerExcept
(all from the java.lang package).
It would be a major inconvenience to have to always declare that these common cases might
happen, or to explicitly catch them, in situations where we know they will not be thrown due
to the way we have written the code. So, for these kinds of exception, Java leaves it as an option
for us to declare whether they might be thrown by a method. For example, in the following
method there is an array reference, and also an (implicit) array element access. These could
in principle result in a NullPointerException and an ArrayIndexOutOfBoundsException
respectively. The Java compiler is not clever enough to be able to reason whether such an
exception can actually occur, whereas we know they cannot because of the way our code works.
{
if (array == null)
return 0;
int sum = 0;
for (int element : array)
sum += element;
return sum;
} // sum
On the other hand, the following method can cause some kinds of RuntimeException if
given a null reference or an empty array. Java still cannot know this without us declaring it
in the heading.
15032
{
int sum = array[0];
for (int index = 1; index <= array.length; index++)
sum += array[index];
return sum / array.length;
} // sum
For code which is intended for software reuse, it is a good idea for us to be disciplined about
this relaxation of the normal rule. If we write a method that can throw some exception which
is a RuntimeException, because we have not written the code in a way which always avoids
the possibility, or indeed we explicitly throw such an exception, then we should still declare it
in the method heading, even though we are not forced to.
Exceptions for which we must either have a catch clause or list in a throws clause are known
as checked exceptions, and those for which the rule is relaxed, that is RuntimeException and
its specific kinds, are known as unchecked exceptions.
6.2 Command line arguments: program arguments are accessed by index (page 26)
The command line arguments given to the main method are a list of strings. These are
the text data string arguments supplied on the command line. The strings are indexed by
integers (whole numbers) starting from zero. We can access the individual strings by placing
the index value in square brackets after the name of the list. So, assuming that we call the list
args, then args[0] is the first command line argument given to the program, if there is one.
15033
6.4 Command line arguments: list index can be a variable (page 79)
The index used to access the individual items from a list of strings does not have to be an
integer literal, but can be an int variable or indeed an arithmetic expression. For example,
the following code adds together a list of integers given as command line arguments.
int sumOfArgs = 0;
for (int argIndex = 0; argIndex < args.length; argIndex = argIndex + 1)
The benefit of being able to use a variable, rather than an integer literal is that the access can
be done in a loop which controls the value of the variable: thus the actual value used as the
index is not the same each time.
7 Type
7.1 Type (page 36)
Programs can process various different kinds of data, such as numbers, text data, images etc..
The kind of a data item is known as its type.
7.4 Type: String: literal: must be ended on the same line (page 21)
characters, exactly as listed. Such a piece of data might be used as a message to the user.
"This is a fixed piece of text data -- a string literal"
7.4 Type: String: literal: must be ended on the same line (page 21)
In Java, string literals must be ended on the same line they are started on.
Name
Backspace
\t
\n
\f
\r
\"
Double quote
Single quote
\\
Backslash
Effect
Moves the cursor back one place, so the next character will over-print the previous.
Moves the cursor to the next tab stop.
Moves the cursor to the next line.
Moves to a new page on many (text) printers.
Moves the cursor to the start of the current line, so
characters will over-print those already printed.
Without the backslash escape, this would mark the
end of the string literal.
This is just for consistency we dont need to escape a single quote in a string literal.
Well, sometimes you want the backslash character
itself.
Note: System.out.println() always ends the line with the platform dependent line separator, which on Linux is a new line character but on Microsoft Windows is a carriage return
15035
character followed by a new line character. In practice you may not notice the difference, but
the above code is not strictly the same as using three separate System.out.println() calls
and is not 100% portable.
15036
The number 51 would be converted to the string "51" and then concatenated to the string
"Please invite " before being processed by System.out.println().
Furthermore, for our convenience, there is a separate version of System.out.println() that
takes a single int rather than a string, and prints its decimal representation. Thus, the code
System.out.println(noOfPeopleToInviteToTheStreetParty);
{
return "(" + x + "," + y + ")";
} // toString
For convenience, whenever the Java compiler finds an object reference as an operand of the
concatenation operator it assumes that the objects toString() method is to be invoked to
produce the required String. For example, consider the following code.
Point p1 = new Point(10, 40);
System.out.println("The point is " + p1.toString());
Thanks to the compilers convenient implicit assumption about toString(), the above code
could, and probably would, have been written as follows.
15037
7.10 Type: String: conversion: from object: null reference (page 211)
For our further convenience, there is a separate version of System.out.println() that takes
any single object rather than a string, and prints its toString(). Thus, the code
System.out.println(p1);
7.10 Type: String: conversion: from object: null reference (page 211)
For convenience, whenever the Java compiler finds an object reference as an operand of the
concatenation operator it assumes that the objects toString() instance method is to be
invoked to produce the required String. However, the reference might be the null reference
in which case there is no object on which to invoke toString(), so instead, the string "null"
is used.
In fact, assuming someString is some String and myVar is a variable of a reference type,
then the code:
someString + myVar
The same applies to the first operand of string concatenation if that is an object reference.
For this reason, most Java programmers prefer to use "" + myVar rather than myVar.toString()
when they wish to convert the object referenced by myVar to a string, because it avoids the possibility of an exception if myVar contains the null reference.
15039
backspace = \b;
newline = \n;
carriageReturn = \r;
singleQuote = \;
char
char
char
char
tab = \t;
formFeed = \f;
doubleQuote = \";
backslash = \\;
has a unique number and when two characters are compared, the result is formed from the
same comparison on the two numbers.
Generally speaking we do not need to know the actual numbers used for specific characters.
However, there are certain properties that are useful to know, such as that the number for A is
one less than that for B, which is one less than the number used for C, and so on. In other
words, the upper case alphabetic letters have contiguous character codes. The same is true of
the lower case alphabet, and also the digit characters 0 through to 9. The character codes
for the digits are all less than those for the upper case letters, which are all less than those for
the lower case letters.
For example, the following method checks whether a given character is a lower case alphabetic
character.
{
return aChar >= a && aChar <= z;
} // isLowerCase
A method similar to this is provided in the standard class java.lang.Character. That one
also works for locales (i.e. languages) other than English.
Another property worth remembering is that, for the English characters, the code for each upper
case letter is 32 less than the code for the corresponding lower case letter.
The following method returns the upper case equivalent of a given character, if it is a lower
case letter, or the original character if not. It assumes availability of the method isLowerCase().
1 Actually,
the cast in the first line from char to int would be implicit, but it is good style to write it anyway.
In the second line, the cast from int to char is required.
15041
{
if (isLowerCase(aChar))
return (char) ((int)aChar - (int)a + (int)A);
else
return aChar;
} // toUpperCase
A method similar to this is provided in the standard class java.lang.Character. That one
also works for locales (i.e. languages) other than English.
15042
This behaves rather like we have defined a class called Direction, and four variables, each
referring to a unique instance of Direction. So, for example, we can have the following.
If we wanted the type to be available in other classes, then we would declare it as public.
Enum types can also be used in switch statements.
switch (currentDirection)
{
case UP:
case DOWN:
case LEFT:
case RIGHT:
default:
...
...
...
...
...
} // switch
7.27 Type: enum type: access from another class (page 312)
If we declare a public enum type, then it can be used in other classes. We access it using dots
(.) rather like we do for other kinds of access from another class.
For example, if the enum type Direction is defined in the class Movement, then we could refer
to it, and one of its values as follows.
15043
8 Standard API
8.1 Standard API: System: out.println() (page 18)
The simplest way to print a message on standard output is to use:
System.out.println("This text will appear on standard output");
System is a class (that is, a piece of code) that comes with Java as part of its application
program interface (API) a large number of classes designed to support our Java programs.
Inside System there is a thing called out, and this has a method (section of code) called
println. So overall, this method is called System.out.println. The method takes a string
of text given to it in its brackets, and displays that text on the standard output of the program.
System.out.println() with no argument is most useful when we need to end a line which
has been generated a piece at a time, or when we want to have a blank line.
15044
System.out.print("Hello");
System.out.print(" ");
System.out.println("world!");
System.out.println("Hello world!");
System.out.print() is most useful when the output is being generated a piece at a time,
often within a loop.
1234567890
123
15045
The first % tells out.printf() that we wish it to format something, the 10 tells it the minimum
total width to produce, and the following letter says what kind of conversion to perform. A d
tells it to produce the representation of a decimal whole number, which is given after the format
specifier string, as the second method argument. The %n tells out.printf() to output the
platform dependent line separator.
The method can be asked to format a floating point value, such as a double. In such cases we
give the minimum total width, a dot (.), the number of decimal places, and an f conversion.
For example,
System.out.printf("%1.2f%n", 123.456);
needs more than the given minimum width of 1, and so produces the following.
123.46
Whereas, the format specifier in
System.out.println("1234567890");
System.out.printf("%10.2f%n", 123.456);
prints a total of ten characters for the number, two of which are decimal places.
1234567890
123.46
1234567890
0000000123
Similarly,
System.out.println("1234567890");
System.out.printf("%010.2f%n", 123.456);
8.7 Standard API: System: out.printf(): fixed text and many items (page 289)
8.7 Standard API: System: out.printf(): fixed text and many items (page
289)
We can give System.out.printf() a format string with more than one format specifier in
it, together with more than one value to be printed. What is more, any text in the format string
which is not part of a format specifier is simply printed as it appears. Also, if no width is given
for a format specifier then its natural width is used.
For example,
System.out.println("123456789012345X");
System.out.printf("%-15sX%n", "Hello World");
123456789012345X
Hello World
X
Perhaps surprisingly, unlike the standard output, the standard input in Java is not easy to use
as it is, and we typically access it via some other means, such as a Scanner.
15049
Integer is a class (that is, a piece of code) that comes with Java. Inside Integer there is a
method (section of code) called parseInt. This method takes a text data string given to it in
its brackets, converts it into an int and returns that number. A run time error will occur if
the given string does not represent an int value.
For example
int firstArgument;
firstArgument = Integer.parseInt(args[0]);
would take the first command line argument and, assuming it represents a number (i.e. it is a
string of digits with a possible sign in front), would turn it into the number it represents, then
store that number in firstArgument. If instead the first argument was some other text data
string, it would produce a run time error.
Double is a class (that is, a piece of code) that comes with Java. Inside Double there is a
method (section of code) called parseDouble. This method takes a text data string given to
it in its brackets, converts it into an double and returns that number. A run time error will
occur if the given string does not represent a number. For example
double firstArgument = Double.parseDouble(args[0]);
would take the first command line argument and, assuming it represents a number, would
turn it into the number it represents, then store that number in firstArgument. To represent
a number, the string must be a sequence of digits, possibly with a decimal point and maybe a
negative sign in front. If instead the first argument was some other text data string, it would
produce a run time error.
import java.util.Scanner;
...
Scanner inputScanner = new Scanner(System.in);
...
Each time we want a line of text we invoke the nextLine() instance method.
String line = inputScanner.nextLine();
...
Essentially, System.in accesses the standard input as a stream of bytes of data. A Scanner
turns these bytes into a stream of characters (i.e. char values) and offers a variety of instance
methods to scan these into whole lines, or various tokens separated by white space, such as
spaces, tabs and end of lines. Some of these instance methods are listed below.
Public method interfaces for class Scanner (some of them).
Method
nextLine
Return
String
nextInt
int
nextBoolean
nextByte
nextDouble
nextFloat
nextLong
nextShort
boolean
byte
double
float
long
short
Arguments
Description
Returns all the text from the current point in the
character stream up to the next end of line, as a
String.
Skips any spaces, tabs and end of lines and then
reads characters which represent an integer, and
returns that value as an int. It does not skip
spaces, tabs or end of lines following those characters. The characters must represent an integer, or
a run time error will occur.
Similar to nextInt() except for a boolean value.
Similar to nextInt() except for a byte value.
Similar to nextInt() except for a double value.
Similar to nextInt() except for a float value.
Similar to nextInt() except for a long value.
Similar to nextInt() except for a short value.
15052
There are very many more features in this class, including the ability to change what is considered to be characters that separate the various tokens.
...
Scanner input = new Scanner(new File("my-data.txt"));
we are asking for an object of type String to be created, containing the text Java, and for a
reference to that object to be placed in the variable called name. So, even though we do not
15053
use the special word new, whenever we write a string literal in our code, we are asking for a
new String object to be created.
String name
A String object
The text of a String is stored as a sequence of characters, each of these is a member of the
char type. This text cannot be changed: Strings are immutable objects.
Return
Arguments
char
int
compareTo
int
String
endsWith
boolean
String
equals
boolean
String
indexOf
int
String
length
startsWith
int
boolean
String
substring
String
int
Description
This returns the character at the specified string
index. The characters are indexed from zero upwards.
Compares the text of this with the given other, using lexicographic ordering (alphabetic/dictionary
order). Returns 0 if they are equal, a negative int if
this is less than the other, a positive int otherwise.
Returns true if and only if the text of this string
ends with that of the given other.
Returns true if and only if this string contains the
same text as the given other.
Returns the index within this string of the first occurrence of the given other string, or -1 if it does not
occur.
Returns the length of this string.
Returns true if and only if the text of this string
starts with that of the given other.
Returns a new string that is a substring of this string.
The substring begins with the character at the given
index and extends to the end of this string.
15054
Return
String
toLowerCase String
toUpperCase String
Arguments
int, int
Description
Returns a new string that is a substring of this string.
The substring begins at the first given index and extends to the character at the second index minus one.
Returns a new string which is the same as this one
except that all upper case letters are replaced with
their corresponding lower case letter.
Returns a new string which is the same as this one
except that all lower case letters are replaced with
their corresponding upper case letter.
has precisely the same effect as the following. (Observe the %n.)
System.out.printf("The distance between %s and %s is %1.2f.%n",
p1, p2, p1.distanceFromPoint(p2));
Resulting array
{ "The", "cat", "sat",
"on", "the", "mat" }
"The--cat--sat--on--the--mat".split("-")
{ "The", "", "cat",
"", "sat", "", "on",
"", "the", "", "mat" }
"The--cat--sat--on--the--mat".split("-+")
{ "The", "cat", "sat",
"on", "the", "mat" }
"The-cat--sat---on----the--mat".split("-+") { "The", "cat", "sat",
"on", "the", "mat" }
In the last two examples, the regular expression "-+" means one or more hyphens.
Return
Arguments
boolean
char
isDigit
boolean
char
isLetter
boolean
char
boolean
char
isUpperCase
boolean
char
toLowerCase
char
char
toUpperCase
char
char
Description
Returns true if the given char is a white space
character, (e.g. space character, tab character,
new line character), or false otherwise.
Returns true if the given char is a digit (e.g. 0,
8), or false otherwise.
Returns true if the given char is a letter (e.g. A,
a), or false otherwise.
Returns true if the given char is a letter or a digit,
or false otherwise.
Returns true if the given char is a lower case letter,
or false otherwise.
Returns true if the given char is an upper case letter, or false otherwise.
Returns the lower case equivalent of the given char
if it is an upper case letter, or the given char if it is
not.2
Returns the upper case equivalent of the given char
if it is a lower case letter, or the given char if it is
not.1
For maximum portability of code to different regions of the world, it is better to use the String versions of
these methods.
15056
9 Statement
9.1 Statement (page 18)
A command in a programming language, such as Java, which makes the computer perform
a task is known as a statement. System.out.println("I will output whatever I am
told to") is an example of a statement.
9.2 Statement: simple statements are ended with a semi-colon (page 18)
All simple statements in Java must be ended by a semi-colon (;). This is a rule of the Java
language syntax.
We use a single equal sign (=), with the name of the variable to the left of it, and the value we
wish it to be given on the right. In the above example, the integer literal 47 will be placed into
the variable noOfPeopleLivingInMyStreet. Assuming the variable was declared as an int
variable then this assignment would be allowed because 47 is an int.
int noOfPeopleToInviteToTheStreetParty;
when executed, would evaluate the expression on the right of the equal sign (=) and then place
the resulting value in the variable noOfPeopleToInviteToTheStreetParty.
int x;
int y;
int z;
maximumOfXYandZ = y;
if (maximumOfXYandZ < z)
maximumOfXYandZ = z;
See that the variable maximumOfXYandZ is given a value which then might get changed, so that
after the end of the second if statement it holds the correct value.
A very common thing we want the computer to do, typically inside a loop, is to perform a
variable update. This is when a variable has its value changed to a new value which is based
on its current one. For example, the code
count = count + 1;
will add one to the value of the variable count. Such examples remind us that an assignment
statement is not a definition of equality, despite Javas use of the single equal sign!
15058
9.7 Statement: assignment statement: updating a variable: shorthand operators (page 87)
Operator
++
-+=
-=
*=
/=
Name
postfix increment
postfix decrement
compound assignment: add to
compound assignment: subtract from
compound assignment: multiply by
compound assignment: divide by
Example
x++
x-x += y
x -= y
x *= y
x /= y
Longhand meaning
x = x + 1
x = x - 1
x = x + y
x = x - y
x = x * y
x = x / y
The point of these postfix increment, postfix decrement and compound assignment operators is not so much to save typing when a program is being written, but to make the program
easier to read. Once you are familiar with them, you will benefit from the shorter and more
obvious code.
There is also a historical motivation. In the early days of the programming language C, from
which Java inherits much of its syntax, these shorthand operators caused the compiler to
produce more efficient code than their longhand counterparts. The modern Java compiler with
the latest optimization technology should remove this concern.
15059
This layout reflects our abstract thinking that the collection of statements is one construct
offering three choices, even though it is implemented using two if else statements. This idea
extends to cases where we want many choices, using many nested if else statements, without
the indentation having to increase for each choice.
15060
This will print the message if the variable has a value greater than 500, or otherwise execute the empty statement between the reserved word else and the semi-colon. Such empty
statements do nothing, as you would probably expect!
It is quite common to wish nothing to be done when the condition is false, and so Java offers
us the if statement. This is similar to the if else statement, except it simply does not have the
word else, nor a false part.
if (noOfPeopleToInviteToTheStreetParty > 500)
15061
When the condition of the if statement is true, the body of the if statement is executed. This
single statement is itself a compound statement, and so the three statements within it are executed. It is for this sort of purpose that the compound statement exists.
Note how we lay out the compound statement, with the opening brace at the same indentation
as the if statement, the statements within it having extra indentation, and the closing brace
lining up with the opening one.
Less usefully, a compound statement can be empty, as in the following example.
As you might expect, the meaning of an empty compound statement is the same as the meaning
of an empty statement!
int x = 1;
while (x < 20)
x = x + 2;
The variable starts off with the value 1, and then repeatedly has 2 added to it, until it is no
longer less than 20. This is when the loop ends, and x will have the value 21.
Notice the brackets around the condition and the semi-colon at the end of the statement inside
the loop. Notice also the way we lay out the code to make it easy to read, splitting the lines at
sensible places and adding more indentation at the start of the inner statement.
15062
Observe the similarity between the while loop and the if statement the only difference in
syntax is the first word. There is a similarity in meaning too: the while loop executes its body
zero or more times, whereas the if statement executes its body zero or one time. However,
if statements are not loops and you should avoid the common novice phrase if loop when
referring to them!
The statement starts with the reserved word for, which is followed by three items in brackets,
separated by semi-colons. Then comes the loop body, which is a single statement (often a
compound statement of course). The first of the three items in brackets is a for initialization,
which is performed once just before the loop starts. Typically this involves declaring a variable
and giving an initial value to it, as in the above example int count = 1. The second item is
the condition for continuing the loop the loop will only execute and will continue to execute
while that condition is true. In the example above the condition is count <= 10. Finally, the
third item, a for update, is a statement which is executed at the end of each iteration of the
loop, that is after the loop body has been executed. This is typically used to change the value
of the variable declared in the first item, as in our example count = count + 1.
So the overall effect of our simple example is: declare count and set its value to 1, check that it
is less than 10, print out Counting 1, add one to count, check again, print out Counting 2,
add one to count, check again, and so on until the condition is false when the value of count
has reached 11.
We do not really need the for loop, as the while loop is sufficient. For example, the code above
could have been written as follows.
int count = 1;
while (count <= 10)
However you will see that the for loop version has placed together all the code associated with
the control of the loop, making it easier to read, as well as a little shorter.
15063
9.14 Statement: for loop: multiple statements in for update (page 136)
There is one very subtle difference between the for loop and while loop versions of the example
above, concerning the scope of the variable count, that is the area of code in which the variable
can be used. Variables declared in the initialization part of a for loop can only be used in the for
loop they do not exist elsewhere. This is an added benefit of using for loops when appropriate:
the variable, which is used solely to control the loop, cannot be accidentally used in the rest of
the code.
9.14 Statement: for loop: multiple statements in for update (page 136)
Java for loops are permitted to have more than one statement in their for update, that is, the
part which is executed after the loop body. Rather than always being one statement, this part
may be a list of statements with commas (,) between them.
One appropriate use for this feature is to have a for loop that executes twice, once each for the
two possible values of a boolean variable.
For example, the following code prints out scenarios to help train people to live in the city of
Manchester!
9.15 Statement: statements can be nested within each other (page 92)
Statements that control execution flow, such as loops and if else statements have other statements inside them. These inner statements can be any kind of statement, including those that
control the flow of execution. This allows quite complex algorithms to be constructed with
unlimited nesting of different and same kinds of control statements.
For example, one simple (but inefficient) way to print out the non-negative multiples of x which
lie between y ( 0) and z inclusive, is as follows.
15064
{
case 99: case 101:
The switch statement starts with the reserved word switch followed by a bracketed expression of a type that has discrete values, such as int (notably not double). The body of the
statement is enclosed in braces, ({ and }), and consists of a list of entries. Each of these starts
with a list of labels, comprising the reserved word case followed by a value and then a colon
(:). After the labels we have one or more statements, typically ending with a break statement.
One (at most) label is allowed to be the reserved word default followed by a colon usually
written at the end of the list.
When a switch statement is executed, the expression is evaluated and then each label in the
body is examined in turn to find one whose value is equal to that of the expression. If such
a match is found, the statements associated with that label are executed, down to the special
break statement which causes the execution of the switch statement to end. If a match is not
found, then instead the statements associated with the default label are executed, or if there
is no default then nothing is done.
15065
valueToThePower1
valueToThePower2
valueToThePower4
valueToThePower8
=
=
=
=
value;
valueToThePower1 * valueToThePower1;
valueToThePower2 * valueToThePower2;
valueToThePower4 * valueToThePower4;
int result = 1;
switch (power)
{
case 10: result *=
case 9: result *=
case 8: result *=
break;
case 7: result *=
case 6: result *=
case 5: result *=
case 4: result *=
break;
case 3: result *=
case 2: result *=
break;
case 1: result *=
break;
valueToThePower1;
valueToThePower1;
valueToThePower8;
valueToThePower1;
valueToThePower1;
valueToThePower1;
valueToThePower4;
valueToThePower1;
valueToThePower2;
valueToThePower1;
} // switch
System.out.println(result);
If you find the semantics of the switch statement somewhat inelegant, then do not worry you
are not alone! Java inherited it from C, where it was designed more to ease the work of the
15066
compiler than to be a good construct for the programmer. You will find the switch statement is
less commonly used than the if else statement, and the majority of times you use it, you will
want to have break statements on every set of case labels. Unfortunately, due to them being
optional, accidentally missing them off does not cause a compile time error.
int x = 1;
do
x += 2;
while (x < 20);
int x = 0;
int y = 100;
do
x++;
y--;
} while (x != y);
The above is a long winded and inefficient way of giving both the variables x and y the value
50.
Note that, because the condition is evaluated after the body is executed, the body is executed at
least once. This is in contrast to the while loop, which might have have its body executed zero
times.
15067
Then we can find the sum of the array elements with the following for-each loop.
double myTotalFingerLength = 0;
for (double fingerLength : myFingerLengths)
myTotalFingerLength += fingerLength;
This is saying that we want to loop over all the elements in the array which is referenced by
myFingerLengths, storing each element in turn in the variable fingerLength, and adding it to
the value of myTotalFingerLength. In other words for each fingerLength in myFingerLengths,
add fingerLength to myTotalFingerLength.
The above for-each loop is actually a shorthand for the following for loop.
double myTotalFingerLength = 0;
for (int index = 0; index < myFingerLengths.length; index++)
{
double fingerLength = myFingerLengths[index];
myTotalFingerLength += fingerLength;
} // for
Here is the general case of the for-each loop when used with arrays, where anArray is a variable
referring to some array with array base type SomeType and elementName is any suitable
variable name.
popular name for this loop may seem odd, because the word each is not used in it, but the meaning of
the statement is similar to a concept in languages such as Perl[17], which does use the phrase for each. And we
actually say for each when we read out the Java statement.
15068
A for-each loop can and should be used instead of a for loop in places where we wish to loop
over all the elements of a single array, and the array index is only used to access (not change)
the elements of that array. In other words, for processing where the element values matter, but
their position in the array is not directly used, and there is only one array. So, for example, the
following code cannot be replaced with a for-each loop.
int weightedSum = 0;
for (int index = 0; index < numbers.length; index++)
otherNumbers[index] = numbers[index];
Finally, a common error (even in some Java text books!) is to think that a for-each loop can be
used to change the array elements. For example, the following code compiles without errors,
but it does not do what you might expect!
number = 10;
The for-each loop above is a shorthand for the following, which you can see achieves nothing.
{
int number = numbers[index];
number = 10;
} // for
15069
try
The statement consists of two parts, the try block and the catch clause. When the try statement is executed, the code inside the try block is obeyed as usual. However, if at some point
during this execution an exception occurs, an instance of java.lang.Exception is created,
and then control immediately transfers to the catch clause. The newly created Exception object is available to the code in the catch clause, as an exception parameter, which is a bit like
a method parameter. For this reason, we must declare a name (and type) for the exception in
the round brackets following the reserved word catch.
For example, the following method computes the mean average of an array of int values,
dealing with the possibility of the reference being the null reference or the array being an
empty array, by catching the exception and returning zero instead.
private double average(int[] anArray)
{
try
{
int total = anArray[0];
for (int i = 1; i < anArray.length; i++)
total += anArray[i];
return total / (double) anArray.length;
} // try
catch (Exception exception)
{
// Report the exception and carry on.
System.err.println(exception);
return 0;
} // catch
} // average
Note: unlike most Java statements that may contain other statements, the two parts of the try
statement must both be compound statements, even if they only contain one statement!
15070
9.21 Statement: try statement: with multiple catch clauses (page 347)
9.21 Statement: try statement: with multiple catch clauses (page 347)
The try statement may have more than one catch clause, each of which is designed to catch a
different kind of exception. When an exception occurs in the try block, the execution control
transfers to the first matching catch clause, if there is one, or continues to propagate out of the
try statement if there is not.
For example, consider the following method which finds the largest of some numbers stored
in an array of String objects.
{
try
{
int maximumSoFar = Integer.parseInt(anArray[0]);
for (int i = 1; i < anArray.length; i++)
{
int thisNumber = Integer.parseInt(anArray[i]);
if (thisNumber > maximumSoFar)
maximumSoFar = thisNumber;
} // for
return maximumSoFar;
} // try
catch(NumberFormatException exception)
{
System.err.println("Cannot parse item as an int: "
+ exception.getMessage());
return 0;
} // catch
catch(ArrayIndexOutOfBoundsException exception)
{
System.err.println("There is no maximum, as there are no numbers!");
return 0;
} // catch
} // maximum
If the array referenced by the method parameter is an empty array, that is, it has no elements,
then an ArrayIndexOutOfBoundsException object will be created when the code tries to
access the first array element. This will be caught by the second catch clause. If, on the other
hand, one of the strings in the array does not represent an int then a NumberFormatException
object will be created inside the parseInt() method, and this will be caught by the first catch
clause.
However, if the given method argument was actually the null reference, that is, there is no
array at all not even an empty one, then a NullPointerException object is created when
the code tries to follow the array reference to access element zero of it.
15071
The code anArray[0] means follow the reference in the variable anArray to the array referenced by it, and then get the value stored at array index 0 in that array. In this example there
is no catch clause matching a NullPointerException, so the execution control transfers out
of the try statement altogether, and out of the method. If the method call was itself inside the
following try statement, then the NullPointerException would get caught there.
try
{
int max = maximum(null);
...
} // try
catch (NullPointerException exception)
{
System.err.println("Silly me!");
} // catch
15072
10 Error
10.1 Error (page 20)
When we write the source code for a Java program, it is very easy for us to get something
wrong. In particular, there are lots of rules of the language that our program must obey in order
for it to be a valid program.
15073
11 Execution
11.1 Execution: sequential execution (page 23)
Programs generally consist of more than one statement, in a list. We usually place these on
separate lines to enhance human readability, although Java does not care about that. Statements
in such a list are executed sequentially, one after the other. More correctly, the Java compiler
turns each one into corresponding byte codes, and the virtual machine executes each collection of byte codes in turn. This is known as sequential execution.
15074
11.5 Execution: parallel execution threads: the GUI event thread (page
254)
When we have a program that places a graphical user interface (GUI) window on the screen,
the Java virtual machine creates another thread, which we shall call the GUI event thread.
This is created when the first window of the program is shown. As a result of this, the program
does not end when the main thread reaches the end of the main method this is of course
what we want for a program with a GUI.
15075
(In reality, the virtual machine creates several GUI event threads, but it suffices to think of there
being just the one.)
The GUI event thread spends most of its life asleep quietly doing nothing. When the end user
of the program does something that might be of interest to the program, the operating system
informs the virtual machine, which in turn wakes up the GUI event thread. Such interesting
things include moving the mouse into, out of, or within a window belonging to the program,
pressing a mouse key while the mouse is over such a window, typing a keyboard key while
a window of the program has keyboard focus, etc.. These things are collectively known as
events.
When it is woken up, the GUI event thread looks to see what might have changed as a result of
the end users action. For example, he or she may have pressed a GUI button belonging to the
program. For each event which is definitely interesting, the GUI event thread executes some
code which is designed to process that event. Then it goes back to sleep again.
12 Code clarity
12.1 Code clarity: layout (page 31)
Java does not care how we lay our code out, as long as we use some white space to separate
adjacent symbols that would otherwise be treated as one symbol if they were joined. For
example public void with no space between the words would be treated as the single symbol
publicvoid and no doubt cause a compile time error. So, if we were crazy, we could write
all our program source code on one line with the minimum amount of space between symbols!
Oh dear it ran off the side of the page (and that was with a smaller font too). Let us split it up
into separate lines so that it fits on the page.
15076
System.out.println("Hello Mercury!");System.out.println(
"Hello Venus!");System.out.println("Hello Earth!");System.out.println
("Hello Mars!");System.out.println("Hello Jupiter!");System.out.
println("Hello Saturn!");System.out.println("Hello Uranus!");System.
out.println("Hello Neptune!");System.out.println("Goodbye Pluto!");}}
Believe it or not, this program would still compile and run okay, but hopefully you will agree
that it is not very easy for us to read. Layout is very important to the human reader, and
programmers must take care and pride in laying out their programs as they are written. So we
split our program sensibly, rather than arbitrarily, into separate lines, and use indentation (i.e.
spaces at the start of some lines), to maximize the readability of our code.
System.out.println("Hello world!");
}
}
When code with long lines is viewed on the screen, the reader either has to use a horizontal
scroll bar to see them, or make the window so wide that other windows cannot be placed next
to it. Worst of all, when code with long lines is printed on paper there is a good chance that the
long lines will disappear off the edge of the page! At very least, they will be wrapped onto the
next line making the code messy and hard to read.
So a good rule of thumb is to keep your source code lines shorter than 80 characters long. You
can do this simply in most text editors by never making the text window too wide and never
using the horizontal scroll bar while writing the code.
When we do have a statement that is quite long, we simply split it into separate lines at carefully chosen places. When we choose such places, we bear in mind that most human readers
scan down the left hand side of the code lines, rather than read every word. So, if a line is a
continuation of a previous line, it is important to make this obvious at the start of it. This means
using an appropriate amount of indentation, and choosing the split so that the first symbol on
the continued line is not one which could normally start a statement.
A little thought at the writing stage quickly leads to a habit of good practise which seriously
reduces the effort required to read programs once they are written. Due to bug fixing and
general maintenance over the lifetime of a real program, the code is read many more times than
it is written!
12.5 Code clarity: comments: marking ends of code constructs (page 83)
Another good use of comments is to mark every closing brace (}) with a comment saying what
code construct it is ending. The following skeleton example code illustrates this.
15078
{
public static void main(String[] args)
...
while (...)
...
...
...
} // while
...
} // main
} // class SomeClass
13 Design
13.1 Design: hard coding (page 36)
Programs typically process input data, and produce output data. The input data might be
given as command line arguments, or it might be supplied by the user through some user
interface such as a graphical user interface or GUI. It might be obtained from files stored on
the computer.
Sometimes input data might be built into the program. Such data is said to be hard coded.
This can be quite common while we are developing a program and we havent yet written the
code that obtains the data from the appropriate place. In other cases it might be appropriate to
have it hard coded in the final version of the program, if such data only rarely changes.
15079
15080
can find. This is called noun identification and is useful because the objects inherent in the
solution to most problems actually appear as nouns in the description of the problem. Some of
the nouns will relate to objects that will exist at run time, and some will relate to classes in
the program.
It is not the case that every noun found will be a class or an object, of course, and sometimes
we need classes that do not appear as nouns in the requirements. However, the technique is
usually a good way of starting the process.
15081
12 79 60 17
On the first pass, we compare 45 with 78, which are in order, and then 78 with 12 which need
swapping. Next we compare 78 with 79, and so on. Eventually we end up with 79 being at the
end of the list.
Start
45 <= 78
78 > 12
78 <= 79
79 > 60
79 > 17
45
78
12
okay 45 <=
78
12
swap
45
12 <=
78
okay
45
12
78 <=
swap
45
12
78
swap
45
12
78
79
79
79
79
60 <=
60
60
60
60
60
79
17 <=
17
17
17
17
17
79
The highest number, 79, is in place, but the preceding items are not yet sorted.
After the second pass, the second highest item must be at the penultimate place in the list, and
so on. It follows that, if there are N items in the list, then N 1 passes are enough to guarantee
the whole list is sorted. Furthermore, the first pass needs to look at N 1 adjacent pairs, but
the next pass can look at one less, because we know the highest item is in the right place at the
end. The very last pass only needs to look at one pair, as all the other items must be in place by
then.
Going back to our example, here are the results at the end of the next passes.
Pass
2
3
4
5
12
12
12
12
45
45
17
17
60
17
45
45
17
60
60
60
78
78
78
78
79
79
79
79
Notice that pass 5 was actually unnecessary as the array became sorted after pass 4.
Here is some pseudo code for sorting anArray using bubble sort.
15082
This can be improved by observing that the list may get sorted before the maximum number
of passes needed to guarantee it. For example it could be sorted to start with! Here is an
alternative design.
int unsortedLength = anArray length
boolean changedOnThisPass
do
changedOnThisPass = false
for pairLeftIndex = 0 to unsortedLength - 2
if items in anArray at pairLeftIndex and pairLeftIndex + 1
are out of order
swap them over
changedOnThisPass = true
end-if
end-for
unsortedLength-while changedOnThisPass
{
int searchPos = 0;
while (searchPos < anArray.length && anArray[searchPos] != toFind)
searchPos++;
if (searchPos == anArray.length) return -1;
else
return searchPos;
} // posOfInt
If the value of toFind is not in the array, then eventually the value of searchPos will reach
anArray.length. At that point the first conjunct of the while loop condition, searchPos <
anArray.length becomes false and hence so does the conjunction itself, without it evaluating the second conjunct, anArray[searchPos] != toFind. If on the other hand we swapped
15083
over the two conjuncts, when searchPos reaches that same value the (now) first conjunct
would cause an ArrayIndexOutOfBoundsException.
14 Variable
14.1 Variable (page 36)
A variable in Java is an entity that can hold a data item. It has a name and a value. It is rather
like the notion of a variable in algebra (although it is not quite the same thing). The name of
a variable does not change it is carefully chosen by the programmer to reflect the meaning
of the entity it represents in relation to the problem being solved by the program. However,
the value of a variable can (in general) be changed we can vary it. Hence the name of the
concept: a variable is an entity that has a (possibly) varying value.
The Java compiler implements variables by mapping their names onto computer memory
locations, in which the values associated with the variables will be stored at run time.
So one view of a variable is that it is a box, like a pigeon hole, in which a value can be placed. If
we wish, we can get the program to place a different value in that box, replacing the previous;
and we can do this as many times as we want to.
Variables only have values at run time, when the program is running. Their names, created by
the programmer, are already fixed by the time the program is compiled. Variables also have
one more attribute the type of the data they are allowed to contain. This too is chosen by the
programmer.
declares an int variable, that is a variable the value of which will be an int, and which has the
name noOfPeopleLivingInMyStreet. Observe the semi-colon (;) which, according to the
15084
14.3 Variable: a value can be assigned when a variable is declared (page 42)
Java syntax rules, is needed to terminate the variable declaration. At run time, this variable is
allowed to hold an integer (whole number). Its value can change, but it will always be an int.
The name of a variable should reflect its intended meaning. In this case, it would seem from
its name that the programmer intends the variable to always hold the number of people living
in his or her street. The programmer would write code to ensure that this meaning is always
reflected by its value at run time.
By convention, variable names start with a lower case letter, and consist of a number of words,
with the first letter of each subsequent word capitalized.
a good thing, as it allows us to localize our variables to the exact point of their use, and so
avoid cluttering up other parts of the code with variables available to be used but which have
no relevance.
Consider the following symbolic example.
public static void main(String[] args)
...
int x = ...
... x is available here.
while (...)
{
... x is available here.
int y = ...
... x and y are available here.
} // while
... x is available here, but not y,
... so we cannot accidentally refer to y instead of x.
} // main
The variable x can be used from the point of its definition onwards up to the end of the method,
whereas the variable y can only be used from the point of its definition up to the end of the
compound statement which is the body of the loop.
15086
Notice that we use the reserved word static in their declaration. Also, class variables have a
visibility modifier the above have all been declared as being private, which means they can
only be accessed by code inside the class which has declared them.
declares two variables, both of type int. We can even assign values to the variables, as in the
following.
int minimumVotingAge = 18, minimumArmyAge = 16;
This shorthand is not as useful as one might think, because of course, we typically have a
comment before each variable explaining what its meaning is. However, we can sometimes
have one comment which describes a group of variables.
15087
Some people would argue that this makes for more readable code, as in effect, we have named
the condition in a helpful way. How appropriate that is would depend on how obvious the code
is otherwise, which is context dependent and ultimately subjective. Of course, the motive for
storing the condition value in a variable is less subjective if we wish to use it more than once.
boolean correctOrder = age1 < age2 || age1 == age2 && height1 <= height2;
if (correctOrder)
Many novice programmers, and even some so-called experts, when writing the code above may
have actually written the following.
boolean correctOrder;
if (age1 < age2 || age1 == age2 && height1 <= height2)
correctOrder = true;
else
correctOrder = false;
if (correctOrder == true)
There are three terrible things wrong with this code (two of them are the same really) identify
them, and do not write code like that!
15088
char firstLetter = J;
declares a variable of type char, with the name firstLetter. At run time, this variable is
allowed to hold a char data item, that is a single character.
{
private double x;
private double y;
...
} // class Point
Like class variables, instance variables have a visibility modifier the above variables have
both been declared as being private, which means they can only be accessed by code inside
the class which has declared them.
Class variables belong to the class in which they are declared, and they are created at run time
in the static context when the class is loaded into the virtual machine. There is only one copy
of each class variable. By contrast, instance variables are created dynamically, in a dynamic
context, when the object they are part of is created during the run of the program. There are
as many copies of each instance variable as there are instances of the class: each object has its
own set of instance variables.
originally been made private, the programmer would know that there could not be any mention
of them in other classes. So it would be safe to replace them with ones of a different name
and which work differently. To make the points behave the same as before, the values given to
the constructor method would be converted from x and y values to polar values, before being
stored, and the toString() method could convert them back again.
The above defines two local variables or method variables of type Point. We also can have
class variables and even instance variables whose type is a class.
15090
Date someBirthday
= new Date(birthDate.day, birthDate.month, birthDate.year + 1);
Yes, it can be useful: for example, when we want to use objects just once, straight after constructing them.
Also, we can change the value of a variable making it refer to a different object.
This creates a new Date object, and stores the reference to it in someBirthday overwriting
the reference to the previous Date object. This is illustrated in the following diagram.
A Date object
Date someBirthday
01
07
2010
Date someBirthday
A Date object
01
01
07
07
2010
2011
There is a special reference value, known as the null reference, which does not refer to an
object. We can talk about it using the reserved word null. It is used, for example, as a value
for a variable when we do not want it to refer to any object at this moment in time.
15092
14.17 Variable: of a class type: holding the same reference as some other variable (page
216)
Point p2 = null;
So, in the example code here we have two Point variables, p1 and p2, but (at run time) only
one Point object.
Suppose the Point class has instance methods getX() and getY() with their obvious implementations. Then obtaining the x value of the object referenced by p1 is fine; the following
code would print 75.
System.out.println(p1.getX());
However, the similar code involving p2 would cause a run time error (an exception called
NullPointerException).
System.out.println(p2.getX());
This is because there is no object referenced by p2, and so any attempt to access the referenced
object must fail.
14.17 Variable: of a class type: holding the same reference as some other
variable (page 216)
A variable which is of a class type can hold a reference to any instance of that class (plus the
null reference). There is nothing to stop two (or more) variables having the same reference
value. For example, the following code creates one Point object and has it referred to by two
variables.
15093
14.17 Variable: of a class type: holding the same reference as some other variable (page
216)
Point p1
A Point object
private double x
10
private double y
30
Point p2
This reminds us that a variable is not itself an object, but merely a holder for a reference to an
object.
Having two or more variables refer to the same object can cause us no problems if it is an
immutable object because we cannot change the objects state no matter which variable we
use to access it. So, in effect, the object(s) referred to by the two variables behave the same as
they would if they were two different objects. The following code has the same effect as the
above fragment, almost no matter what we do with p1 and p2 subsequently.
The only behavioural difference between the two fragments is the conditions p1 == p2 and
p1 != p2 which are true and false respectively for the first code fragment, and the other
way round for the second one.
If, on the other hand, an object referenced by more than one variable is a mutable object we
have to be careful because any change made via any one of the variables causes the change to
occur in the (same) object referred to by the other variables. This may be, and often is, exactly
what we want, or it may be a problem if our design is poor or if we have made a mistake in our
code and the variables were not meant to share the object.
Consider the following simple example.
{
private final String name;
private int salary;
public Employee(String requiredName, int initialSalary)
15094
14.17 Variable: of a class type: holding the same reference as some other variable (page
216)
name = requiredName;
salary = initialSalary;
} // Employee
public String getName()
{
return name;
} // getName
public void setSalary(int newSalary)
salary = newSalary;
} // setSalary
public int getSalary()
{
return salary;
} // getSalary
} // class Employee
...
Employee debora = new Employee("Debs", 50000);
Employee sharmane = new Employee("Shaz", 40000);
...
Employee worstEmployee = debora;
Employee bestEmployee = sharmane;
...
15095
The effect of the accidental sharing is to give Sharmane, who is our best employee, a pay
increase to 55,000 immediately followed by a pay cut to zero because worstEmployee and
bestEmployee are both referring to the same object, the one which is also referred to by
sharmane. Meanwhile our worst employee, Debora, gets to keep her 50,000! Further more,
the report only actually talks about Sharmane in both contexts!
Our best employee, Shaz, is paid 0
Our worst employee, Shaz, is paid 0
By convention, class constants are usually named using only capital letters with the words
separated by underscores ( ).
14.20 Variable: final variables: class constant: a set of choices (page 308)
One use of class constants is to define a set of options for the users of a class, without them
having to know what values have been chosen to model each option they instead use the name
of one or more class constants to represent their choices.
15096
14.21 Variable: final variables: class constant: a set of choices: dangerous (page 308)
For example, the following could be possible directions available in a class that is part of a
game that permits simple movement of some game entity.
public
public
public
public
static
static
static
static
final
final
final
final
int
int
int
int
UP = 0;
DOWN = 1;
LEFT = 2;
RIGHT = 3;
Apart from leading to more readable code, this technique gives us more flexibility: the maintainer of the source code might decide for some reason to change the values (but not the names)
of the four constants. This should not cause any code outside of the class to need rewriting.
14.21 Variable: final variables: class constant: a set of choices: dangerous (page 308)
The use of int class constants to model a small set of options does have two dangers.
The constants could be used for other purposes e.g. they could be used inappropriately
in some arithmetic expression.
Someone may accidentally use another int value which is not one of the constants in
places where a constant should be used. The compiler would accept it because it is an
int.
As arrays are objects, they are accessed via references. So an array variable at run time
holds either a reference to an array or the null reference. The following diagram shows the
above variable referring to an array of int values.
int[] salaries
15000
25000
17750
15097
23950
49950
12700
15 Expression
15.1 Expression: arithmetic (page 38)
We can have arithmetic expressions in Java rather like we can in mathematics. These can contain literal values, that is constants, such as the integer literals 1 and 18. They can also contain variables which have already been declared, and operators to combine sub-expressions
together. Four common arithmetic operators are addition (+), subtraction (-), multiplication (*) and division (/). Note the use of an asterisk for multiplication, and a forward slash for
division computer keyboards do not have multiply or divide symbols.
These four operators are binary infix operators, because they take two operands, one on
either side of the operator. + and - can also be used as the unary prefix operators, plus and
minus respectively, as in -5.
When an expression is evaluated (expression evaluation) Java replaces each variable with
its current value and works out the result of the expression depending on the meaning of the
operators. For example, if the variable noOfPeopleLivingInMyStreet had the value 47 then
the expression noOfPeopleLivingInMyStreet + 4 would evaluate to 51.
Value
18
16
In mathematics one would expect to get the same answer from both these expressions, but not
in Java!
Result
4
4.0
4
4.5
4.5
4.5
Type of Result
int
double
int
double
double
double
{
return number % 2 == 0;
} // isEven
15099
The value of the first expression is made from the addition of 2 and 4 and then multiplication
of the resulting 6 by 8 to get 48. The second expression is evaluated by multiplying 4 with 8
to get 32 and then adding 2 to that result, ending up with 34.
To help us see the structure of these two expressions, let us draw them as expression trees.
(2 + 4) * 8
*
___/ \
+
/ \
2
2 + (4 * 8)
+
/ \___
2
*
/ \
4
8
Java allows us to have expressions without any brackets, or more generally, without brackets
around every sub-expression. It provides rules to define what the structure of such an expression
is, i.e., where the missing brackets should go. If you look at the 4 in the above expression, you
will see that it has an operator on either side of it. In a sense, the + operator and the * operator
are both fighting to have the 4 as an operand. Rather like a tug of war, + is pulling the 4 to the
left, and * is tugging it to the right. The question is, which one wins? Java, as in mathematics,
provides the answer by having varying levels of operator precedence. The * and / operators
have a higher precedence than + and -, which means * fights harder than +, so it wins! 2 + 4
* 8 evaluates to 34.
10
10
10
10
+
+
-
7
7
7
7
+
+
-
3
3
3
3
In all four expressions, the 7 is being fought over by two operators which have the same
precedence: either two +, two -, or one of each. So where should the missing brackets go?
The expression trees could have one of the two following structures, where OP1 is the first
operator, and OP2 is the second.
10 OP1 (7 OP2 3)
OP1
/
\___
10
OP2
/
\
7
3
___OP2
/
\
OP1
3
/
\
10
7
Value
20
20
14
14
6
0
0
6
As you can see, it does make a difference sometimes in these cases when the first operator
is subtraction (-). So how does Java resolve this problem? As in mathematics, Java operators
have an operator associativity as well as a precedence. The operators +, -, * and / all have
left associativity which means that when two of these operators of equal precedence are both
fighting over one operand, it is the left operator that wins. If you like, the tug of war takes
place on sloping ground with the left operator having the advantage of being lower down than
the right one!
Expression
10 + 7 + 3
10 + 7 - 3
10 - 7 + 3
10 - 7 - 3
Implicit brackets
(10 + 7) + 3
(10 + 7) - 3
(10 - 7) + 3
(10 - 7) - 3
15101
Value
20
14
6
0
The operators * and / also have equal precedence (but higher than + and -) so similar situations
arise with those too.
!=
<
>
<=
>=
Title
Equal
Description
This is the equal operator, which provides the notion of
equality. a == b yields true if and only if the value of
a is the same as the value of b.
Not equal
This is the not equal operator, providing the the notion
of not equality. a != b yields true if and only if the
value of a is not the same as the value of b.
Less than
This is the less than operator. a < b yields true if and
only if the value of a is less than the value of b.
Greater than
This is the greater than operator. a > b yields true if
and only if the value of a is greater than the value of b.
Less than or equal
This is the less than or equal operator. a <= b yields
true if and only if the value of a is less than value of b,
or is equal to it.
Greater than or equal This is the greater than or equal operator. a >= b
yields true if and only if the value of a is greater than
value of b, or is equal to it.
15102
Title
and
Posh title
conjunction
||
or
disjunction
not
negation
Description
c1 && c2 is true if and only if both conditions c1
and c2 evaluate to true. Both of the two conditions, known as conjuncts, must be true to satisfy
the combined condition.
c1 || c2 is true if and only if at least one of the
conditions c1 and c2 evaluate to true. The combined condition is satisfied, unless both of the two
conditions, known as disjuncts, are false.
!c is true if and only if the condition c evaluates to
false. This operator negates the given condition.
We can define these operators using truth tables, where ? means the operand is not evaluated.
c1
c2
c1 && c2
c1
true
true
false
true
false
true
false
false
true
false
false
c2
?
true
false
c1 || c2
true
true
false
!c
true
false
false
true
Using these operators, we can make up complex conditions, such as the following.
age1 < age2 || age1 == age2 && height1 <= height2
As with the arithmetic operators, Java defines operator precedence and operator associativity to disambiguate complex conditions that are not fully bracketed, such as the one above.
&& and || have a lower precedence than the relational operators which have a lower precedence
than the arithmetic ones. ! has a very high precedence (even more so than the arithmetic operators) and && has a higher precedence than ||. So the above example expression has implicit
brackets as follows.
(age1 < age2) || ((age1 == age2) && (height1 <= height2))
This might be part of a program that sorts people standing in a line by age, but when they
are the same age, it sorts them by height. Assuming that the int variables age1 and height1
contain the age and height of one person, and the other two variables similarly contain that
data for another, then the following code might be used to tell the pair to swap their order if
necessary.
if (age1 < age2 || age1 == age2 && height1 <= height2)
We might have, perhaps less clearly, chosen to write that code as follows.
15103
You might find it tricky, but its worth convincing yourself: yet another way of writing code
with the same effect would be as follows.
In mathematics, we are used to writing expressions such as x y z to mean true, if and only
if y lies in the range x to z, inclusive. In Java, such expressions need to be written as x <= y
&& y <= z.
Also, in everyday language we are used to using the words and and or where they have very
similar meanings to the associated Java operators. However, we say things like my mothers
age is 46 or 47. In Java, we would need to write myMumAge == 46 || myMumAge == 47
to capture the same meaning. Another example, my brothers are aged 10 and 12, might be
coded as myBrother1Age == 10 && myBrother2Age == 12.
However, there are times in everyday language when we say and when we really mean or
in logic, and hence would use || in Java. For example, the two possible ages for my dad are
49 and 53 is really the same as saying my dads age is 49 or my dads age is 53.
c ? e1 : e2
where c is some condition, and e1 and e2 are two expressions of some type. The condition
is evaluated, and if the value is true then e1 is evaluated and its value becomes the result of
the expression. If the condition is false then e2 is evaluated and its value becomes the result
instead.
For example
int maxXY;
if (x > y)
maxXY = x;
else
maxXY = y;
16 Package
16.1 Package (page 187)
There are hundreds of classes that come with Java in its application program interface (API),
and even more that are available around the world for reusing in our programs if we wish. To
help manage this huge number of classes, they are grouped into collections of related classes,
called packages. But even this is not enough to make things manageable, so packages are
grouped into a hierarchy in a rather similar way to how a well organized file system is arranged
into directories and sub-directories. For example, there is one group of standard packages
called java and another called javax.
This fully qualified name is unique: if someone else was to create a class called Scanner then
it would not be in the same package, so the two would not be confused.
We can refer to a class using its fully qualified name, for example the following declares a
variable of type java.util.Scanner and creates an instance of the class too.
17 GUI API
17.1 GUI API: JFrame (page 245)
Each instance of the class javax.swing.JFrame corresponds to a window that appears on the
screen.
15106
public
public
public
public
static
static
static
static
final
final
final
final
int
int
int
int
DO_NOTHING_ON_CLOSE = ?;
HIDE_ON_CLOSE = ?;
DISPOSE_ON_CLOSE = ?;
EXIT_ON_CLOSE = ?;
We simply use whichever class constant suits us, as in the following example.
setDefaultCloseOperation(DISPOSE_ON_CLOSE);
17.9 GUI API: Container: add(): adding with a position constraint (page
268)
The class java.awt.Container has another instance method called add which takes a graphical user interface (GUI) component and some other object constraining how the component should be positioned. This is intended for use with layout managers that use position
constraints, such as java.awt.BorderLayout. For example, the following code makes the
JLabel appear in the north position of myContainer.
myContainer.setLayout(new BorderLayout());
myContainer.add(new JLabel("This is in the north"), BorderLayout.NORTH);
15108
15109
The argument is an int value, and should be an appropriate class constant, including the
following.
This next example constructs a GridLayout which has two columns, and as many rows as are
needed depending upon the number of components being laid out.
If both the rows and columns arguments are non-zero, then the columns argument is totally
ignored! Neither values may be negative, and at least one of them must be non-zero, otherwise
we get a run time error.
We can also specify the horizontal and vertical gaps that we wish to have between items in the
grid. These can be given via a constructor method that takes four arguments.
15110
The above example creates a GridLayout that has five columns, with a horizontal gap of 10
pixels between each column, and a vertical gap of 20 pixels between each row. A pixel is the
smallest unit of display position. Its exact size will depend on the resolution and physical size
of the computer monitor.
BorderLayout.CENTER
BorderLayout.SOUTH
15111
BorderLayout.EAST
BorderLayout.WEST
BorderLayout.NORTH
Suppose also we wish events from that source to be processed by some code that we write. Let
us put that in a class called SomeKindOfEventListener for this abstract example.
{
public void processSomeKindOfEvent(SomeKindOfEvent e)
To link our code to the event source, we would make an instance of SomeKindOfEventListener
and register it with the event source as a listener.
The above code (or rather a concrete version of it) would typically be run in the main thread
during the set up of the GUI. The following diagram illustrates the finished relationship between the source and listener objects.
15112
SomeKindOfEventSource source
A SomeKindOfEventSource object
A SomeKindOfEventListener object
set of listeners
processSomeKindOfEvent
addSomeKindOfEventListener
Now when an event happens, the GUI event thread can look at the set of listeners in the source
object, and call the processSomeKindOfEvent() instance method belonging to each of them.
So, when our source object generates an event, the processSomeKindOfEvent() instance
method in our listener object is called.
Java Swing actually has several different kinds of listener for supporting different kinds of
event. The above example is just an abstraction of this idea, so do not take the names
SomeKindOfEventSource, SomeKindOfEventListener, processSomeKindOfEvent and addSomeKindOfLi
literally each type of event has corresponding names that are appropriate to it. For example, events generated by GUI buttons are known as ActionEvents and are processed by
ActionListener objects which have an actionPerformed() instance method and are linked
to the event source by an addActionListener() instance method.
15113
Each implementation of the method will perform whatever task is appropriate as a response to
the particular action in a particular program.
15115
15116
To make the JTextArea scrollable, we would replace the above with the following code instead.
18 Interface
18.1 Interface (page 257)
An interface is like a class, except all the instance methods in it must have no bodies. It is
used as the basis of a kind of contract, in the sense that it may be declared that some class implements an interface. This means that it supplies full definitions for all the body-less instance
methods listed in the interface. For example, the following code
15117
...
} // MyClass
says that the class being defined, MyClass, provides full definitions for all the instance methods
listed in the interface SomeInterface. So, for example, if a method somewhere has a method
parameter of type SomeInterface, then an instance of MyClass could be supplied as a corresponding method argument, as it satisfies the requirements of being of type SomeInterface.
19 Array
19.1 Array (page 286)
An array is a fixed size, ordered collection (list) of items of some particular type. The items
are stored next to each other in computer memory at run time. As an example, the following
is a representation of an array of 8 int values, which happen to be the first 8 prime numbers
(excluding 1).
11
13
17
19
Each box, or array element, contains a value, which can be changed if desired. In other
words, each element is a separate variable. At the same time, the array as a whole is a single
entity. This is rather similar to the idea of an object having instance variables, except that the
elements of an array must all be of the same type.
Indeed, arrays in Java are objects.
15118
At run time, this code yields a reference to the newly created array, which we typically would
want to store in a variable.
Thanks to the use of references, the size of an array does not need to be known at compile
time, because the compiler does not need to allocate memory for it. This means at run time
we can create an array which is the right size for the actual data being processed.
...
smallPrimes[0]=2; smallPrimes[1]=3; smallPrimes[2]=5;
smallPrimes[3]=7; smallPrimes[4]=11; smallPrimes[5]=13;
smallPrimes[6]=17; smallPrimes[7]=19;
and somehow we have placed the lengths of my fingers and thumbs into the ten elements of
myFingerLengths, then the following code would compute the total length of my fingers and
thumbs.
double myTotalFingerLength = 0;
for (int index = 0; index < 10; index++)
myTotalFingerLength += myFingerLengths[index];
So, arrays are a bit like ordinary objects with the array elements being instance variables,
except that the number of instance variables is chosen when the array is created, they are all
the same type, they are named by indices rather than names, and they are accessed using a
different syntax.
then my2DArray[0] is a reference to the first row, and so my2DArray[0][0] is the first element
in the first row. Similarly, my2DArray[4][3] is the last element in the last row.
In the above code fragment, the variable myArrayLength will have the value 25.
15120
The above code will output zero, whereas the following code will cause a run time error (in
fact a NullPointerException), because there is no array so we cannot ask for its length.
System.out.println(myNonArray.length);
The following diagram shows the above method parameter referring to an array, with the
array elements themselves referring to String objects.
15121
String[] args
0
"Quick Hackers"
String object
"15049"
String object
"Top Soft"
String object
"49959"
String object
"Middle Ware"
String object
"27750"
We can add another item into the array, or do nothing if it is full, as follows.
anArray[noOfItemsInArray] = aNewItem;
noOfItemsInArray++;
} // if
15122
SomeType[] biggerArray
= new SomeType[anArray.length * ARRAY_RESIZE_FACTOR];
for (int index = 0; index < noOfItemsInArray; index++)
biggerArray[index] = anArray[index];
anArray = biggerArray;
} // if
anArray[noOfItemsInArray] = aNewItem;
noOfItemsInArray++;
The new array does not need to be twice as big as the original, just at least one element bigger.
However, increasing the size by only one at a time would be slow due to the need for copying
the existing elements across.
int[][] myArray
null
17
999
99
256
108
99
10
97
367
23
12
The type of the variable is int[][], that is int array, array. The variable references an array
of 5 values, the first of which is a reference to an array of 5 numbers, the second a reference to
an array of 3 numbers, the third is a reference to an array of 4 numbers, the fourth is the null
reference and the final element is a reference to an array of 3 numbers. These arrays could be
created, ready for the numbers to be put in them, as follows.
15124
17
0
0
999
23
99
99
27
1
0
2
57
93
30
79
3
0
4
14
10
15
768
13
The above two-dimensional array could be created (without the numbers being assigned into it
yet) by the following code.
Two-dimensional arrays are so common, that Java provides a shorthand notation for defining
them. The shorthand for the above example is as follows.
The code new int[5][4] makes an array of length 5 get created at run time, and also 5 arrays
of length 4, which are capable of holding int values, with these latter 5 arrays being referenced
by the 5 elements in the first array.
15125
20 Exception
20.1 Exception (page 340)
A run time error is called an exception in Java. There is a standard class called java.lang.Exception
which is used to record and handle exceptions. When an exceptional situation happens, an instance of this class is created, containing information about the error, stored in its instance
variables. In particular, it includes a stack trace containing the source line number, method
name and class name at which the error occurred. This stack also contains the same information for the method that called the one that failed, and so on, right back up to the main method
(for an error occurring in the main thread).
15126
15127
15128