Bluej 1
Bluej 1
Ron McFadyen
Jeanette Bautista
September 3, 2019
©2019 Ron McFadyen, Jeanette Bautista
Department of Applied Computer Science
University of Winnipeg
515 Portage Avenue
Winnipeg, Manitoba, Canada
R3B 2E9
je.bautista@uwinnipeg.ca
r.mcfadyen@uwinnipeg.ca
2
To Callum
3
Contents
1. Introduction............................................................................................................................................ 9
1.1 Java, the beginning ..................................................................................................................... 9
1.2 The Java Compiler and the Java Virtual Machine ........................................................ 10
1.3 BlueJ ............................................................................................................................................... 11
1.4 A First Program ......................................................................................................................... 12
1.5 Using BlueJ to Run HelloWorld ............................................................................................ 13
2 Basics ....................................................................................................................................................... 17
2.1 Literals .......................................................................................................................................... 17
2.2 Variables....................................................................................................................................... 17
2.3 Primitive Data Types ............................................................................................................... 22
2.3.1 Numeric Data Types: byte, short, int, long ............................................................. 22
2.3.2 Integer Arithmetic .......................................................................................................... 22
2.3.3 Numeric Data Types: float, double ........................................................................... 26
2.3.4 Numeric Expressions..................................................................................................... 29
2.3.5 boolean Data Type .......................................................................................................... 36
2.3.6 char Data Type .................................................................................................................. 41
2.4 Conditional Operator ?: ........................................................................................................ 44
2.5 Operator Priorities ................................................................................................................... 45
2.6 The String Class .......................................................................................................................... 48
2.7 Implied declarations using var ........................................................................................... 58
2.8 Output............................................................................................................................................ 59
2.8.1 System.out.......................................................................................................................... 59
2.8.2 JOptionPane....................................................................................................................... 63
2.9 Input ............................................................................................................................................... 65
2.9.1 The Scanner Class ........................................................................................................... 65
2.9.2 The JOptionPane Class .................................................................................................. 68
3 Control Structures.............................................................................................................................. 71
3.1 Compound Statements ........................................................................................................... 71
3.2 if ....................................................................................................................................................... 72
4
3.3 while ............................................................................................................................................... 85
3.4 for .................................................................................................................................................... 93
3.5 switch ......................................................................................................................................... 107
3.6 do ...while ................................................................................................................................... 112
4 Introduction to Methods .............................................................................................................. 117
4.1 Void Methods........................................................................................................................... 118
4.2 Value-returning Methods ................................................................................................... 120
4.3 Parameters ............................................................................................................................... 122
4.4 Summary ................................................................................................................................... 126
5 Classes in the Java Class Libraries ............................................................................................ 131
5.1 Random...................................................................................................................................... 131
5.2 Character ................................................................................................................................... 135
5.3 Scanner ...................................................................................................................................... 143
5.4 Math ............................................................................................................................................ 150
5.5 Integer ........................................................................................................................................ 154
6 ArrayLists ........................................................................................................................................... 159
6.1 Examples ................................................................................................................................... 161
6.2 Sieve of Eratosthenes ........................................................................................................... 166
6.3 Parallel Lists ............................................................................................................................ 169
7 Designing Java Classes................................................................................................................... 173
7.1 Using Multiple Classes ......................................................................................................... 175
7.2 Fields........................................................................................................................................... 176
7.3 Methods ..................................................................................................................................... 180
7.4 Constructors ............................................................................................................................ 185
7.5 Visibility Specifications: Public, Private ....................................................................... 189
7.6 Constructors ............................................................................................................................ 190
7.7 Overloading .............................................................................................................................. 191
7.8 Associations ............................................................................................................................. 192
7.9 Reusing code ............................................................................................................................ 196
7.10 Parameter lists and arguments ........................................................................................ 198
7.10.1 Varargs: a variable number of arguments ......................................................... 201
5
7.10.2 Code listings: Student, Subject................................................................................ 203
6
Preface
This book is Part I of a two-part set that introduces the Java programming
language. The text assumes the student will be using the BlueJ development
environment and provides some introductory BlueJ material. Our experience
has been that BlueJ is easy to learn and provides a good programming
environment for the beginner programmer.
7
The examples in the text, and solutions to many exercises, are available on
the website for this text.
8
1 Introduction
This book is about programming in Java. We begin with short descriptions of Java and
BlueJ. We feel that BlueJ is one of the simplest development environments for the
beginning programmer to use. All examples in this text have been tested using BlueJ.
Sample solutions for odd-numbered exercises are available on the website for this text.
2015 - awarded the IEEE John von Neumann Medal for ”the Java programming
language, Java Virtual Machine, and other contributions to programming
languages and environments”.[3]
In 2010 Oracle acquired Sun Microsystems and took over the development of the
language. The language has gone through a number of updates, and at the time of writing
the current release is referred to as Java 12. All programs in this text have been tested
using BlueJ running with Java 11.
This text is about programming Java applications. The student may be interested in other
Java technologies such as Java Card, Java TV, applets, etc.; for these we refer you to
Oracle documentation
(https://www.oracle.com/technetwork/java/javase/tech/index.html).
9
10
A program that performs this transation is called a compiler, and we say that the source
code is compiled into bytecode. The compiler made available by Oracle is called javac.
Bytecode files always have a name that ends with ”.class”.
The bytecode is not directly executable on a computer - bytecode is not machine code,
but it is close to that. Bytecode is ”executed” by a special program call the Java Virtual
Machine, or JVM. Java programs are portable in the sense that you can write a program
and deploy it anywhere - as long as there is a JVM for that platform.
The process of developing, compiling, and running a Java program is shown below.
11
BlueJ
BlueJ is an integrated development environment that provides a programmer with a
framework that includes an editor, a compiler, and a runtime environment. It is our
experience that BlueJ is very suitable for the beginning Java programmer.
We expect that if you are reading this text then BlueJ is already installed on available
student workstations. If not please consult your technical services staff. If you need BlueJ
on your own computer then please visit http://www.bluej.org and follow their
download and installation instructions.
Below is a picture showing HelloWorld in a BlueJ project. Note the button available to
compile the source code. This program is discussed in the next section.
12
A First Program
Shown in Listing 1.1 is the traditional first program, HelloWorld, that appears in many
Java texts. When executed, this program does one simple thing: it displays the message
”Hello World”.
The purpose of the HelloWorld program is to display one line on the standard output
device (the Terminal Window in BlueJ). When you inspect this program one thing that is
immediately obvious is that there is a lot of overhead to do just one thing. Each line of
the program is explained below:
The program is actually a Java class and the lines making up the class are delimited by
the left brace { in line 2 and the right brace } in line 8.
Line 3 begins the definition of a method named main. In general, a method can take
arguments and the text String[] args() is the way those are indicated for a main
method - much more on this in later chapters.
The lines that comprise the main method begin with the left brace { in line 4 and end
with the right brace } in line 7.
Line 5 is an example of a Java assignment statement that, when executed, causes the value
Hello World to be stored in the memory locations reserved for the variable message.
13
Line 6 is an example of how a program creates output. When this line executes the
contents of message are transferred to the standard output device (BlueJ’s Terminal
Window) for the user to see.
In this section we discuss typical steps one can follow to run HelloWorld in the BlueJ
environment.
2. Unzip the sample programs storing them in a folder on your computer. Open the
folder and locate the file HelloWorld.java.
...a file named ReadMe.txt that will be discussed later on in the text.
4. Now, to get a copy of HelloWorld ...Click the HelloWorld.java file, hold the mouse
button down, drag the file to your new BlueJ project window, and then release the mouse
button:
14
This action copies the file and now you have HelloWorld in your project.
5. Double-click the image in the project representing HelloWorld ...the BlueJ editor
opens showing you the contents. You should see the 8 lines shown in Listing 1.1.
You should see the editor open as shown below:
6. The next step is to compile the program. There are two ways to do this ...use the
compile button on the editor window, or use the compile button on the project
window with HelloWorld selected. If you click the compile button on the editor
window the response will be that the code compiled with no errors:
15
7. Finally, to run the program you must close the editor by clicking the close button.
You are now back at the BlueJ project where you must right-click the HelloWorld
icon and select, from the options shown, to execute the main method:
8. As a result of the above, BlueJ is ready to run the main method and prompts you
for any argument values for main. Since there are none (arguments are discussed
much later in the text), click the OK button:
16
9. The program runs and you see the output in a window (named the Terminal
Window) that pops up:
Exercises
1. Run the Hello World program.
2. Modify the Hello World program so it displays your name instead of “Hello
World”. To do this you must use the BlueJ editor and alter line 5. Then you must
recompile the program and run the new version.
17
2 Basics
This chapter covers material that gives you the necessary information to run basic
programs that use constants and variables, perform calculations, obtain input from a
user, and generate output. The topics covered are literals, variables, primitive data types,
the String class, input, and output. Java is an object-oriented language and with the last
three topics you will begin to get an understanding of what object-oriented means.
Literals, variables, and the primitive data types are concepts you will find in most (if not
all) programming languages you encounter.
Literals
It is common for programs to include constants; in Java these are referred to as literals.
Examples include: 123, 123.45, ’a’, "Gosling", true. Most of the time a programmer codes
numeric literals and boolean literals in the same way we would normally write them
down (e.g. 123, 123.45, true, false). With practice you will get used to using single quotes
to specify a single character (e.g. ’a’), or double quotes to specify a text string (e.g.
"Gosling").
Variables
The variable is a fundamental concept in programming. In general terms we say a
variable is a named location in a computer’s memory, and the value stored in that
location is controlled during the execution of programs. A variable is a name associated
with a piece of computer memory - a piece of memory that holds a value that a program
can use and change as it executes.
The Java programming language requires us to declare the type of data to be primitive
types associated with a variable. Java makes a distinction between primitive data types
and other data types defined via classes. In the Java class libraries there are many pre-
defined classes, for example: String and System. The Java language contains eight
primitive data types: byte, short, int, long, float, double, char and boolean:
• byte, short, int, and long are used for cases where the data is to be treated as
whole numbers (numbers without a fractional component). For example, 33,
498, -100 are whole numbers. These data types differ with regards to the
magnitude of number they can represent.
18
• float and double are used for cases where the data is numeric and where one
expects values to have a fractional component such as: 101.5, 26.334, -55.5.
When written we show them with a decimal point. Again, these two types differ
with regards to size in terms of the number of significant digits and in the
magnitude of the number they can represent.
• boolean is used when the situation requires one to work with logical values of
true and false. In a Java program these values are written just as we do in
English: true, false.
A Java programmer declares a variable in a declaration statement, and then uses the
variable name later in a program to assign a value, to alter the current value, and to
reference the value currently stored. Two example programs follow; in Listing 2.1 the
program defines and uses a variable, and in Listing 2.2 the program alters the value
stored in a variable.
In line 11 the value 14 is assigned to i (that is, the value 14 is stored in the
memory location reserved for i),
9 /**
10 * This Java class declares
11 * an int variable named i,
12 * assigns the value 14 to i,
13 * and displays i.
14 */
15 public class Variable
16 {
17 public static void main(String[] args){
18 int i;
19
19 i = 14;
20 System.out.println(i);
21 }
Listing 2.2 starts off like Listing 2.1 but modifies the value of i to 30 in line 13 just
before it is displayed for the second time. This program changes the value associated
with the variable.
1 /**
2 * This Java class declares
3 * an int variable named i,
4 * assigns it a value and then
5 * changes its value.
6 */
7 public class VariableChanged
8 {
9 public static void main(String[] args){
10 int i;
11 i = 14;
12 System.out.println(i);
13 i = 30;
14 System.out.println(i);
15 }
16 }
Naming Variables
A convention used by many Java programmers is to choose names that are concise yet
meaningful. A name you choose should indicate the intent of its use. In situations where
the intent of use involves more than one word a common naming scheme is camel case.
For instance, suppose you need a variable to keep track of net pay. In order to have a
proper name a programmer could choose the name netPay for the variable. Two words
are involved: net and pay. the first word is in lower case and other word is catenated to
it, and only the first letter of the second word is capitalized.
Camel case is a style where words are catenated together forming a variable name - the
first word is all lower case, the second and subsequent words have only the first letter
capitalized.
20
Camel case is a good convention to follow when declaring variables. However, Java will
accept any variable name as long as the name starts with a letter and contains any
mixture of letters, digits, and the underscore character (’ ’). Some valid variable names
include: a123, net pay, gross pay.
Java variable names are case-sensitive. This means that variable names such as NetPay
and netPay are different variables.
Keywords
Java reserves the use of certain names referred to as keywords. Keywords are reserved
for special purposes and cannot be used as variable names. For example, int is reserved
for situations where one declares a variable to be of type int; you cannot declare a
variable with the name int.
In the sample programs shown so far we have seen a few of these reserved words: public,
class, void, static. In subsequent chapters we will see other keywords introduced such as
while, do, if, else.
21
Exercises
1. Java requires that all variables be declared. What type of message does the Java
compiler report if a variable is not declared before it is used?
abc = 14;
instead of
i = 14;
Compile the program. What is the response you get from the compiler?
Consider Listing 2.1 again. Change all references to the variable i to public, as shown
here:
int public;
public = 14;
System.out.println(public);
Compile the program. What is the response you get from the compiler?
3. Java variable names are case sensitive so two variables named Message and
message do not refer to the same thing. Modify line 6 in the HelloWorld to be:
System.out.println(Message);
Numeric data types are used for numer values where there is no fractional component -
all values are whole integers. The byte, short, int, and long types differ in the amount of
memory used (and therefore minimum and maximum values):
If the operands of an arithmetic operation are both integers, the result is an integer.
Consider division - there is no remainder ...13/5 evaluates to 2 and not 2.6.
Modulo gives the remainder when the first operand is divided by the second operand.
The result of 13%5 is 3.
23
Example: Division and Modulo
The following example program uses division and modulo to obtain the last two digits of
an integer. The output follows the listing.
If a numeric literal has no decimal point (such as 10025) then the data type used is int.
If a programmer wanted to use the long data type the value would have a suffix of L or l;
for example, 10025L.
L is recommended since the lowercase l appears too much like digit 1. We say int is the
default integer data type.
25
Exercises
4. We have seen some simple expressions in Java. Modify the program in Listing
2.2 to use a simple expression. Alter the statement
i = 30;
i = i*3;
5. Modify the program in Listing 2.3 so that each of the four digits are displayed
on separate lines.
99 / 10
99 / 10 * 10
99 % 10
99 - 99 % 10
99 - 99 / 10
99 10 * 10 + 99 % 10
26
These data types are used to represent values that have decimal places. For example, the
numbers 11.5, 12.25, -300.123, and 0.0 are written with decimal places. Even zero
written as 0.0 is a double.
The float and double types differ with respect to the number of significant digits they
store (approximately 7 for float and 16 for double) and the overall magnitude of a value
that can be represented. The table below shows the amount of memory used and the
maximum value per type:
Of course a programmer can perform calculations on doubles and floats. The operators
we will discuss at this time include +, -, *, and / as shown in the following table.
Listing 2.4 illustrates some simple double calculations in order to compute and display
fuel consumption as litres per 100 kilometres travelled.
Doubles as approximations
Not every number can be represented exactly as a double or float. You know that some
fractions cannot be written, using decimals, exactly or completely. Most people use the
decimal number system where we can write out the fraction 1/4 exactly as 0.25.
However, the fraction 1/3 is a repeating decimal. If we write it out as a decimal number
we either stop at some number of digits, or, we write it as 0.33333 ..., to indicate the
number has an infinite representation.
A similar case arises with computers - there are fractions that cannot be represented
exactly in a computer. With limited space we are often storing just an approximation.
One must be aware that round-off can occur when calculations are done with float and
double. Hence they are not appropriate for certain situations: for example if your
program needs to represent monetary values. A highly recommended book on Java is
Effective Java[4]. This is a great reference for the experienced programmer ...for
monetary calculations the BigDecimal class is recommended.
The following program demonstrates a calculation: one value subtracted from another.
If you performed the calculation yourself, you would say the answer is 0.05. However
this program prints a different answer. We have included this example to illustrate how
some values are just approximate values.
When a numeric literal (such as 100.25) appears in a program with a decimal point, the
data type used is double; we say double is the default data type for values with a decimal
point. If the programmer wanted to use a float value then the suffix f would be used, as
in 100.25f.
To a non-programmer literals such as 100.0 and 100 may seem the same, but a Java
programmer knows the first is represented internally as a double and the second is
represented as an int.
We say that double and int are the default numeric data types.
We focus on these numeric data types for the rest of this text.
29
Exercises
8. Modify the program in Listing 2.4 to calculate and display fuel consumption as
the number of kilometres travelled per litre of fuel.
9. Write a program that converts a value in centimetres to an equivalent value in
inches. Use the conversion: one inch equals 2.54 centimetres. Use variables of
type double.
10. Write a program that converts a value in dollars to an equivalent value in euros.
Use the conversion: one euro equals 1.5 dollars. Use variables of type double.
11. Modify Listing 2.5 to run some different calculations, such as:
System.out.println(100.5-100.00);
System.out.println(100.33-100.00);
Calculations are defined using Java expressions which comprise operators and operands:
Expressions numbered 3, 4 and 5 above are complex, and to fully understand how Java
evaluates these requires knowledge of operator priorities and associativity.
Operator Priorities
Java gives each operator a priority and then uses those priorities to control the order of
evaluation for an expression. Higher priority operators are executed before lower
priority operators. Sometimes a programmer may need to override these priorities and
would use a sub-expression for that purpose; a sub-expression is always evaluated
before the expression in which it is contained is evaluated. Consider the following table
of operator priorities:
Operator Priorities
Highest to lowest
* / %
+ -
Multiplication is given the same priority as division and modulo, and addition is given
the same priority as subtraction. However, the priority of multiplication, division, and
modulo is higher than that of addition and subtraction. The following table shows
expressions, the order of evaluation shown with equivalent sub-expressions, and the
final result.
31
The next two examples show situations where operator priorities must be overridden in
order to have correct calculations:
Suppose we must calculate an employee’s net pay. Suppose for the employee we have
their gross pay, deductions from gross, and their tax rate in variables named grossPay,
deductions, and taxRate respectively. Suppose net pay is calculated by subtracting
deductions from gross pay and then multiplying by the tax rate. If we code this as
grossPay - deductions * taxRate we will get the wrong result since * has
higher priority than -. We need use a sub-expression as:
the area would be calculated incorrectly due to division and multiplication having higher
priority than addition. To force the correct evaluation we can use a sub-expression and
override operator priorities: the formula must be written as:
(a + b)/ 2.0 * h
Sub-expressions are used to change the order of evaluation ...in this case we make a +
b a sub-expression, and hence evaluated before the division and multiplication.
Operator Associativity
When an expression involves more than one operator of the same priority it is necessary
to understand the order in which they are evaluated. If more than one multiplication or
division appears in an expression, they are evaluated from left to right; similarly for
addition and subtraction. In programming terms we say these operators are left
associative.
A programmer can code this as 9.0 / 5.0 * c + 32.0. This would be correct as the expression
is evaluated by Java as required: the division, 9.0 / 5.0, is performed, then the
multiplication, and then the addition. If division and multiplication were right-to-left
associative the result of the above would be incorrect.
Expressions could contain a mixture of types. Java permits conversions between integer
and floating-point types.
By widening we mean that the type being converted to contains all values of the other
type. For example, any value of the short type (a 2-byte integer) can be represented as
an int type (a 4-byte integer). In the following program (see line 12) the value of s, a 2-
byte integer, will be converted to an int value, a 4-byte integer.
33
Example 1
Consider the expression
(100 - 10)* 0.10
The sub-expression involves integers and the result is an integer producing a value of
90. Next in the evaluation will be the multiplication involving 90 and 0.10; note these
are different types: int and double. Java automatically converts the 90 to 90.0 before the
multiply is performed.
Example 2
(9/5)* 1 + 32.0
The sub-expression, 9/5, involves integers and the result is an integer yielding a value of
1. Next in the evaluation will be the multiplication involving 1 and 1, which yields the int
value of 1. Now we have 1 plus 32.0. For this to be performed the 1 is converted to 1.0
and the final result is 33.0. Note that this would be considered inaccurate (wrong) for the
conversion of 1 degree Celsius to Fahrenheit. To obtain a more accurate result 9.0/5.0
should be used instead of 9/5.
Narrowing conversions are cases where there could be a loss of precision narrowing
going from one type to another. For example converting from a double to an int is not
allowed unless the programmer directly indicates that casting is to be performed. We will
leave casting until a later chapter.
Unary Minus
There are several unary operators where the operator takes one operand. The unary
minus is one most people would be familiar with. A unary minus, -, can be placed
immediately in front of an expression to negate the value of the expression. For instance
the value of -(50-75) is 25. The unary minus precedes its operand as shown above. Its
priority is higher than multiplication, division, and modulo.
Exercises
12. Write a program to calculate an employee’s gross pay where variables
hoursWorked and rateOfPay hold the employees hours worked and rate of
pay respectively. Gross pay is calculated as hours worked times rate of pay. Test
your program with hoursWorked = 40 and rateOfPay = $7.50 per hour.
13. Write a program to calculate the provincial sales tax and the general sales tax
payable for an item where the variables pstPayable, gstPayable,
price represent the provincial sales tax payable, the general sales tax payable,
and an item’s price. Use the formulas:
pstPayable = price ∗ 0.05 gstPayable = price ∗ 0.08
14. Suppose a customer is charged an amount and the customer gives the clerk an
amount that is larger. An amount equal to the difference between the amount
given and the amount charged must be returned to the customer. Write a
program that calculates this amount to be returned to the customer. Use
35
variables amountCharged, amountGiven, amountReturned to represent the
different amounts. Test your program with amountCharged = $75.50 and
amountGiven = $100.00.
15. Write a program that uses the formula
The boolean type has two values: true and false. We will see that the boolean type can be
useful when we discuss control structures in the next chapter. There are three operators
defined for booleans: and, or and not represented in Java as &&, ||, and ! respectively.
&& and || are binary operators where the operator appears between the two operands;
Boolean operators
Three truth tables below show the results for Boolean operators for all possible values
of their operands.
boolean x, y, z;
x=false; y=true; z=true;
example result
1 y true
2 y && z true
3 x || y true
4 !x true
5 x && y || ! z false
6 ! x || y true
7 ! (x || y) false
A Boolean expression may have multiple operators. Consider example 5 from above,
x && y || ! z
Higher priority operators are evaluated before lower priority operators. So, for the
above expression
So now the expression effectively becomes: false || false which evaluates to false.
38
sub-expressions
In example 6:
! x || y
true || y
In example 7:
! (x || y)
the sub-expression (x || y) is evaluated first, and then ! is evaluated. Since x||y evaluates
to true, the result for the expression is false.
Some further points about the Boolean operators (not very important to us yet):
When && is being evaluated and if the first operand is false, then the result must
be false and so the second operand is not evaluated.
When || is being evaluated and if the first operand is true, then the result must
be true and so the second operand is not evaluated.
other operators
• There are other operators (&, |, and ^) that you may be interested in learning about
subsequent to this course. These, amongst other features, are discussed in Java in a
Nutshell [5].
39
Relational Operators
There are a number of operators defined for comparing one value to another. These are
summarized in the table below (assume x and y are of type int). These operations
evaluate to a boolean (true or false):
Relational operators
== equal to x == y
Make special note that == is the operator used to test for equality, and != is used to test
two operands to determine if they are not equal. Listing 2.7 illustrates the use of
relational operators. Later in the chapter on control structures we will use relational
operators in many examples.
6 int i1 = 111;
7 int i2 = 555;
8 // Display i1 and i2
9 // Display true or false according
10 // to whether they are equal or not
11 System.out.println("The int values");
12 System.out.println(i1);
13 System.out.println(i2);
14 System.out.println("Testing i1==i2");
15 System.out.println(i1==i2);
16 System.out.println("Testing i1<i2");
17 System.out.println(i1<i2);
18 System.out.println("Testing i1>i2");
19 System.out.println(i1>i2);
20 }
21 }
41
2.3.6 char Data Type
char is used when you need to handle characters individually. When you see a char value
in a program you see it enclosed in single quotes, as in:
Java organizes memory for char values so that each value is stored using two bytes of
memory. One byte of memory is eight bits. We can consider a bit as being either on or off,
or, 0 or 1. A byte of memory can be considered to be a sequence of eight 0’s and 1’s. Just
for interest, the bit sequences and corresponding integer value for a few characters is
listed below:
Recall the relational operators compare one value to another, and so these operators
produce a boolean value of true or false. These are shown again in the table below;
assume x and y are of type char.
42
Relational operators
Recall that == is the operator used to test for equality, and != is used to test two values
to determine if they are not equal. Listing 2.8 illustrates their use in a program. Later on
in the section on the Character class you will see useful techniques for analyzing
individual characters in a string.
Exercises
18. Write a program that will print the integer values for the characters ’!’,
’@’, ’#’, ’$’, ’%’, ’^’, ’&’, ’*’, ’(’, ’)’. Note that Java
allows a statement such as
int value = ’a’;
19. Since Java uses two bytes of memory there are 16 bits used to represent char
values. How many different char values can be represented?
44
Conditional Operator ?:
The conditional operator is sometimes called the ternary operator as it has three
operands. Note the placement of ? and : in its syntax:
where
The conditional operator yields a result that is either <true value> or <false value>.
Example 1
Suppose we want to assign the variable maxValue the maximum of two variables, x and
y. This is easily done with an assignment statement where the right hand side is coded
with the conditional operator, as in:
maxValue = (x>y) ? x : y ;
This form is often used by programmers for simple cases like the above. In a later
chapter we will see the if-else statement that can be used for exactly the above
, but it is much more verbose.
Example 2
Suppose you need to display the larger of two values x and y. To do this we can use the
above expression inside a display statement., as in:
Exercises
20. Write a program that obtains a String (a password) from the user and displays
the message “too short” if the length of the password is less than 8. Note
that if passwd is of type String then passwd.length() is the number of
characters (the length) of the value stored in passwd.
45
Operator Priorities
We have seen arithmetic, relational, and boolean operators so far. The table below shows
these operators and several others: method invocation, postincrement, post-decrement,
and assignment.
Priorities of Operators
priority Java operator meaning
16 name of a method(...) method invocation
++ post-increment
– post-decrement
15 - unary minus
! boolean not
14 new object creation
13 / division
* multiplication
% modulo
12 + addition
- minus
+ string catenation
10 < less than
<= less than or equal to
> greater than
>= greater than or equal to
9 == equals
!= not equals
5 && boolean and
4 || boolean or
3 ?: conditional operator
2 = assignment
+= assignment with operation
Previously we stated some operators had the same priority as others, and that some had
a lower/higher priority that some others. In the table above you see the actual operator
46
priorities. For example, both unary minus and boolean not have the same priority (15)
which is much higher than most others. Assignment has the lowest priority (2).
There are several operators we do not discuss in this text. There are operators for every
level from 1 to 16; we have not included any of the operators at levels 1, 6, 7, or 8. You
could consult a reference such as Java in a Nutshell [5] at some future date.
Complex Expressions
Expressions can be very complex ...each operand can itself be an expression that
evaluates to true or false. Consider the following complex expression where a, b, c,
d, x, z are numeric types:
and each will evaluate to either true or false. If you look at the priorities of operators you
will see the additions will be done first, followed by the relational operators, followed by
&&, and finally the assignment to the variable answer.
Some programmers prefer to include extra spaces and parentheses in expressions like
the above ...in order to make the expression more readable, as in:
In this example the parentheses do not change the order of operations; rather, they may
make it easier for someone to read.
What is often referred to as the assignment statement is really a Java expression followed
by a semicolon. The assignment operator, having a priority of 2, is usually the last
operator to be evaluated. The assignment operator is right associative. That is, when
several assignment operators appear in an expression they are evaluated/performed
from right to left. So, if you have the statement:
int q = (j=1)+1;
47
then j will have the value 1 and q will have the value 2.
declares fullName to be of type String. fullName is a variable and the Java compiler
allocates memory for fullName. The memory location for fullName will contain a
reference (an address) to the storage location where the text string ”Joe Smith” is
actually stored. Memory for primitive types is handled differently. The memory location
associated with a primitive type contains the value (not an address) of the variable. For
example, an int variable will have a memory location reserved for it where the value of
the variable is stored.
There is a subtle difference that may be hard to appreciate at this time: a variable (of
type String) holds a reference to the value instead of holding the actual value. The
diagram below attempts to show the difference.
Object References
49
50
Since text strings are objects of type String another way to declare fullName and assign
it a value is to use the new operator:
In general, the new operator is used to instantiate (to create) an object. new operator
Because text strings are so common Java provides the short cut for allocating a string,
such as:
The only way to work with objects is through the methods that are defined in the class
from which the object is instantiated. The String class provides many methods for
working with text strings such as:
At some time you should view the official documentation for the String class. Perhaps
you will do this when you are developing a program and you want to look up the String
methods. If you are using BlueJ it is very easy to see the documentation for a class. As
Figure 2.4 illustrates, you just need to click on Help and then click on Java Class Libraries.
Choosing this results in an internet browser opening to a page where, on the left pane,
you can find and click on the entry for String (or some other class) to view
documentation which includes information about methods.
Several example programs follow that demonstrate how to use the various methods of
the String class. To use a String method it is necessary that you reference the object
and the method. For example, to obtain the length of s use the expression s.length().
Note the variable name is followed by a period which is followed by the method name
and any arguments enclosed in parentheses. In object-oriented terminology we are
asking the object s to execute its length() method.
length which returns, to the point where it is called, an integer value that is the length of
the string. The following program shows the method being used; see line 9 in particular:
When this line executes the method is invoked and returns a value to where it was
invoked. The value returned is assigned to passwordLength. Note the name of the method
is followed by parentheses even though no argument is passed ...this is necessary so the
Java compiler knows that the code specifies a method name.
In many applications where strings are being processed a specific character is expected
in a specific position. For instance, a social insurance number can be coded as 3 digits, a
hyphen, 3 digits, a hyphen followed by 3 more digits. The following program obtains the
character at position 3. The method charAt(...) returns the character at a specific position
to the point where the method is invoked. The method charAt(...) must always have an
argument value (the position) passed to it. For Java, positions within a string begin at 0
and so the first hyphen should be at position 3. Note in the program, at line 9, shown
here:
how the method is invoked (a period separates the name of the string, sin, from the name
of the method) and how the value 3 is passed to the method (in parentheses as an
argument value).
To determine if one object is equal to another object you must use a method which, by
convention, is named equals. The String class has a method equals and another method
named equalsIgnoreCase. Both of these methods require an argument to be passed. If we
want to compare two strings, say s1 and s2, to see if they are equal we can use either of
these two expressions: s1.equals(s2) s2.equals(s1)
Both must return the same boolean value. The following program initializes two strings
and then displays the value when they are compared for equality. Note line 15, repeated
here:
s1.equals(s2)
We say, in object-oriented terms, that we are asking the object s1 to execute its equals()
method with the argument s2. When line 15 executes the method is invoked, a value is
returned to this point in the statement, and that result is assigned to the boolean variable
equalsResult.
Catenation operator +
We have seen the + operator before, but the operands were always numeric. The +
operator can also be used to add (i.e. catenate) strings. It is used frequently in statements
that generate output. If at least one operand is a string then a result is formed by joining
two strings. Joining two strings is called catenation.
When one operand is not a string then the equivalent string representing that non-
string’s value is generated, and then the catenation of two strings is carried out forming
a new string as a result. For instance if you want to display a message "The value of
x is " followed by the value of x you just code:
However, suppose you wanted to display a string and show the sum of two numbers.
Consider:
The total is 21
The reason this happens is that the expression is evaluated from left to right. The first +
is adding a string and a number producing the string "The total is 10". Hence the
second + is adding a string and a number producing the string "The total is
1011".
57
Exercises
With the above statements the variables sum, count and name have been initialized, and
their types (determined by their initialized values) are double, int, and String
respectively.
Consider the listing below which is a rewrite of Listing 2.11 but all declarations use
var.
Listing 2.12: Using var to declare/initialize variables
1 public class UsingVar
2 {
3 public static void main(String[] args)
4 {
5 // variable password is of type String
6 // variable passwordLength is of type int
7 var s1 = "John A. Smith";
8 var s2 = "John A Smith";
9 // Display s1 and s2
10 // Display true or false according
11 // to whether they are equal or not
12 System.out.println("The strings");
13 System.out.println(s1);
14 System.out.println(s2);
15 var equalsResult = s1.equals(s2);
16 System.out.println(equalsResult);
17 }
18 }
Java is a strongly typed language. When the compiler sees a statement such as
it determines s1 is of type String and so we could not follow that with a statement
such as
s1 = 100;
Output
We discuss two different ways to generate output from a program: using System.out
and JOptionPane. We discuss the use of System.out in the next two sections; in the
second of these we discuss how you can redirect the output which normally appears in
the Terminal Window to a file.
In the third section we discuss the JOptionPane class and how that can be used to
present information and data in dialog boxes.
2.8.1 System.out
A simple way to generate output for the user is to use the println(...) and
print(...) methods that belong to the pre-defined Java class named System and an
object within System named out. The output generated is said to go to the standard
output device. When you use this type of output with BlueJ you will see a window pop
up named ”Terminal Window” that contains the output produced by the program.
The following program listing illustrates ways of producing output. The println(...)
and print(...) methods take one argument which is a text string. Often that text
string is composed of multiple catenations. Notice the last println(...) introduces
special characters for new line (\n) and tab (\t). The special characters are not
displayed, they are used to control the appearance of the output.
60
The println(...) method causes the display to advance to a new line and then
displays output. The print(...) method differs from println(...) in that it does
not automatically advance to a new line when it displays output; instead, output begins
at the point where the previous print(...) or println(...) left off. If we change
all the println(...) to print(...) expressions for the previous example the
output we get is:
Exercises
23. Write a program to calculate the total of the provincial sales tax, the general
sales tax, and the price of an item. Use the variables totalPayable, pstPayable,
gstPayable, and price to represent the total payable, the provincial sales tax
payable, the general sales tax payable, and the item’s price. Use the formulas:
pstPayable = price ∗ 0.05
gstPayable = price ∗ 0.08
totalPayable = price + pstPayable + gstPayable
62
Test your program with price = $50.00. Your program must display price, pstPayable,
gstPayable, and totalPayable.
Similar to lines 28-31 in Listing 2.12 create output that is nicely aligned with values
on separate lines.
63
2.8.2 JOptionPane
When lines 9 and 10 execute a pop-up window becomes visible and the program
waits for the user to press the OK button:
64
Exercises
24. Write a program that prompts the user for their first name, last name, and
middle name. The program then displays the names in order of first name,
middle name, last name.
Input
We examine two ways a programmer can arrange to get input from the user by using
pre-defined Java classes: the Scanner class and the JOptionPane class.
A Scanner object can be used with the standard input stream which is named System.in.
The typical statement used is:
System is a pre-defined Java class that has an object named in. Once a variable like
keyboard is defined the programmer can use methods defined for a scanner object to get
values (Java refers to these as tokens) the user has typed on the keyboard. Some of the
most useful methods are listed below.
The program below shows one how to use next(), nextDouble(), and nextInt()
to obtain a user’s name, hours worked and rate of pay. Note that line 1 is an import
statement that directs the compiler to the location where it find details of the Scanner
class. The program uses pairs of statements; for example consider lines 12 and 13
repeated here:
65
66
Exercises
25. Write a program that prompts the user for their birthday as the day (as an
integer), followed by the month (as text), followed by the year (as an integer)
with at least one space between the values. Use the Scanner methods next()
and nextInt() to get these values. Then the program displays the birthday in
the format month day, year. For example, if the user entered
1 January 1990
To provide a user with a more interactive experience the programmer can use
JOptionPane to prompt the user and to obtain text input from the user. One of the
methods defined in JOptionPane is showInputDialog(...). When this method executes the
user is prompted to enter text. The text the user enters becomes the value of the method.
Typically showInputDialog(...) is on the right-hand-side of an assignment statement; for
example:
When the above line executes the user sees the pop-up window:
The user then uses the keyboard to enter something in the white box in the pop-up, and
then clicks the OK button. The text the user entered is the value returned by the method.
The following program uses two pop-ups to obtain values from the user; comments
follow the listing.
• Line 5 is required since we need to tell the Java compiler where it can find the
JOptionPane class.
The user enters a value in the box and presses OK. Then control returns to the
program and the value entered is assigned to firstName.
A similar dialog box is displayed when line 10 executes.
• In line 13 the values obtained from the dialog boxes is displayed in BlueJ’s
terminal window.
Exercises
26. Write a program that uses a dialogue box to prompt the user for a temperature
in Celsius. Then the program uses a dialogue box to display the equivalent
temperature in Fahrenheit.
27. Write a program that uses a dialogue box to prompt the user for a temperature
in Fahrenheit. Then the program uses a dialogue box to display the equivalent
temperature in Celsius.
70
3 Control Structures
Programmers need 3 basic control structures when coding programs. These three things
are: sequences, decisions, and loops. A sequence structure is one that comprises
instructions that are to be executed sequentially one after the other. A decision structure
allows for exactly one of a set of sequences to be executed. A loop structure comprises a
sequence that is to be executed iteratively. Java has one sequence structure, two (some
may say more) different decision structures, and several ways of coding loops.
Compound Statements
Java statements delimited by curly braces form a compound statement. The opening
brace, ”{”, appears first followed by Java statements and then the closing brace, ”}”
follows. Any time you include a ”{” you must have a matching ”}”. Pairs like these must
be used properly - a pair cannot overlap with another pair, but as we will see one
compound statement can contain another compound statement (see sections on nesting
statements). An example is the following compound statement where the values of x and
y are interchanged:
{
temp = x;
x = y;
y = temp;
}
71
72
if
The structure of an if statement is shown below. The else and statement-2 are
optional; we say the if statement has an optional else clause. Statement-1 is
sometimes referred to as the then clause.
When the JVM executes an if statement, the JVM will first evaluate the logical
expression. If the expression is true then statement-1 is executed; if the expression is
false then statement-2 is executed. The if statement conditionally executes either
statement-1 or statement-2, and never both. The JVM process can be visualized as:
Logical Expressions
A logical expression is an expression that evaluates to a boolean value, i.e. true or false.
Java has several operators which evaluate to true and false including the relational and
equality operators. Recall the relational operators are <, <=, >=, and >:
Relational operators
Recall the logical operators and, or, and not where operands are boolean values and the
result is a boolean:
Boolean operators
Operator In Java Meaning
AND && Evaluates to true if and only if both operands are
true
Evaluates to false otherwise
OR || Evaluates to true if any operand is true
Evaluates to false otherwise
NOT ! Negates the operand
74
Example 1
Suppose one needs to display one of two possible messages. To do this we can use an if
with a then clause and an else clause. Consider the following program that displays one
of two messages depending on the value of the expression number > 0. In lines 9 and 10
the user is prompted for a number; in line 14 the if determines to print "positive"
or "not positive". Note that compound statements are used even though it was not
necessary. The output of a run where the user supplied the value 123 follows.
19 }
20 }
21 }
76
Exercises
1. Write a program that obtains a number from the user and displays whether the
number is an even number or an odd number. Note the expression number % 2
is equal to 0 if number is even and 1 if number is odd. Use an if-else.
2. Write a program that obtains two numbers from the user and displays the larger
of the two numbers. Use if-else.
Nesting statements
The syntax of the if statement provides for the conditional execution of any Java
statement, including other if statements, whiles, etc.
Example 2
Consider the program in Listing 3.2 where the user is prompted to supply two things:
the nature of the transaction (cash vs debit card) and the amount of the transaction. In
the section on doubles we discussed the use of an integer data type for monetary
transactions, and so the amount of a transaction is in pennies. In line 12 int variables are
defined to hold the amount. In line 14 the user is prompted for the type and cost of a
purchase.
The structure of the code involves the use of nested if statements. The outer if (lines 19
to 26) determines if payment is by cash or debit card. The then clause (lines 20-24)
handles a cash payment and the else clause (lines 25-26) handles a debit card payment.
For the case of a cash payment there is an inner if (lines 20 to 23) nested inside the then
clause that rounds the cost up or down to the nearest nickel. The else clause of the outer
adds the additional charge for using a debit card.
Following the listing is sample output showing the result for a cash transaction for
$121.21.
78
Example 3
letter numeric
grade grade
A 4
B 3
C 2
D 1
F 0
If a person is given a letter grade, its a simple matter for that person to find the grade in
the letter grade column and look across to determine the numeric grade. However, it
may not be obvious how to do this in a Java program. We will consider 3 different ways
this might be coded, the last of which we would say is the preferred approach.
A first approach is to code an if statement for each line of the table where the logical
expression relates to the letter grade value in the line. For instance the statement
will assign numericGrade the value 4.0 when the letter grade is "A". A program needs
similar statements for the other letter grades. For example at most one of the following
logical expressions will evaluate to true:
If you examine the program in Listing 3.3 you will see the variable numericGrade
initialized to 0.0 and so there are just 4 if statements to catch "A", "B", "C" and
"D"
80
When this first version executes every logical expression is evaluated. This can be
avoided to some degree if we use nested ifs - we can avoid some unnecessary
evaluations.
Consider the program in Listing 3.4. When you review this program note the nesting
of the ifs - each else clause contains an if. Only a minimum number of logical
expressions are evaluated. For instance if the letter grade is ”B” only two logical
expressions are evaluated.
81
The indentation you see in the above program is the standard way to show one
control structure embedded in another control structure.
However, when there are nested ifs and when the logical expressions differ only in
the value being tested: ”A”, ”B”, ..., a Java programmer can change the indentation.
Each of the cases being tested for are essentially the same and to stress that, a
82
programmer would alter the indentation to that shown below in Listing 3.5. Then,
the nested ifs are be referred to as an if-else-if structure.
Later on in the section on the switch statement we will see yet another way to
determine the pertinent line of the grade table.
83
84
Exercises
4. Consider how a numeric grade could be translated into a letter grade, as defined
in this table:
range grade
80-100 A
70-79 B
60-69 C
50-59 D
0-49 F
Given a mark, it is a simple matter to figure out which range it falls into and
determine the corresponding grade. Write a program which obtains a numeric value
and translates that into a letter grade. Consider using statements of the form: if (
mark > ... )
5. Modify your program for the above question so that it validates the mark
obtained from the user to ensure the value is in the range [0,100].
6. Write a program that obtains 10 numbers from the user and then displays the
largest of these numbers. Control the input using a while and nest an if inside
the while.
85
while
The JVM executes the statements in a program sequentially, one statement after another.
However, the while statement can change this. A while statement contains a statement to
be executed repeatedly as long as some logical expression is true. The statement
executed repeatedly is often a compound statement. The general syntax is
The order of execution of Java statements can be visualized using a flow diagram:
Example 1
The following program prints numbers from 0 to 9. It does so by executing a compound
statement repeatedly. The variable count is initialized in line 8 to the value 0 and as the
while loop executes count takes on the values 1, 2, 3, etc. A detailed explanation of the
program follows the program listing. As you examine the code note the use of
indentation - for readability purposes it is common practice to indent the lines
comprising a while loop.
The JVM starts sequential execution with the statement in line 8 - the variable
count is initialized to 0.
The JVM then moves on to Line 9 which results in the printing of a heading for
the output.
Observe that lines 11 and 12 are part of a compound statement. This compound
statement is executed for count equal to 0, 1, 2, and so on, up to count equal to
9; when count has the value 9 the compound statement is executed and count is
assigned the value 10 in line 12. That’s the last time the compound statement is
executed since the logical expression evaluates to false - the JVM will move on to
the statement following the while statement (line 14) where normal sequential
execution resumes.
Example 2
Consider another program which displays the digits of a positive number provided by
the user. The program includes a scanner object in line 7 that is used to get input from
the user via the keyboard. Lines 14 to 19 form a while loop where
Line 15: the rightmost digit is obtained using the expression number % 10
Line 16: the digit is displayed
Line 17: the value of number is reduced by a factor of 10 using the expression
number / 10
Line 18: the number is displayed
Eventually the value of number will be reduced to 0 and the loop terminates.
13 System.out.println("\tdigit\tnumber");
14 while (number > 0){
15 int digit = number % 10;
16 System.out.print("\t"+digit);
17 number = number / 10;
18 System.out.println("\t"+number);
19 }
20 System.out.println("end of list");
21 }
22 }
An example of output follows where the user entered the value 3476:
Nesting statements
The statement executed repeatedly can be any Java statement including another while
(or any other statement discussed in this chapter).
Example 3
The program in Listing 3.8 displays the product i*j for i and j where both i and j take
on values 1 through 4. The outer while (lines 15-23) executes 4 times, the first time
with i as 1 and the next time with i as 2, then 3, and then 4. The inner while (lines 18-
21) is executed entirely for each value of i; that is, for each value of i, the variable j takes
on the value 1, then 2, then 3, then 4. Note the indentation in the program: each line
within the outer while is indented the same amount, and each line within the inner
while is indented a further amount.
1 /**
2 * Program with one while inside another while.
3 * The program prints i, j, and i*j
4 * where i varies from 1 to 4 and
5 * where j varies from 1 to 4
6 */
7 public class NestedWhiles
8 {
9 public static void main(String[] args)
10 {
11 int i, j;
12 System.out.println("\ti\tj\ti*j");
13 // i takes on values 1,2,3,4
14 i = 1;
15 while (i < 5){
16 j = 1;
17 // j takes on values 1,2,3,4
18 while (j < 5){
19 System.out.println("\t"+i+"\t"+j+"\t"+(i*j));
20 j = j + 1;
21 }
22 i = i + 1;
23 }
24 System.out.println("program ended");
25 }
26 }
90
Exercises
7. What happens when a user enters the value 0 when DisplayDigits is executed?
9. What happens when a user enters something that is not an integer when
DisplayDigits is executed?
10. Write a program that will sum the digits of a number. For example if the number
is 124, then the sum of its digits is 7 = 1+2+4.
11. Write a program that obtains integers from the user and displays their total. The
program keeps getting integers until the user enters a value less than zero or greater
than 100.
91
12. Write a program that will sum the integers from -100 to 100. Note the answer
you expect is a sum equal to 0.
13. Write a program that converts from Celsius to Fahrenheit for Celsius values
starting at -40 and going up +40 in increments of 1.
14. Write a program that converts from Fahrenheit to Celsius for Fahrenheit values
starting at -40 and going up +40 in increments of 1.
15. Write a program to convert from Euro Dollars to US Dollars for Euros ranging
from 100 to 1,000 in steps of 100. Prompt the user for the exchange rate for
converting Euros to US dollars. At the time of writing the exchange rate was 1.12;
that is, 1 Euro was worth 1.12 US dollars.
17. How many times is the print statement in Listing 3.3 (line 19) executed?
18. Modify the program in Listing 3.3 so that i and j vary from 1 to 10.
Autoincrement
Because statements that increment a variable’s value, such as
i = i + 1;
are so common, Java has a special unary operator ++ for this. The statement
i++;
has the same effect as the above assignment statement. ++ is a unary operator (takes one
operand). The operand can be before or after the ++. The difference relates to when the
increment occurs which is only relevant in more complex expressions.
Java has a similar operator, - -, which has the effect of decrementing the value of a
variable, and so the following two statements are equivalent:
92
count = count - 1;
count--;
Exercises
19. Modify the program in Listing 3.3 to use the ++ operator.
20. Use nested whiles to print a 4×4 times-table. The times-table should appear as
follows
1 2 3 4
1 1 2 3 4
2 2 4 6 8
3 3 6 9 12
4 4 8 12 16
93
for
The for statement is commonly used where there is a need for a statement to be
executed a specific number of times. This type of looping construct is sometimes called
a counted loop. The syntax of the for statement we consider here is
An initialization section
A logical expression (just as the while has)
An increment section
The for is heavily used in Java programming. We will use several examples to show its
application.
Example 1
Below we use a for to manage a loop that displays the numbers from 0 to 9. You should
compare this to Numbers0To9 in Section 3.2.
2. The second component is the logical expression - the loop executes as long as
this evaluates to true
Notice how the lines that comprise the for statement are indented to enhance
readability. This program displays the values 0, 1, ...9 and so it should be evident that
count takes on values 0, 1, ...9, and that the for executes 9 times.
The for statement is the preferred programming idiom for a counted loop.
95
Example 2
A common situation where a counted loop arises in the processing of strings. A string of
text comprises individual characters. The String method length() returns the length of a
string, and the charAt(...) is used to access individual characters. The argument provided
to charAt(...) is the index of a character within the string - the index of the first character
is 0, and the index of the last character is length()-1.
Consider the following program that displays the characters comprising a string one-by-
one. To do this, the program has a for loop (lines 14-17) that executes once for each
character in the string.
Nested statements
The for statement contains a statement to be repeated. This statement can be any Java
statement. Consider the following example where an if statement appears inside a for
statement.
Example 3
This program examines a line of text and counts the number of times ’a’ appears. The
program uses the String method length() to obtain the length of a text string and the
method charAt(...) to obtain an individual character within a text string. The program has
a for loop (lines 17-20) that executes once for each character in the text string; the for
contains an if where the current character is compared to ’a’.
Example 4
The program in Listing 3.12 below displays the product i*j for i and j where both i
and j take on values 1 through 4. The output produced is the same as Example 3 in the
section on the while statement.
The outer for (lines 10-13) executes 4 times, the first time with i as 1 and the next time
with i as 2, then 3, and then 4. The inner for (lines 11-12) is executed entirely for each
value of i; that is, for each value of i, the variable j takes on the value 1, then 2, then 3,
then 4.
Note the indentation in the program: each line within the outer for is indented the same
amount, and each line within the inner for is indented a further amount.
Example 5
In this example we create a 5 × 5 times table. This table comprises rows and columns
where the entry at the intersection the ith row and jth column is the product of i and j,
i∗ j:
1 2 3 4 5
1 1 2 3 4 5
2 2 4 6 8 10
3 3 6 9 12 15
4 4 8 12 16 20
5 5 10 15 20 25
We develop this example in two steps. In the first step we simply produce the values that
will appear as entries in the times table, and in the second step we will see it properly
formatted with column and row headings.
This version produces all the values for the first row, then for the second row, etc. This
will require an outer for controlling the row number and an inner for controlling the
column number:
In the above the outer for uses the variable i to ensure the loop controlling rows executes
5 times, and the inner for uses the variable j to ensure this loop executes 5 times, once
for each column. As the inner loop is executed completely for each value of i, the print
statement in the inner loop executes a total of 5×5 = 25 times. Now, consider the
following program where nested for s are used to produce values for the times table.
101
The completed program and its output are shown next. To reasonably format the times
table we have added a title for the output (line 10), column headings (lines 12-14). Then,
for each row of the table, a row heading is printed (line 19). Note the mixed use of the
print() and println() methods.
Exercises
21. Modify the program in Example 1 to display the value of count in line 11 outside
the scope of the for. Does your program compile? What message do you get from
the compiler?
22. Consider Example 1 again. The variable count is defined in the for statement and
so the scope of count is the for statement. Modify the example properly in order
to display the value of count in the print statement (line 11). To do this you must
declare count before the for statement, as in:
int count; for (count=0; count < 10; count++)
...
23. Write a program that prompts the user for 10 values, and then displays the sum,
the average, the minimum, and the maximum of those 10 values.
24. Write a program that converts from Celsius to Fahrenheit for Celsius values
starting at -40 and going up +40 in increments of 1.
25. Write a program that converts from Fahrenheit to Celsius for Fahrenheit values
starting at -40 and going up +100 in increments of 1.
26. Write a program to convert from Euro Dollars to US Dollars for Euros ranging
from 100 to 1,000 in steps of 100. Prompt the user for the exchange rate for
converting Euros to US dollars. At the time of writing the exchange rate was
1.12; that is, 1 Euro was worth 1.12 US dollars.
27. Write a program that will sum the digits of a number. For example if the number
is 124, then the sum of its digits is 7 = 1+2+4
28. Write a program that prompts the user for an identification number (e.g.
student number, credit card number, etc.). The program must then display each
digit of the number.
105
n n!
1 1
2 2
3 6
4 24
…
32. Modify the Times Table example so that it produces an n × n times table. Prompt
the user for the value of n.
106
33. Write a program that reads an integer value and then displays that number of
asterisks. For instance, if the value read is 11 then the output is:
***********
34. Write a program that reads an integer value representing the number of
students majoring in Mathematics and then another value representing the
number of students majoring in Statistics. The program then displays two lines
of asterisks to illustrate the number of students majoring in those subject areas.
For example if the values were 11 and 15 the output would be:
Mathematics ***********
Statistics ***************
35. Modify the previous program so that it reads 5 pairs of values, where each pair
comprises a major (a text string) and the number of students in that major (an
integer). For example if the input was
Mathematics 14
Statistics 15
English 25
French 15
Geology 10
Mathematics **************
Statistics ***************
English *************************
French ***************
Geology **********
107
switch
The switch statement is a decision structure where one choice, of possibly many,
different choices are made. The general structure of the switch statement is
switch ( expression ){
case value1 : statement list1
case value2 :statement list2
case value3 :statement list3
...
default: default statement list
}
The switch statement contains a number of case groups where each group contains a
list of statements. The switch statement has an expression which is used to determine
where execution continues: If the value of the expression matches a value for a case
108
group, then execution continues with the case group’s statement list. If the expression
does not match any of the specified values then the default statement list is executed, if
one exists.
Each statement list has a well-defined starting point. The statements of a statement list
are executed one-by-one until the JVM encounters a break statement. When a break is
executed, the execution of the switch terminates and the statement following the
switch is executed next (normal sequential execution of statements resumes). If a
statement list does not have a break statement then the the next statement list will
execute, and so on until either a break is encountered or the end of the switch is reached.
The default case group is optional: If the switch expression’s value does not match a
case value and if there is no default case group then the switch statement terminates -
and the statement following the switch is executed next.
Normal usage of the switch is that each case group has a statement list and the last
statement of the group is a break. However, there are times when it is useful for a
statement group to be empty, and there are times when it is useful for a statement group
to not have a break statement.
Note that when all statement lists end with a break statement it is possible to replace a
switch statement with nested if statements where the logical expressions are of the
form expression.equals(value) for String expressions, and expression == value for other
types.
The expression and matching values can only be of certain data types that include: char,
byte, short, int, and the String type. Other included types are enumeration types and
the wrapper classes: Character, Byte, Short, Integer.
109
Example 1
letter grade
grade point
A 4
B 3
C 2
D 1
F 0
In this program a letter grade is obtained from the user. When the switch executes the
expression grade is evaluated and compared to each case value. If the value of grade
matches a value in some case, then the statement list for that case is executed. If the value
of grade is not an ”A”, ”B”, ”C” or ”D” the program assumes it must be ”F” and so the
default case is executed and 0.0 is assigned to nGrade.
20 break;
21 case "D": nGrade = 1.0;
22 break;
23 default: nGrade = 0.0;
24 }
25 System.out.println(grade+" --> "+nGrade);
26 }
27 }
If this program did not have any break statements then every grade would be assigned
the same numeric value: 0.0. Consider this code:
grade = kb.next();
switch (grade) {
case "A": nGrade = 4.0;
case "B": nGrade = 3.0;
case "C": nGrade = 2.0;
case "D": nGrade = 1.0;
default: nGrade = 0.0;
}
System.out.println(grade+" --> "+nGrade);
Now suppose grade has the value "A" then every assignment statement executes and
the last one executed is nGrade = 0.0 so the numeric grade assigned is 0.0.
111
Exercises
36. Write a program that prompts the user for a date in the yyyy mm dd format and
then prints the date in the form month name dd, yyyy. For example, if the user
provides 2000 01 01 then the program displays January 1, 2000.
37. Write a program where the user provides the name of a month and the program
displays the number of days in that month. We will ignore the fact that February
sometimes has 29 days (in a leap year). In a sense Java lets you combine cases
by allowing empty statement lists. For example, April, June, September, and
November each have 30 days and so you can write code such as:
case "April":
case "June":
case "September":
case "November": numDays = 30;
break;
If the switch expression evaluates to any of
38. Suppose we need a program that accepts a month followed by a day and then
reports the number of days left in the year. Again, we shall ignore the concept
of leap year. For example, suppose the user entered: October 30
As October has 31 days, November has 30 days, and December has 31 days, the
number of days left is (31 − 30) + 30 + 31 = 62.
Incorporate the following type of switch where each statement group simply
increments a variable and where there are no break statements (so statement
lists are executed from the selected case until the end of the switch). Note the
use of the combined assignment operator +=.
int numberOfDays = 0;
switch (month) {
case "January": numberOfDays += 31;
case "February": numberOfDays += 28;
case "March": numberOfDays += 31;
...
112
do ...while
The do ...while statement is useful when it is known the loop body must execute at
least once. The syntax of the do ...while statement is
When one compares this control structure to other Java control structures (compound,
if, for, and switch statements) there is one difference that stands out: the semi-colon
at the end. This semi-colon is necessary - if you remove it the compiler will not recognize
your do ...while and the program will not be executable.
Example 1
Let us consider a simple program in Listing 3.16 below that displays the numbers from
0 to 9 using a do...while. Lines 11 and 12 form the compound statement that is
executed repeatedly. The process of executing the do ...while is straightforward:
Example 2
Consider a program someone can use to develop their addition skills (Listing 3.17
below). The program should behave as follows:
113
114
As well as including a do ...while this program makes use of three Java classes:
Random (Chapter 5.1), Scanner (Chapter 5.3), and String (Section 2.6). Consider these
points:
1. (line 14) The variable generator references an instance created from the Random
class. The Random class has many methods that can be used to generate random
values; in lines 20 and 21 there is the expression generator.nextInt(10)+1 to
obtain random values between 1 and 10.
2. The variable kb defined in line 13 references an instance of the Scanner class and
is used to manage input from the standard input device, the keyboard.
3. The String variable response defined in line 15 is used to hold the user’s response
to the prompt "To try again enter Y". The program uses two methods
from the String class: toLowerCase() and equals(...).
(a) (line 31) toLowerCase() converts the user’s response to all lower case
characters
(b) (line 33) equals("y") is used to compare the user’s response in lower case to
the lower case ”y” and evaluates to true if the user’s response had been ”Y”
or ”y”. If true then execution resumes at line 20, otherwise execution of the
do ...while terminates and execution resumes at line 34.
115
Exercises
39. Modify Example 1 so the program will display the sum of the numbers from 0
to 9.
40. Modify Example 2 so the user gets a report when the program ends: the number
of correct and the number of incorrect answers.
41. Write a program that chooses a random number between 1 and 100, and then
asks the user to guess what the number is. If a user guesses the number the
program informs the user and stops, otherwise the program informs the user if
they too high or too low, and the user is prompted to guess again. Use a do
...while to control the iteration.
42. One can simulate the tossing (rolling) of a six-sided die through the use of the
Random class. In many games two dice are thrown and the player’s turn
depends on the total value of the two dice. The following code instantiates two
dice that can be used in a game:
Random die1 = new Random();
Random die2 = new Random();
Now, if we want to roll the two dice and know the total thrown we could use:
int toss1 = die1.nextInt(6)+1;
int toss2 = die2.nextInt(6)+1;
total = toss1 + toss2;
In some games a player rolls the dice at least once. Suppose we want to simulate a
player rolling the dice until ”snake eyes” are thrown. Snake eyes is the term used
to describe a throw where two one’s appear. Write a program that uses a do
...while to simulate the rolling of two dice. The program must list the totals
thrown until ”snake-eyes” appear.
4 Introduction to Methods
Every Java application has at least one class that has a method named main. If you
execute a Java class the JVM automatically looks for a method named main and passes
control to its first statement.
where <return type> can be one of void, int, double, char, or String;
In this chapter we introduce methods to show you can organize your code to develop
more readable programs. In the following sections we discuss:
117
118
Void Methods
A void method is a named code segment that can be called to execute. When called, it
does something useful, and when complete control returns automatically to the point
following where it was called.
Example 1
displays headings;
The main method in Listing 4.1 calls two methods, displayHeadings and
displayRows, that do just what their names suggest.
Examine lines 7 and 8 below and note how each method is called. Lines 11 and 20 are
the beginnings of the methods – note their headers: public static void …
Listing 4.1
1 /**
2 * 5x5 times table
3 */
4 public class TimesTable
5 {
6 public static void main(String[] args) {
7 displayHeadings();
8 displayRows();
9 }
10
11 public static void displayHeadings(){
12 // heading and column headings
13 System.out.println("\n\t5x5 Times Table");
14 System.out.println();
15 for (int i=1; i<=5; i++)
16 System.out.print("\t"+i);
119
17 System.out.println();
18 }
19
20 public static void displayRows(){
21 // Compute and print rows of times table
22 for (int i=1; i<=5; i++){
23 // row heading and row contents
24 System.out.print(i);
25 for (int j=1; j<=5; j++)
26 System.out.print("\t"+i*j);
27 System.out.println();
28 }
29 }
30 }
void methods are useful for decomposing a complex program into manageable
components. Overall, this type of program decomposition can lead to more readable
programs.
When the JVM executes a statement specifying the name of a void method (i.e. the
calling statement; e.g. lines 7 and 8 above) the following occurs:
the JVM transfers control to the method (one exception – see section on
parameters);
after the method’s last statement executes the JVM transfers control back to the
statement following the calling statement.
Value-returning Methods
A value-returning method is designed to return a value to the point where it is called.
The return type for a method can be any of Java’s primitive types (e.g. int, double,
char, boolean, etc.), String, or any other class defined in Java and its libraries, and
as we will see later on, class types that you create. For now we focus on methods that
return values of type int, double, char, boolean and String.
return <expression>
<expression> is a Java expression that yields a value corresponding to the method’s type.
Example 2
Consider Question 10 from Chapter 3 where we are required to get a value for n from
the user and then calculate and display n! We have rewritten the provided solution
replacing the code that gets the value of n from the user with a method named
askUserForN. See Listing 4.2 for the revised code.
return n;
Listing 4.2
1 import java.util.Scanner;
2 /** Consider the calculation of n factorial defined as:
3 * n! = 1 × 2 × 3 × ... × n where n > 0
4 * Use a while to calculate n!
5 * Prompt the user for the value of n
6 */
7 public class Ch3Q10
8 {
9 public static void main(String[] args){
10 int n = askUserForN();
11 int originalN = n;
12 int nFactorial = 1;
13 while (n > 0){
14 nFactorial = nFactorial * n;
15 n = n-1;
16 }
17 System.out.println("The value of "
18 +n
19 +"! is: "
20 +nFactorial);
21 }
22
23 public static int askUserForN(){
24 Scanner kb = new Scanner(System.in);
25 System.out.println("Please enter a value for n");
26 int n = kb.nextInt();
27 return n;
28 }
122
Parameters
If you require a method that works with one set of values one time, and possibly
another set of values another time, you use a method with parameters. A calling
method can pass values to those parameters in the calling statement.
A calling statement must supply arguments matching each parameter, and the
arguments must be in the same order as the parameters. For example, consider:
This statement would invoke findMax with the values 10, 4, 7 passed to
parameter variables i1, i2, and i3 respectively.
The mechanism Java uses, in computer science terms, for passing values to parameters
is call-by-value. With this technique, all values passed to a method are copied to
corresponding parameter variables. On exit from the method the opposite does not
occur. There is more to be said about this subject, but that is mentioned later on when
we discuss creating your own classes and objects.
Aside: some programming languages may use call-by-value and/or another technique
call-by-reference.
123
Example 3
Listing 4.3 is our rewrite that uses a method named convert that starts
and has one parameter, a variable named s of type String. The main method has the
calling statement:
1 the value of grade in main is copied to the memory locations reserved for s in
the method convert;
2 the code comprising convert executes, and during its execution the variable
num in convert will be assigned a value;
3 lastly, the return statement in convert executes causing the value of num to
be passed back to where convert was invoked (and so nGrade gets a value).
Note the variables in a method are independent of variables outside of it, and so the
variables in convert could just as easily have been named nGrade and grade
instead of num and s. We say the variables defined in a method are local to that
method. Local variables may have the same names as variables in other methods, and
there is no confusion as they belong to separate methods.
Depending on the value of the argument in the calling statement, different values can
be returned by convert:
nGrade = convert ("A"); // nGrade becomes 4.0
nGrade = convert ("C"); // nGrade becomes 2.0
124
125
Listing 4.3
1 import java.util.Scanner;
2 /**
3 * Letter grade translated to a numeric grade.
4 */
5 public class LetterGradeToNumericGrade
6 {
7 public static void main(String[] args)
8 {
9 String grade;
10 double nGrade;
11 System.out.println("Enter letter grade:");
12 Scanner kb = new Scanner(System.in);
13 grade = kb.next();
14 nGrade = convert (grade);
15 System.out.println(grade+" --> "+nGrade);
16 }
17 public static double convert(String s){
18 double num;
19 switch (s) {
20 case "A": num = 4.0;
21 break;
22 case "B": num = 3.0;
23 break;
24 case "C": num = 2.0;
25 break;
26 case "D": num = 1.0;
27 break;
28 default: num = 0.0;
29 }
30 return num;
31 }
32 }
126
Summary
We have known since Chapter 1 that every Java application has a main method. Each
program you write is an algorithm that may be solving some scientific problem, or,
provide a process useful in some business application. Regardless, we need to make
our algorithms comprehensible to others.
A program implements an algorithm that you code in a language such as Java. Your
program’s methods must reflect the overall structure of your algorithm. If some part is
complex then you can break it down into simpler components. In his book Clean Code,
Robert Martin recommends writing methods that “do one thing, and only one thing”.
then,
o if the method is of type void, then when the end of the method is
encountered control returns to the point following the method call and the
calling method resumes execution.
Exercises
1. Rewrite the program in Listing 4.2 so the main method becomes:
public static void main(String[] args)
{
int n = askUserForN();
int nFactorial = factorial(n);
displayResults(n, nFactorial);
}
2. Rewrite the program in Listing 4.3 so the main method becomes:
public static void main(String[] args)
{
String grade = askUserForLetterGrade();
int nGrade = convert(grade);
displayResults(grade, nGrade);
}
3. Write a program that displays the French translation of an English word obtained
from the user. Include a method named translate that returns a French word for a
given English word. The method has one parameter, a word in English, and returns
the French translation according to the table below. If a word passed
to translate does not appear in the table, then the method must return “????”.
English French
season saison
winter hiver
rain plouie
car voiture
street rue
4. We define a palindrome as a word that reads the same in either the forward or
reverse direction.
Examples of palindromes
Ava
Radar
Pip
Otto
Mom
Noon
Layal
129
Write a program that obtains a word from the user and displays whether of not the
word is a palindrome. Include a boolean method isPalindrome that determines
whether or not a word is a palindrome.
5. Suppose we have a simple check digit scheme for a control number. To calculate
the check digit we need to know the sum of the digits of the control number. The
check digit is calculated as the remainder when the sum is divided by 10.
For example if the control number is “2389” then the weighted sum is calculated as
2 + 3 + 8 + 9 = 22
Write a program that obtains a control numbers from the user and prints the control
number followed by its check digit. Include a method checkDigit that returns the
check digit of an integer.
The Random class provides methods the programmer can use to generate random values
that include boolean, integer, and double types. The Math class also has a method
random() that can be used to generate random double values between 0.0 (inclusive)
and 1.0.
In order to generate random values a program must instantiate an object from the
Random class. There are two constructors for this purpose: one that takes an argument
(a seed or initial value) and one that does not (the no-arg constructor). The advantage to
using a seed is that the stream of values is always the same and this can assist in
debugging code. One cannot predict the values to be obtained if the no-arg constructor
is used since it bases its’ seed on the system time.
The table below shows some of the methods in the Random class.
Method Description
nextBoolean() Returns the next pseudorandom uniformly
distributed boolean value
nextInt() Returns the next pseudorandom
uniformly distributed int value
nextInt(int limit) Returns the next pseudorandom
uniformly distributed int value between
0 and limit-1
131
132
Example 1
We begin with a simple example to simulate rolling a six-sided die. Traditionally the
values of the sides are 1, 2, 3, 4, 5, 6. We use Random’s nextInt(...) method to
obtain an int value between 0 and 5. So, if g is an instance of Random, and we want values
between 1 and 6, then we use: g.nextInt(6)+1. The following program simulates
tossing a die 10 times.
Example 2
Consider the tossing of a coin where one side of the coin is considered a head and the
other a tail. There are many approaches one could use, for example:
3. nextInt() generates integers - approximately half are negative, the other half
positive (or half are even and half are odd).
The next program simulates tossing a coin 100 times and tabulating the number of
occurrences for the two outcomes. In the long run we expect the number of heads and
the number of tails to be equal, but that’s not likely to occur on a single run.
Exercises
1. Modify Example 1 using a seed value when instantiating g. For example replace
the line
Random g = new Random()
with
Random g = new Random(101)
Run the program twice and notice the sequence of random numbers is the same both
times. Using a seed can be useful if you are having difficulty debugging your program.
2. In the game of craps there are names given to various outcomes of rolling two
dice. For example:
Names of rolls
snakes eyes two 1s
hard four two 2s
yo-leven 6 and 5
natural 1 and 6, 2 and 5, 3 and 4
Write a program that will simulate throwing 2 dice until snake eyes occurs. The program
must list each throw including the snake eyes.
3. In the standard game of Pig players take turns rolling a single die. In a turn a
player repeatedly rolls a die according to:
a. If a player rolls a 1, the player scores nothing for that turn and it
becomes the next player’s turn.
b. If a player rolls any other number, that number is added to the player’s
turn total and the player’s turn continues.
c. If a player chooses to ”hold”, the player’s turn total is added to the
player’s total score, and it becomes the next player’s turn.
Write a program to simulate the rolling of a single die until a 1 turns up. Your program
must list each roll.
4. Consider the game of Pig again. Write a program to simulate a player’s turn
where the player’s strategy is to continue rolling as long as the turn score is less
than 25. That is, the player holds if the turn score is 25 or better. Of course, if a
1 is rolled, the player gets a turn score of 0. Your program must list each roll and
at the end of the turn display the turn total.
135
Character
The Character class has many static methods that can be used. Because the methods are
static the programmer does not instantiate an object. Instead, when using one of these
class methods it must be prefixed with Character., for example
Character.toLowerCase(ch). The following table lists some common static
methods of the Character class:
Method Description
getNumericValue(...) Returns the int value that the specified
character represents.
isDigit(...) Determines if the specified character is a
digit.
isLetter(...) Determines if the specified character is a
letter.
isWhitespace(...) Determines if the specified character is
white space
toLowerCase(...) Converts the character argument to
lowercase
toUpperCase(...) Converts the character argument to
uppercase
Three examples follow
3. Validating input
136
Example 1
If the data you have is a string then the String method charAt(...) can be used to access a
character at a specific index. When used in conjunction with a for statement the
characters of a string can be accessed one-by-one. In the following program we access
the characters of a string one-by-one and determine the type of each character using the
Character methods isDigit() and isLetter().
Below is the output from CharacterTypes.java for when the user provides the string
"A$12"
137
138
Example 2
The Character method getNumericValue() can be used to obtain the decimal value of a
character. Consider the program in Listing 5.4. The main method in lines 7-13:
calls a method named addDigits to get the sum of digits in the line
26 }
Below is the output where the user provides the string "1A 4c!6" .
140
Example 3
In many situations a user’s input must be validated. Suppose a user is prompted for a
student number that must comprise only digits. If the user enters invalid characters, and
the program executes the Scanner method nextInt(), then the program would crash.
Instead the programmer must use the Scanner method nextInt() and then analyze
the characters to determine if the user entered a correctly formatted value.
isDigit(...) can be used to check if a character is a digit or not. Consider Listing 5.5.
Output from ValidateStudentNumber.java for two runs of the program is shown below.
141
Exercises
5. Java allows char values to be used directly in arithmetic expressions. Modify
Example 2 to just add characters instead of the character’s numerical value using
a statement such as sum += c; The sum in this case is the sum of the internal
representations of those characters.
8. The standard US zip code is five digits. Write a program that prompts the user for
a zip code and then determines if it is valid or not. To be valid the code must be
five characters in length and all characters must be digits.
9. In 1983 the US Postal Service extended zip codes (ZIP+4) to include the five digits
of the ZIP code, a hyphen, and four more digits that determine a more specific
location within a given ZIP code. Write a program to validate a zip code entered
by the user where the user might have entered a standard zip code (5 characters)
or a zip+4 code (10 characters including the dash separating the first 5 digits from
the last 4 digits).
10. Sweden has a personal identity number (personnummer) that is issued by the
Swedish Tax Agency. This identity number has 10 digits with a hyphen between
the 6th and 7th digits, and is such that the 10th digit is a check digit. The check digit
is calculated using the first 9 digits. A weighted sum of products is calculated as
P(digiti × weighti) where the weights are 2, 1, 2, 1, 2, 1, 2, 1, 2. However if a product
is more than 9 it is replaced by the sum of its digits. The check digit must be equal
to 10 minus the last digit (but note that if the last digit of the sum is zero, the check
digit is 0). Write a program to verify the user has entered a valid personnummer:
• 10 digits with a dash between the 6th and 7th digits, and
• the check digit is correctly based on the first 9 digits.
For example consider the personnummer 811228-9874. To verify the check digit
(the last digit, the 4) is correct we need to follow the above procedure. The sum
of the weighted products is:
142
Scanner
Previously we used a Scanner object to obtain data from the user via the standard input
device, the keyboard. The input is considered to be a sequence of tokens where tokens
are strings separated by delimiters which by default are whitespace. To Java, whitespace
includes spaces, tabs, newline, and a few other characters. A Scanner object is said to
parse the input stream making tokens available.
A programmer can specify exactly what constitutes a token. Consider that a program
could be reading a file where tokens are separated by commas (e.g. a CSV file that is easily
generated from Excel). The interested reader is referred to the Java documentation for
more information on how to specify delimiter patterns. For our purposes we use the
defaults for a scanner object and so tokens are strings where the strings are delimited
by whitespace.
To use the methods in the Scanner class we must instantiate a Scanner, for example:
The Scanner class is in the java.util package and so programs need to include:
import java.util.Scanner;
We will illustrate the use of a scanner object for reading a file and another for scanning
a string.
but a class file contains Java bytecode and to view and make sense of its contents would
be quite difficult.
To read a text file we can declare a Scanner object which is associated with that file. Let
us consider only files that are in our project. When the file is contained in our project we
only need to name it as a string, as in: Scanner f = new Scanner(new File("Readme.txt"));
Consider the following table of Scanner methods. We will use a number of these in the
examples that follow.
method name description
next() Gets next token
nextBoolean() Gets next token and converts it to an boolean
nextInt() Gets next token and converts it to an int
nextDouble() Gets next token and converts it to an double
hasNext() Returns true if there is at least one more token
available, false otherwise
hasNextBoolean(...) Returns true if there is at least one more token
available and that token is of type boolean, false
otherwise
hasNextInt() Returns true if there is at least one more token
available and that token is of type int, false
otherwise
hasNextDouble() Returns true if there is at least one more token
available and that token is of type double, false
otherwise
hasNextLine() Returns true if there is at least one more line
available, false otherwise
nextLine() Returns an entire line, up to the next end-of-line
character and returns the line as a String (the
end-of-line character is consumed but it is not
part of the return value).
Note that the above methods can result in errors that cause a program to fail. For
instance, if a program uses nextInt(), but the next token is a character string, then an
exception will occur. If a program executes next(), but the input stream is empty, then an
exception will occur.
145
Consider the following program the reads the file Readme.txt and displays its lines
including line numbers. Note the program has three import statements to direct the
compiler to definitions for Scanner, File and FileNotFoundException.
The File class itself is quite complex but for our purposes we are just naming the file and
instantiating a File object. Errors can arise when a program processes a file - the obvious
one is trying to read a file that does not exist. The Java file FileNotFoundException is
associated with that condition. Note the program also contains a throws clause - Java
requires this and for our purposes here we are declaring that we know this situation
might arise.
1 import java.util.Scanner;
2 import java.io.File;
3 import java.io.FileNotFoundException;
4 /**
5 * Display contents of Readme.txt with line numbers
6 */
7 public class DisplayReadme
8 {
9 public static void main(String[] args)
10 throws FileNotFoundException
11 {
12 Scanner f = new Scanner(new File("Readme.txt"));
13 int i=1;
14 System.out.println("<<<< File Readme.txt >>>>");
15 while (f.hasNext()) {
16 String line = f.nextLine();
17 System.out.println((i++)+" "+line);
18 }
19 System.out.println("<<<< end of listing >>>>");
20 }
21 }
When BlueJ creates Readme.txt it initializes the file with default contents. The
programmer can edit this file to store relevant information about the project. If the file
has not been edited then it has certain contents by default which are:
147
148
Exercises
11. Modify Example 1 to use next() instead of nextLine(). Display each token on a
separate line.
12. Modify Example 2 to get the value for the variable sample from the user.
13. Write a program that prompts the user for 10 boolean values. Display the number
of true values entered by the user.
150
Math
The class Math contains fields for π and e and methods for performing basic numeric
operations including exponential, logarithm, square root, and trigonometric functions.
The methods in the Math class are static methods and so one does not instantiate an
instance. To use a method you must prefix the method name by Math.. For example to
get the absolute value of an int x the programmer uses:
int y = Math.abs(x);
or to determine the circumference of a circle of radius r:
double circumference = 2.0 * Math.PI * r;
Next we list a number of the Math methods and then we present an example.
Fields
E double e
PI double π
Static Methods
pow double Returns the value of the first argument raised to the power of the second
argument. e.g. Math.pow(x, y)
random double Returns a double value with a positive sign, greater than or equal to 0.0
and less than 1.0.
e.g. Math.random()
max int returns the larger of two int values. e.g. Math.max(5, 2)
max double returns the larger of two double values. e.g. Math.max(5.6, 2.0)
min int returns the smaller of two int values. e.g. Math.min(5, 20)
min double returns the smaller of two double values. e.g. Math.min(5.3, 20.7)
Example 1
The following program prompts the user for three int values and reports the largest
of the three.
Exercises
14. Write a program that accepts int values until the user enters a zero. The program
must display the smallest value greater than zero.
15. Write a program that obtains the radius of a circle from the user and calculates
the area of the circle.
16. Write a program that obtains the radius of a sphere from the user and calculates
the volume of the sphere.
17. Write a program that obtains the x and y values of a right-angled triangle from the
user and calculates the length of the hypotenuse.
154
Integer
The Integer class has many static fields and methods that can be used. Because these are
static the programmer does not instantiate an object. Instead, when using one of these
class fields or methods it must be prefixed with Integer., for example Integer.MAX_VALUE.
The following lists some common static fields and methods of the Integer class:
Field Description
MAX VALUE A constant holding the maximum value an int
can have, 231−1.
MIN VALUE A constant holding the minimum value an int can
have, −231.
Method Description
max() Returns the greater of two int values as if by
calling Math.max. E.g Integer.max(34, 55)
min() Returns the smaller of two int values as if by
calling Math.min. E.g Integer.min(34, 55)
parseInt() Parses the string argument as a signed decimal
integer. E.g. parseInt(” 23 ”)
Example 1
Suppose input values to a program are provided in a CSV style. CSV stands for comma-
separated-values and is a format that has been used in computing systems for moving
data from one system to another system. Suppose the data is available in the following
manner: each line has an item name, a comma, and a quantity, with no embedded spaces.
For example:
item,quantity
monitor,45
laptop,55
tablet,50
desktop,40
155
Using a Scanner object a program could use the Scanner method nextLine() to get a line
having three things: an item name, a comma, and an integer. The program can find the
location of the comma and know that what follows in the string is a quantity. The
quantity can be converted to an integer using the parseInt() method. The program below
is designed to obtain 4 lines of such information from a user.
When the program is run with the 4 lines mentioned above we have the output:
156
157
Exercises
18. Modify Example 1 to find the item for which the quantity on hand is the largest.
19. Write a program that accepts one line that holds an unknown number of integers
in a CSV format. The program must print each value on a separate line and then
display the largest and smallest of the values.
158
6 ArrayLists
There are several techniques for handling collections of data. In this chapter we
introduce the ArrayList. An ArrayList can be visualized as a linear list of objects at index
positions 0, 1, ....
The ArrayList is a data structure that grows and shrinks gracefully as objects are added
and removed. This is a distinct contrast to the array structure covered in Part II of these
notes (with an array once you have defined its size the size cannot be changed).
Below we list some important methods that are defined for ArrayList.
Method Description plus examples using:
ArrayList¡String¿ people = new Arraylist()
add(...) Can be used to either
a) append a given element to the end of a list,
or,
b) if a position is specified insert the given
elementat the specified position (following
elements are shifted down).
people.add(”Jaime”);
people.add(4, ”Jaime”) ;
clear() Removes all elements from a list.
people.clear();
contains(...) Returns true if this list contains the specified
element.
boolean found = people.add(”Jaime”);
159
160
Examples
Example 1. Basic Operations
It is considered a good programming practice to specify the data type for the elements
of an ArrayList. The way to express this is to declare the type inside a pair of angle
brackets: < >. By specifying this a program cannot accidentally add a different type of
object to the ArrayList. We say this makes the ArrayList typesafe. In this example we
use the basic add() and remove() methods to add 4 elements and remove 1 element, and
then we use an enhanced for to display the elements one by one.
162
The following shows the prompt to the user, the user’s response:
Joe Joe Jasper Abigail Abigail Jasper stop
and the output generated:
164
This example is included to show how ArrayLists are specified in some legacy code.
When ArrayLists were added to the Java language they were not typesafe - the declaration
of an ArrayList did not include a type specification, for example:
This declaration has no angle brackets and so no type specification, and so its possible to
add any kind of object to the ArrayList. Currently, the recommended practice is always to
include a type in the declaration so the program is more robust - certain errors at
runtime cannot occur. This example is included only for demonstration purposes and is
not recommended practice. The output follows the code listing.
The output below shows two String objects, a System.out object, and a Scanner object - all
of which were added to the ArrayList.
166
Sieve of Eratosthenes
A Greek mathematician, Eratosthenes of Cyrene, who lived more than 2, 000 years ago
developed an algorithm that enables us to find prime numbers. In our adaptation we are
going to store a list of prime numbers in an ArrayList.
With a sieve of size n we can find all the prime numbers between 1 and n. Recall that a
prime number is an integer greater than 1 that has no positive divisors other than 1 and
itself. For instance, 7 is a prime number since the only integers that evenly divide 7 are
1 and 7 itself; the number 7 can only be expressed as the product of two numbers: 1 ×7.
Any integer that is not prime can be expressed as the product of two integers other than
1 and itself. For example, 8 is not a prime number since it can be expressed as a product
of 2 and 4. The integer 8 is divisible by 1, 2, 4, and 8; we say the integer 8 is a composite
integer.
There are many references to the Sieve of Eratosthenes on the web . At the time of writing
an article could be found in Wikipedia that illustrates a sieve for finding all primes less
than 120.
To use the sieve we first construct a list of positive integers ranging up to a limit. The
algorithm is iterative; it begins by crossing off all multiples of 2. Then the list is scanned
for the next integer following 2 that is not crossed off (this will be 3), and its multiples
are crossed off. This process of finding the next non-crossed off integer and crossing off
its multiples continues until no more can be found. In the implementation we represent
the list with a list of integers where the ith entry is simply i, and we cross off an integer
by setting it to 0.
i. p ← 2*next
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
• When step 2 executes for the first time (next is 2) the list becomes
0 1 2 3 0 5 0 7 0 9 0 11 0 13 0 15 0 17 0 19 0 21 0 23 0 25
0 1 2 3 0 5 0 7 0 0 0 11 0 13 0 0 0 17 0 19 0 0 0 23 0 25
0 1 2 3 0 5 0 7 0 0 0 11 0 13 0 0 0 17 0 19 0 0 0 23 0 0
• From the above, starting at 2, we easily see primes less than or equal
to 25 are: 2 3 5 7 11 13 17 19 23
1 import javax.swing.JOptionPane;
2 import java.util.ArrayList;
3
4 public class SieveOfEratosthenes
5 {
6 public static void main(String[] args){
7 // get limit from user
8 String limitAsString = JOptionPane.showInputDialog(
9 "Enter upper limit:");
10 int limit = Integer.parseInt(limitAsString);
11 // set up the list of integers
12 ArrayList<Integer> list = new ArrayList<>();
13 for (int i=0; i<=limit; i++){
14 list.add(i);
15 }
16 // apply the sieve technique
17 for (int next=2; next<limit; next++){
18 if (list.get(next)!=0){
19 // cross off multiple of next
20 int p = 2*next;
21 while (p <= limit){
22 // cross off this element
23 list.set(p, 0);
24 p+=next;
25 }
26 }
27 }
28 // display primes
29 ArrayList<Integer> result = new ArrayList<>();
30 for (int i=2; i<limit; i++){
31 if (list.get(i)!=0) result.add(i);
32 }
33 JOptionPane.showMessageDialog(null,
34 "primes < "+limit+" are "+result);
35 }
36 }
169
Parallel Lists
There are situations where more than one list is needed. When it is also the case that
elements of the lists at the same index are related to one another, we say we are using
parallel lists.
Example 5
Suppose we are interested in words and how many times each word occurs. To do this
we could use two Arraylists, one for words and the other for the frequency of words.
Let us consider that the ith element of frequency is the frequency of occurrence for the
word stored as the ith element of word. In this case frequency and word are parallel
Arraylists.
Consider Listing 6.5 where words are stored in word, and frequencies in a parallel list
frequency.
1 import java.util.ArrayList;
2 public class WordFrequency
3 {
4 public static void main(String[] args){
5 // two parallel lists: words and frequencies
6 ArrayList<String> word = new ArrayList<>();
7 ArrayList<Integer> frequency = new ArrayList<>();
8 // try adding words: today, tomorrow, today
9 addWord(word, frequency, "today");
10 addWord(word, frequency, "tomorrow");
11 addWord(word, frequency, "today");
12 // display the two lists
13 System.out.println(word);
14 System.out.println(frequency);
15 }
16
17 /**
18 * addWord: add a new word to the list of words, or
19 * increment frequency for existing word
170
20 *
21 * parameters:
22 * wordList a list of words
23 * frequencyList frequencies for words
24 * newWord potential new word
25 */
26 public static void addWord(
27 ArrayList<String> wordList,
28 ArrayList<Integer> frequencyList,
29 String newWord)
30 {
31
32 int i = wordList.indexOf(newWord);
33 if ( i>=0 ) {
34 // new word found in list
35 int currentFrequency = frequencyList.get(i)+1;
36 frequencyList.set(i,currentFrequency);
37 }
38 else {
39 // new word not found
40 wordList.add(newWord);
41 frequencyList.add(1);
42 }
43 }
44 }
Output:
171
Exercises
1. There is a class called Collections which can be used in a program if one includes
the import statement:
import java.util.Collections;
The ArrayList is part of the Java Collections framework and there is a method
sort(...) in Collections that can be used to sort an ArrayList. For instance, to
sort the ArrayList named people you use the statement:
Collections.sort(people);
The Math class contains various mathematical constants and utility methods for
common mathematical operations. For instance, the Math class has a field named PI. In
a program we can have a statement such as
where we reference PI using the name of the class, Math. In particular we did not create
an object of type Math. It’s a similar case for the method max() in the Math class. To find
the maximum of two numbers we can use the expression Math.max(num1, num2). PI is
a static field and max() is a static method; these types of fields and methods can be
accessed without the need for an object.
So to use the facilities of the Math class we did not need an object, but there are other
times when it was necessary for us to create an object. For example consider the Scanner
class and the instantiation of an object:
In order to get the next token from scanner we use expressions like scanner.next().
The object (also called an instance) named scanner must keep track of its source and its
current position on that source. When a scanner object executes the next() method, the
method obtains the next token on the source, advances its position on that source, and
returns the token.
With respect to methods we have seen another difference: sometimes we have used a
method that returned a value and other times we invoked a method knowing that
something will happen. When we simulate the tossing of a six-sided die we use:
173
174
When we display something in the user’s terminal window we use a statement like:
and where there is no value returned that we make any use of. The method println()
is an example of a void method (one that does not return a value).
• present an example from an educational setting where multiple classes are useful;
• discuss modifiers named public and private used to control access to classes,
fields, methods, and constructors;
The above list is lengthy and indicates this chapter covers several new Java programming
concepts.
175
public class
Student{
...
public class
Subject{
...
public class
Course{
...
public class
Instructor{ ...
Before writing any code we recommend drawing a Class Diagram to illustrate the
concepts you are thinking about. To simplify we present a diagram in Figure 8.1 that
shows just a subset of the concepts mentioned above: two classes and a relationship. The
relationship is based on a business rule for the institution: a student declares a major in
one subject, and that for a subject there can be many students majoring in that subject.
Each class is shown in its own compartment and a relationship is shown as a named line.
The small filled arrow shape gives the viewer an indication of how to read the diagram.
The 1 and the * are called multiplicities that stand for one and many respectively, and are
used to express how many of one object can be related to another object through the
relationship. In this example the association line represents a two-part business rule:
176
As we continue we will be developing Student and Subject, and in Section 8.11 you will
find complete listings of these two classes.
Fields
We have learned to define variables when we needed to keep track of information.
Suppose we were developing a class to represent the concept of student. We would need
variables for student identifier, first name, last name, gender, active, etc. Formally these
variables are referred to as fields and previously we would have defined these similar to:
However, it generally recommended that one define the above fields using a different
modifier named private. By specifying private we make it impossible for these fields
to be referenced from outside the class. We will say more about this idea later. Now we
have:
The above is Java code that defines part of a class named Student. A less formal way to
illustrate the above is to use a class diagram. Now we show two compartments, one for
the name of the class, and one for the names of the fields and types, as shown in Figure
8.2.
Student objects can be created where each object would have its own copy of these fields,
and so each student object could have different values stored in its fields. Figure 8.3 is
177
an Object Diagram where each object is represented by two compartments. In the upper
compartment we show a name for an object (e.g. jill) and the class of the object (e.g.
Student). By convention this information is underlined. In the lower compartment we
show values for fields. The diagram makes it clear there are three students and each
student object has its own fields to hold values for id, first name, etc.
178
If we define a field in a class and specify it as static that field is referred to as a class field.
Only one copy of a class field exists regardless of the number of objects that exist.
Suppose we are developing a system where we generate student identifiers sequentially.
Consider a field named lastId where we store the id used for the last student object
created. Consider the following for our Student class:
In Figure 8.4 we show the Student class and 3 student objects. Note that we show the
lastId field in the Student class with its current value. Later we will discuss methods and
how the value of lastId is used and updated.
Methods
A method is a named collection of Java statements. Optionally a method can have a
parameter list to provide for data to be passed in and can be designed to return a value
back to the point where it is invoked. Methods are an important tool when we write Java
programs. We use methods for two purposes.
1. To eliminate code redundancy: If we find that we are repeating the same code as
elsewhere in our program we write that code as a method and call it from
wherever it’s needed. Now, if this code ever needs to change there is only place
where the change needs to be performed.
When we are designing a program and we decide that certain functionality must be
placed into a method we determine
Value-returning methods
A method can be designed to return a value of any primitive type, array, or object type.
We have seen many examples of these including max() and min() in the Math class, and
the nextInt() and nextBoolean() of the Random class.
In our educational example that we are developing we have made the fields of Student
private. Instead of giving other classes direct access to fields the convention is to provide
methods for this purpose. One reason to do things this way is to hide the implementation
181
of fields which then makes it easier to change an implementation later. So, for each field
of the Student getters/accessors class we can design a group of methods that are called
getters (sometimes called accessors). For each of these we specify the data type they
return and the last statement in a getter method is a return statement. Consider the
following code in the Student class:
Observe how methods are named above. Because they are getters, each method name
(but one) begins with ”get” prepended to a field name where the first character of the
field name is capitalized. Since active is boolean its getter begins with is. As for variable
names, we use ”camel case” for method names.
Consider getLastId() above. It is defined as static since the lastId() field is static. To
invoke this method we use:
182
Calling the other methods above only make sense in the context of some object, and so
these methods are examples of instance methods. If joe is the name we are using to
reference a student object then we can write meaningful statements to get, for example,
the gender of this student:
Two other standard value-returning methods normally provided for a class are the
toString() and equals() methods.
When an object is being displayed via println(); it is the toString() method that
determines what will be displayed. The toString() method returns a string that
represents an object. As an example, we will use the following toString() in our
system:
If the statement
System.out.println(jill);
was executed then the output to the terminal window would be:
1 Jill Lee
When objects are compared for equality a programmer normally uses the equals()
method. Previously we have used the equals() method to compare two strings for
equality. The idea that two strings are equal is simple: the two strings are either the same
string, or they are of the same length comprising the same characters. In a program to
compare two names, say name1 and name2, we can use either:
name1.equals(name2)
or
183
name2.equals(name1)
For more complex objects like student objects it is not always so simple to decide on the
equality test. A student object has several fields that could enter into consideration. At
this time we will take a simple viewpoint on this and consider two student objects the
same if they have the same value for the student identifier. Consider the method:
Note how this method has a parameter s of type Student. The equals method is invoked
for a particular student object and that object is being compared to the object s. If some
code were to check two student objects (say jill and sam) to see if the objects have the
same content the programmer could code either
if (jill.equals(sam))
or
if (sam.equals(jill))
If instead one uses jill == sam it is memory addresses (and not content) that are being
compared for equality. We use == only to determine if two object references are to the
same object, as in:
void methods
Sometimes we need methods just to complete some task and for which there is no value
that needs to be returned. One of the conventions in java programming is to provide
setter methods that are used only to set, or change, the value of a field. Consider this
partial listing of Student:
In the above we have commented out a setter that could have been included for id. A
reason for not having a setter for id is the idea that once a student is assigned a unique
identifier that identifier would never change.
Observe how methods are named above. Because they are setters, each method name
begins with ”set” prepended to a field name where the first character of the field name
is capitalized. As mentioned before, we use
185
Constructors
Constructors are used to instantiate an object. If you do not explicitly code a constructor,
then the Java compiler creates a no-arg constructor for you. A no-arg constructor is a
constructor that takes no arguments - the parameter list is empty. A constructor is
invoked any time you use the new operator, for example:
A constructor is similar to a method in that it is a block of code that may have a parameter
list, but there are two major differences:
1. A constructor returns an object but the code for a constructor does not include
any return statements.
Its common for a class to have multiple constructors that will differ from one another in
their parameter lists (see overloading, Section 8.6). To illustrate we introduce two
constructors for the Student class:
The first part of our Student class is now (note that the code for nextId() is shown
on page 199 ):
1 /**
2 * A student.
3 */
4 public class Student {
5 // class fields
6 private static int lastId;
7 // instance fields
186
The second constructor (lines 23-35) illustrates a style of coding that is quite common
for constructors and methods. In the parameter list of the constructor the parameters
have the exact same name as the corresponding fields. Formally, in the Java language, we
say the field is shadowed by the parameter. To reference the field within the method you
must use the this keyword. When the name is used alone (e.g. firstName) in a
187
this.firstName = firstName;
The right hand side of the assignment statement is a reference to a parameter and the
left hand side of the assignment statement is a reference to the the object’s field. And so
this assignment statement assigns a value passed in via the parameter to an object’s field.
We illustrate the class diagram for the Student class with three compartments, where
the third shows constructors and methods. Note that we have left out some details such
as the field types and parameter types. We have included plus and minus signs to show
whether a method or constructor is public(’+’) or private(’-’).
Using constructors
A constructor is invoked any time a program executes a new operator. Consider the code
below where we invoke each of the above constructors. For the no-arg constructor we
follow up with setters to fill out the student object.
The output from UseConstructors is shown below. We can see from the output
that when a student object is displayed the toString() method was used.
189
Classes
When complex systems are developed Java classes will be organized into packages. We
have used several packages (i.e. the Java class libraries) where each library is a package
containing related classes. For example,
The packages we have been using are all designated as public meaning that any other
class can use them. If there is a need to provide different accessibility then other
modifiers such as private and protected can be used. Please see Volume II of these notes
for further information.
For introductory programming we will only use public for our classes. With BlueJ all of
our classes will be in one default package. For more information with respect to BlueJ
consult the BlueJ documentation.
Fields
If a field is designated private the field can only be accessed from within the class where
it is defined. This is considered good practice because the class has control over the
implementation of the field and exposes the field only through methods. This idea of
keeping the implementation aspects hidden is called Information Hiding.
(with minor modification) the needs of other classes. So, information hiding is a way of
controlling the scope of changes in a system.
When a field is designated public the field can be accessed from any other class. What
can happen then is that other classes become dependent on the data type that is used.
However, there are situations where public is appropriate - consider the utility class
Math. Math has two public fields PI and E for π and e.
Methods
When a method is designated public then any other class can invoke that method. For
getter and setter methods this is the usual practice.
When a method is designated as private the method can only be called from within the
class where it is defined. In our Student example we use a private method that controls
the value of the field lastId. Consider the constructor below and the utility method
nextId(). This utility method is only called from a constructor and nothing outside the
class can call it. In this way the value of lastId can never be changed except when a
Student object is created.
public Student(){
id = nextId();
}
private int nextId(){
// increment lastId and return the new value // to be used for
the new student.
return ++lastId;
}
Constructors
When a constructor is designated public then any other class can use that constructor to
create an object. This is the usual case for constructors.
When a constructor is designated as private the constructor can only be called from
within the class where it is defined. One class we have used that has a private constructor
is Math. Math is a utility class made up of static fields and static methods, and so there
191
would be no benefit to ever havinga Math object. The private constructor prevents
anyone from instantiating a Math object.
If you try to instantiate an instance of Math your program will not compile; the message
you receive back from the compiler is ”Math() has private access in java.lang.Math”.
Overloading
The Java language allows you to define more than one method with the same method
name as long as the parameter lists are different. If two or overloaded more methods
have the same name we say the name is overloaded. The same is true for constructors -
a class can have more than one constructor as long as their parameters lists are different.
We have seen overloading in practice with the previous example where two constructors
were coded for the Student class.
192
Associations
Recall the class diagram from Figure 8.1 reproduced below.
To implement this system of classes we need to define a Subject class. Later we discuss
the implementation of the association. To keep our example simple Subject is defined to
have two fields - see below.
1 /**
2 * Subject area in which a student * may declare a major.
3 */
4 public class Subject
5 {
6 // fields
7 private String code;
8 private String name;
9 //constructor
10 public Subject(String code, String name)
11 {
12 this.code = code;
13 this.name = name;
14 }
15 // getters
16 public String getCode(){
17 return code;
18 }
19 public String getName(){
20 return name;
21 }
22 // setters
23 public void setCode(String code){
24 this.code = code;
25 }
26 public void setName(String name){
27 this.name = name;
28 }
29 // toString()
30 public String toString(){
193
When we implement an association we must consider that the association can be viewed
from either side of the association. So in this case we can say there is a student side and
a subject side. Such an association is sometimes called a one-to-many association
because for each student there is only one subject area, and for each subject area there
can be many related students.
Let us consider the student side, is majoring in, first. We have stated that a student
chooses one major and so a simple field could be used for this purpose. We add a field
named major and so the fields in Student now become:
Notice that the last field major, of type Subject, is the field that implements the
association for a student object. For each student object there is field that can be set to
the student’s major subject. Following the convention of getters and setters we add the
following two methods to Student:
// getter
public Subject getMajor(){
return major;
}
// setter
public void setMajor(Subject newMajor){
major = newMajor;
194
To show how we can make use of the above field, consider the code segment below
where a student sam and a subject area math are instantiated, and then we add math as
sam’s major.
Now, we consider the other side of the association ...the subject side. To implement the
subject side of the association, has majors, we need to add a field to the Subject class.
Since many students could have the same major a good name for the field is majors and
a good choice for type is ArrayList<Student> as this allows for any number of
students.
We show selected lines of the Subject class listed below. In line 5 we declare an
ArrayList of Students, and in the constructor (lines 8-13) an empty ArrayList is
created. There is a getter for majors in lines 18-20 that returns majors, and a setter in
lines 24-26 where there is a parameter of type ArrayList. In addition to the getters and
setters we include one more method addMajor( ), in lines 28-30, that allows one to
add a student to the existing list of majoring students.
We show selected lines of the Subject class listed below. In line 5 we declare an ArrayList
of Students, and in the constructor (lines 8-13) an empty ArrayList<Student> is created.
There is a getter for majors that returns majors, and a setter where there is a parameter
of type ArrayList<Student>. In addition to the getters and setters we include one more
method addMajor( ) that allows one to add a student to the existing list of majoring
students.
6 //constructor
7 public Subject(String code, String name)
195
8 {
9 this.code = code;
10 this.name = name;
11 majors = new ArrayList();
12 }
13 // getters
14 …
15 public ArrayList<Student> getMajors(){
16 return majors;
17 }
18 // setters
19 …
20 public void setMajors(ArrayList<Student> majors){
21 this.majors = majors;
22 }
23 // add a student to those majoring in this area
24 public void addMajor(Student newMajor){
25 majors.add(newMajor);
26 }
27 …
Now reconsider the case where there is a student sam and a subject area math, and
where sam declares math as the major. There are two actions we must perform relating
to the two sides of an association. Not only do we add math as the major for sam, but we
add sam to the list of majoring students for math. Consider the following program where
lines 12 and 13 perform the transaction for declaring a major.
1 /**
2 * Create a student Sam and a subject area Math
3 * and then code the action of
4 * Sam declaring a major in Math
5 */
6 public class SamDeclaresMathMajor
7 {
8 public static void main(String[] args){
9 Subject math = new Subject("Math","Mathematics");
10 Student sam = new Student("Samantha","Jones",'F',true);
11 // two actions for the "declare major" transaction
12 sam.setMajor(math);
13 math.addMajor(sam);
196
Reusing code
Consider a case where we want to declare a major for several students. We can choose
to duplicate lines 12 and 13 in Listing 7.2 several times, or, we can create a method that
contains the equivalent of those, and invoke that method as many times as necessary. In
this way we can eliminate code redundancy and can make the overall program easier to
comprehend. And if the code for declaring a major has to change, the change affects the
small method declareMajor(). Consider the following example where we call
declareMajor() several times:
The output below shows the students who have declared their major to be Mathematics.
198
When the called method completes and control returns back to the caller the opposite
does not occur - parameter values are not copied back into the arguments. The caller’s
fields are not altered unless an argument is an object and the called method has modified
the object. If the called method alters the object then the caller’s argument (object) is
changed.
Recall that a variable that represents an object holds a reference to (the memory address
of) the object. So when an object is passed it is the reference that is copied to the
parameter. When the called method accesses the object through the parameter it is
accessing the object and not some copy of the object.
Consider the program below and the method removeMajors() that has two parameters:
the first is n, an int which is a primitive data type, but the second one is an object - an
ArrayList named x. The method removes n elements from x decrementing n in the process.
From the output you will see the arguments before and after the call. The ArrayList is
changed, but the int variable is not changed.
199
42
43 public static void declareMajors
44 (Student s, Subject m)
45 {
46 // s declares a major in m
47 s.setMajor(m);
48 m.addMajor(s);
49 }
50 }
The output below shows the arguments, an int and an ArrayList, before and after the call.
201
A method can be defined such that the last parameter can accept multiple values.
Between the parameter type and the parameter name for the last parameter we include
an ellipsis (...). In the method the last parameter is then an array.
Recall the last program, Listing 7.4, where each student declares a Mathematics major.
That program invokes declareMajors() 3 times, once per student. In the program
listing below we have changed the method in such a way that all students who declare
the same major can be handled in a single call to the method.
In line 13 of the calling method there are three Student variables passed to
declareMajors():
In lines 22-25 you can see the elements of s are accessed using an enhanced for
statement.
When the program is run we get the same output as before - showing three
Mathematics majors:
203
41 return ++lastId;
42 }
43
44 public int getId(){
45 return id;
46 }
47
48 public static int getLastId(){
49 return lastId;
50 }
51
52 public String getFirstName(){
53 return firstName;
54 }
55
56 public String getLastName(){
57 return lastName;
58 }
59
60 public char getGender(){
61 return gender;
62 }
63
64 public boolean isActive(){
65 return active;
66 }
67
68 public Subject getMajor(){
69 return major;
70 }
71
72 public void setLastId(int newLastId){
73 lastId = newLastId;
74 }
75
76 // no setter for the student's id field
77 // public void setId(int newId){
78 // id = newId;
79 // }
80
81 public void setFirstName(String newFirstName){
82 firstName = newFirstName;
83 }
205
84
85 public void setLastName(String newLastName){
86 lastName = newLastName;
87 }
88
89 public void setGender(char newGender){
90 gender = newGender;
91 }
92
93 public void setActive(boolean newActive){
94 active = newActive;
95 }
96
97 public void setMajor(Subject newMajor){
98 major = newMajor;
99 }
100
101 public String toString(){
102 return id+" "+firstName+" "+lastName;
103 }
104
105 public boolean equals(Student s){
106 return id == s.id;
107 }
108 }
14 {
15 this.code = code;
16 this.name = name;
17 majors = new ArrayList();
18 }
19 // getters
20 public String getCode(){
21 return code;
22 }
23
24 public String getName(){
25 return name;
26 }
27
28 public ArrayList<Student> getMajors(){
29 return majors;
30 }
31 // setters
32 public void setCode(String code){
33 this.code = code;
34 }
35
36 public void setName(String name){
37 this.name = name;
38 }
39
40 public void setMajors(ArrayList<Student> majors){
41 this.majors = majors;
42 }
43 // add a student to those majoring in this area
44 public void addMajor(Student newMajor){
45 majors.add(newMajor);
46 }
47 // toString()
48 public String toString(){
49 return code+" ("+name+")";
50 }
51 // equals(...)
52 public boolean equals(Subject other){
53 return this.code == other.code;
54 }
55 }
207
Exercises
1. Create each of the three students shown in the object diagram of Figure 8.3 and
the subject areas Computer Science and Mathematics. Write the code to
implement the transactions: - Samantha declares a major in Computer Science;
- Robert declares a major in Computer Science; - Jill declares a major in
Mathematics.
2. Suppose we must create a way for a student to change their major. This can be
done by adding another method to Subject that would remove a student from
the list of students majoring in a subject area. Write this method and then write
the code necessary for the following transactions:
3. Add a new method to the Student class that returns a student’s full name.
4. In Listing 7.5 there are three Student objects passed to declareMajors().
Because the last argument in declareMajors() is an array you can pass an
array instead of the three Student arguments. Place jill, sam, and bob in a
Student array and call the method using two arguments: the subject and the
Student array.
5. Develop a Course class and then use a program to instantiate the following
objects:
208
Write a program that creates two subject areas and four courses as shown in the
following object diagram. Note the lines that connect a subject to a course - these link
lines show which courses are offered by which subject area.
[2] http://www.acm.org/press-room/news-releases/2013/fellows-2013
[3] http://www.ieee.org/documents/vonneumannrl.pdf