Java PartI
Java PartI
Week 1
1.2 Commands
Computers execute different operations, or actions, based on the commands.
For example, when printing the text "Hello world!" on the screen, it is done
by the command System.out.println.
System.out.println("Hello world!");
The System.out.println command prints the string given inside the brackets
on the screen. The suffix ln is short for the word line. Therefore, this
command prints out a line. This means that after the given string has been
printed, the command will also print a line break.
Even though neither the compiler nor the interpreter need line breaks in
the source code, they are very important when considering human readers
of the source code. Line breaks are required to divide source code in a clear
manner. Readability of source code will be emphasized throughout this
course.
1.4.2 Parameters (information passed to commands)
The information processed by a command are the parameters of a
command. They are passed to the command by placing them between ()
brackets that follow the command name. For example, the System.out.print
command is given the text hello as a parameter as follows:
System.out.print("hello").
1.4.3 Comments
Comments are a useful way to make notes in the source code for yourself
and others. Everything on a line after two forward slashes // is treated as a
comment.
1.4.4 Example of using comments
// We will print the text "Hello world"
System.out.print("Hello world");
System.out.print(" and all the people of the world."); // We print more text
to the same line.
// System.out.print("this line will not be executed, because it is commented
out");
The last line of the example introduces a particularly handy use for
comments: you can comment out code instead of completely deleting it if
you want to temporarily try out something.
The program is stored in a text file named after the program with the .java
extension. For a program named Example, the file should be named
Example.java.
The execution of the program begins at the part marked with the //
program code comment above. During our first week of programming, we
5
will limit ourselves to this part. When we are talking about commands such
as printing, we need to write the commands into the program body. For
example: System.out.print("Text to be printed");
public class Example {
public static void main(String[] args) {
System.out.print("Text to be printed");
}
}
From this point on, the main program body will be omitted from the
examples.
Until you become familiar with NetBeans, follow the guides and steps
precisely. Most of the following exercises show what needs to be printed to
the screen for the program to function correctly.
Note: Do not do the exercises by writing code and then clicking the test
button. You should also execute the code manually (green arrow) and
observe the result on the screen. This is especially useful if an exercise fails
to pass the tests.
In the following exercises, we will practice the use of NetBeans and
printing of text on the screen.
Remember to read the guide on using NetBeans before you continue!
Please answer to our survey: here. It will take less than five minutes.
Exercise 1: Name
Create a program that prints your name to the screen.
The program output should resemble the following:
Jane Doe
Exercise 3: Spruce
Create a program that prints the following:
*
***
*****
*******
*********
*
The information stored in a variable always has a type. These types include
text (String), whole numbers (int), decimal numbers (double), and truth
values (boolean). A value can be assigned to a variable using the equals sign
(=).
int months = 12;
Printing:
The variable's type is text. Its value is includes text
The variable's type is integer. Its value is 123
The variable's type is decimal number. Its value is 3.141592653
The variable's type is truth value. Its value is true
A variable holds its value until it is assigned a new one. Note that the
variable type is written only when the variable is first declared in the
program. After that we can use the variable by its name.
int wholeNumber = 123;
System.out.println("The variable's type is integer. Its value is " +
wholeNumber);
wholeNumber = 42;
System.out.println("The variable's type is integer. Its value is " +
wholeNumber);
10
11
Chickens:
3
Bacon (kg):
5.5
A tractor:
There is none!
In a nutshell:
3
5.5
There is none!
Variable names can contain numbers as long it does not start with one.
Variable names cannot be composed solely of numbers, either.
int 7variable = 4; // Not allowed!
int variable7 = 4; // A valid, but not descriptive variable name
Variable names that have been defined before cannot be used. Command
names such as System.out.print cannot be used, either.
13
int camelCase = 2;
int camelCase = 5; // Not allowed, the variable camelCase is already
defined!
5. Calculation
14
(which means 2 + 4)
// 13
16
The remainder can be calculated using the remainder operation (%). For
example, the calculation 7 % 2 yields 1.
int remainder = 7 % 2; // remainder is 1 (integer)
If either the dividend or the divisor (or both!) is a floating point number
(decimal number) the end result will also be a floating point number.
double whenDividendIsFloat = 3.0 / 2; // result is: 1.5
double whenDivisorIsFloat = 3 / 2.0; // result is: 1.5
If needed, integers can be converted to floating point using the type cast
operation (double) as follows:
int first = 3;
int second = 2;
double result1 = (double)first / second; // result is: 1.5
double result2 = first / (double)second; // result is: 1.5
double result3 = (double)(first / second); // result is: 1
17
In the last example calculation, the result is rounded incorrectly because the
calculation between the integers is done before the type cast to a floating
point number.
If the quotient is assigned to a variable of integer type, the result will be an
integer as well.
int integerResultBecauseTypeIsInteger = 3.0 / 2; // quotient is
automatically integer: 1
The next example will print "1.5" because the dividend is transformed into a
floating point number by multiplying it with a floating point number (1.0 * 3
= 3.0) before the division.
int dividend = 3;
int divisor = 2;
double quotient = 1.0 * dividend / divisor;
System.out.println(quotient);
18
int dividend = 3;
int divisor = 2;
double quotient = dividend / divisor * 1.0;
System.out.println(quotient);
From now on, make sure that you name your variables that follow good
conventions like the variables in the examples above.
Exercise 5: Seconds in a year
Using this information, we can print a mix of strings and values of variables:
int x = 10;
System.out.println("variable x has the following value: " + x);
20
int y = 5;
int z = 6;
System.out.println("y has the value " + y + " and z has the value " + z);
Exercise 6: Addition
Create a program to calculate the sum of two numbers. At the beginning
of the program two variables are introduced and those variables hold the
numbers to be summed. Feel free to use other variables if you need to.
For example, if the variables hold numbers 5 and 4, the program should
output:
5+4=9
If the variables hold numbers 73457 and 12888, the program output
should be:
21
Exercise 7: Multiplication
Create a program similar to the previous one except that it multiplies the
two numbers instead of adding them.
For example, if the variables hold numbers 2 and 8, the program output
should be:
2 * 8 = 16
If the variables hold numbers 277 and 111, the program output should be:
277 * 111 = 30747
22
Let us add the Scanner to our existing main program body. Do not worry if
the main program body seems obscure as we will continue to write our
code in the part marked // program code.
import java.util.Scanner;
public class ProgramBody {
public static void main(String[] args) {
Scanner reader = new Scanner(System.in);
// program code
}
}
23
The program above combined along with the main program body is shown
below. The name of the program is Greeting, which means that it must be
located in a file named Greeting.java.
import java.util.Scanner;
public class Greeting {
public static void main(String[] args) {
Scanner reader = new Scanner(System.in);
System.out.print("Who is greeted: ");
String name = reader.nextLine(); // Reads a line of input from the user
and assigns it
//
24
When the program above is executed, you can type the input. The output
tab in NetBeans (at the bottom) looks as follows when the program has
finished (the user inputs the name "John").
run:
Who is greeted: John
Hi John
BUILD SUCCESSFUL (total time: 6 seconds)
25
Next we will ask the user to give us his name and age. The program body is
included this time.
import java.util.Scanner;
public class NameAndAgeGreeting {
public static void main(String[] args) {
Scanner reader = new Scanner(System.in);
System.out.print("Your name: ");
String name = reader.nextLine(); // Reads a line from the users
keyboard
System.out.print("How old are you: ");
int age = Integer.parseInt(reader.nextLine()); // Reads a string variable
from the keyboard and transfers it to an integer
System.out.println("Your name is: " + name + ", and you are " + age + "
years old, nice to meet you!");
}
}
26
7.3 Summary
The program body for interaction with the user is as follows:
import java.util.Scanner;
public class ProgramName {
public static void main(String[] args) {
Scanner reader = new Scanner(System.in);
// code here
}
}
Reading a string:
String text = reader.nextLine();
Reading an integer:
int number = Integer.parseInt(reader.nextLine());
Exercise 8: Adder
27
Create a program that asks the user for two integers and then prints their
sum.
Type a number: 6
Type another number: 2
Sum of the numbers: 8
In this example the user input is marked in red color. From now on the
red color will indicate user input in examples.
Exercise 9: Divider
Create a program that asks the user for two integers and prints their
quotient. Make sure that 3 / 2 = 1.5. If the decimal part is missing, take
another look at 6.1 Floating point numbers (decimal numbers) to find the
solution.
Type a number: 3
Type another number: 2
Division: 3 / 2 = 1.5
28
import java.util.Scanner;
import nhlstats.NHLStatistics;
public class Mainprogram {
public static void main(String[] args) throws Exception {
Scanner reader = new Scanner(System.in);
System.out.println("Top ten by points");
NHLStatistics.sortByPoints();
NHLStatistics.top(10);
}
}
It will print (this was the situation on the 9th of January 2012):
Top ten by points
Henrik Sedin
Phil Kessel
Claude Giroux
VAN
TOR
43 11 + 38= 49 36
41 24 + 24= 48 10
PHI
36 18 + 30= 48 16
Joffrey Lupul
TOR
41 19 + 28= 47 36
Daniel Sedin
VAN
42 18 + 29= 47 32
Steven Stamkos
TBL
40 28 + 17= 45 34
Marian Hossa
CHI
41 17 + 27= 44 14
Evgeni Malkin
PIT
33 16 + 28= 44 30
31
Jordan Eberle
Jason Pominville
EDM
41 17 + 26= 43 6
BUF
41 14 + 29= 43 8
The name, abbreviation of the club, matches played, assists, points and
penalties of players are printed.
The first command NHLStatistics.sortByPoints() sorts the list of NHL
players by the points they have gathered. The second command
NHLStatistics.top(10); prints the ten first players from the list. Any
integer can be given as a parameter.
Similarly the players can be printed ordered by the goals or assists they
have made, or by penalty minutes they have been given. First, we call the
command to sort the players:
NHLStatistics.sortByPoints();
NHLStatistics.sortByGoals();
After that the players are printed with the command top using the
number of players to be printed as its parameter.
32
named Teemu
The component can also print the statistics of all players in a club:
NHLStatistics.teamStatistics("NYR"); // Statistics of New York Rangers
The order of the printed club statistics can be changed using a sortBy...()
first.
The name of the club must be given using the official three letter
abbreviation. You can check the abbreviations here . The statistics
component prints a list of the available abbreviations if you request the
statistics of an invalid club.
Create a program that does the following tasks into the main program
body. The tasks must be done in exactly the same order as listed below.
Do the tasks in the program body one after another without deleting
tasks you have already done.
33
Note: When you first run the program, the execution might take a while
because the information is downloaded from the web. Execution should
be quick after the first run.
The program must do the following:
Print the top ten players based on goals
Print the top 25 players based on penalty amounts
Print the statistics for Sidney Crosby
Print the statistics for Philadelphia Flyers (abbreviation: PHI). Note in
which order the players are printed in and why that might be!
Print the players in Anaheim Ducks (abbreviation: ANA) ordered by
points
After you have successfully submitted the exercise, you can play with the
code as you wish!
34
The condition (number > 10) evaluates into a truth value; either true or
false. The if command only handles truth values. The conditional statement
above is read as "if the number is greater than 10".
Note that the if statement is not followed by semicolon as the condition path
continues after the statement.
After the condition, the opening curly brace { starts a new block, which is
executed if the condition is true. The block ends with a closing curly brace }.
Blocks can be as long as desired.
The comparison operators are:
> Greater than
>= Greater than or equal to
< Less than
<= Less than or equal to
== Equals
!= Not equal
35
36
In the example above the boolean (i.e. a truth value) variable isGreater now
includes the truth value false.
A boolean variable can be used as a condition in a conditional sentence.
int first = 1;
int second = 3;
boolean isLesser = first < second;
if (isLesser) {
System.out.println(first + " is less than " + second + "!");
}
1 is less than 3!
37
8.2 else
If the truth value of the comparison is false, another optional block can be
executed using the else command.
int number = 4;
if (number > 5) {
System.out.println("Your number is greater than five!");
} else {
System.out.println("Your number is equal to or less than five!");
}
38
8.3 else if
40
If there are more than two conditions for the program to check, it is
recommended to use the else if command. It works like the else command,
but with an additional condition. else if comes after the if command. There
can be multiple else if commands.
int number = 3;
if (number == 1) {
System.out.println("The number is one.");
} else if (number == 2) {
System.out.println("The number is two.");
} else if (number == 3) {
System.out.println("The number is three!");
} else {
System.out.println("Quite a lot!");
}
The number is three!
Let us read out loud the example above: If number is one, print out "The
number is one.". Otherwise if the number is two, print out "The number is
two.". Otherwise if the number is three, print out "The number is three!".
Otherwise print out "Quite a lot!".
Strings cannot be compared using the equality operator (==). For string
comparison, we use the equals. command, which is always associated with
the string to compare.
String text = "course";
if (text.equals("marzipan")) {
System.out.println("The variable text contains the text marzipan");
} else {
System.out.println("The variable text does not contain the text
marzipan");
}
The equals command is always attached to the string variable with a dot in
between. A string variable can also be compared to another string variable.
String text = "course";
String anotherText = "horse";
if (text.equals(anotherText)) {
System.out.println("The texts are the same!");
} else {
System.out.println("The texts are not the same!");
}
42
When comparing strings, it is crucial to make sure that both string variables
have been assigned some value. If a value has not been assigned, the
program execution terminates with a NullPointerException error, which
means that variable has no value assigned to it (null).
Exercise 17: Greater number
Create a program that asks the user for two numbers and prints the
greater of those two. The program should also handle the case in which
the two numbers are equal.
Example outputs:
Type the first number: 5
Type the second number: 3
Greater number: 5
Type the first number: 5
Type the second number: 8
Greater number: 8
Type the first number: 5
Type the second number: 5
The numbers are equal!
43
Grade
029
failed
3034
3539
4044
4549
5060
Example outputs:
Type the points [0-60]: 37
Grade: 2
Type the points [0-60]: 51
Grade: 5
44
45
Next up is the OR operation ||, which will be used to check if the value is less
than 0 or greater than 100. The condition evaluates to true if the value
fulfills either condition.
System.out.println("Is the number less than 0 or greater than 100?");
int number = 145;
if (number < 0 || number > 100) {
System.out.println("Yes! :)");
} else {
System.out.println("Nope :(")
}
Is the number less than 0 or greater than 100?
Yes! :)
System.out.println("Yes")
}
Is the text equal to 'milk'?
No!
Password
alex
mightyducks
emily
cat
The program should check for the username and password as follows:
Type your username: alex
Type your password: mightyducks
You are now logged into the system!
48
Note: Remember that you cannot compare strings with the == operation!
Exercise 21: Leap year
A year is a leap year if it is divisible by 4. But if the year is divisible by 100,
it is a leap year only when it is also divisible by 400.
Create a program that checks whether the given year is a leap year.
Type a year: 2011
The year is not a leap year.
Type a year: 2012
The year is a leap year.
Type a year: 1800
The year is not a leap year.
49
9. Introduction to loops
Conditional statements allow us to execute different commands based on
the conditions. For example, we can let the user login only if the username
and password are correct.
In addition to conditions we also need repetitions. We may, for example,
need to keep asking the user to input a username and password until a valid
pair is entered.
The most simple repetition is an infinite loop. The following code will print
out the string I can program! forever or "an infinite number of times":
while (true) {
System.out.println("I can program!");
}
In the example above, the while (true) command causes the associated
block (i.e. the code between the curly braces {}) to be looped (or repeated)
infinitely.
50
We generally do not want an infinite loop. The loop can be interrupted using
e.g. the break command.
while (true) {
System.out.println("I can program!");
System.out.print("Continue? ('no' to quit)? ");
String command = reader.nextLine();
if (command.equals("no")) {
break;
}
}
System.out.println("Thank you and see you later!");
Now the loop progresses like this: First, the program prints I can program!.
Then, the program will ask the user if it should continue. If the user types
no, the break command is executed and the loop is interrupted and Thank
you and see you again! is printed.
I can program!
Continue? ('no' to quit)?yeah
I can program!
Continue? ('no' to quit)? jawohl
I can program!
51
Many different things can be done inside a loop. Next we create a simple
calculator, which performs calculations based on commands that the user
enters. If the command is quit, the break command will be executed to end
the loop. Otherwise two numbers are asked. Then, if the initial command
was sum, the program calculates and prints the sum of the two numbers. If
the command was difference, the program calculates and prints the
difference of the two numbers. If the command was something else, the
program reports that the command was unknown.
System.out.println("welcome to the calculator");
while (true) {
System.out.print("Enter a command (sum, difference, quit): ");
String command = reader.nextLine();
if (command.equals("quit")) {
break;
}
System.out.print("enter the numbers");
int first = Integer.parseInt(reader.nextLine());
int second = Integer.parseInt(reader.nextLine());
52
if (command.equals("sum") ) {
int sum = first + second;
System.out.println( "The sum of the numbers is " + sum );
} else if (command.equals("difference")) {
int difference = first - second;
System.out.println("The difference of the numbers is " + difference);
} else {
System.out.println("Unknown command");
}
}
System.out.println("Thanks, bye!");
Right!
The secret is: jryy qbar!
Exercise 22.2: Asking for the password until the user gives the
correct one
54
Modify the program so that it asks the user to type a password until it gets
the correct one. Implement this using a while-true loop statement. The
loop statement can be interrupted if and only if the entered password
matches the value of the password variable.
Type the password: turnip
Wrong!
Type the password: beetroot
Wrong!
Type the password: carrot
Right!
55
The secret above has been encrypted using the Rot13 algorithm. During
this course we will implement our own encryption program.
Exercise 23: Temperatures
You will get the Graph component along with the exercise template. Graph
draws graphs based on numbers that are given to it. You can give it
numbers as follows:
Graph.addNumber(13.0);
56
We will continue using the NHL component introduced earlier and create
a program that the user can use to query for statistics.
The program is structured similarly to the Calculator example program
above. The program body is as follows:
public static void main(String[] args) throws Exception {
Scanner reader = new Scanner(System.in);
System.out.println("NHL statistics service");
while (true) {
System.out.println("");
System.out.print("command (points, goals, assists, penalties, player,
club, quit): ");
String command = reader.nextLine();
if (command.equals("quit")) {
break;
}
if (command.equals("points")) {
// print the top ten playes sorted by points
} else if (command.equals("goals")) {
// print the top ten players sorted by goals
} else if (command.equals("assists")) {
// print the top ten players sorted by assists
} else if (command.equals("penalties")) {
57
}
}
}
The program asks the user to give commands and then executes the
operation that is associated with the given command. The commands are:
points, goals, assists, penalties, player, club, quit.
You should write code in the parts marked with comments.
Here is an example demonstrating the program in action:
NHL statistics service
command (points, goals, assists, penalties, player, club): assists
Henrik Sedin
VAN
43 11 + 38= 49 36
Erik Karlsson
OTT
43 6 + 35= 41 24
58
Claude Giroux
PHI
36 18 + 30= 48 16
Pavel Datsyuk
DET
41 13 + 30= 43 10
Brian Campbell
FLA
42 3 + 30= 33 4
Daniel Sedin
VAN
Jason Pominville
42 18 + 29= 47 32
BUF
Nicklas Backstrom
Joffrey Lupul
Evgeni Malkin
41 14 + 29= 43 8
WSH
38 13 + 29= 42 22
TOR
41 19 + 28= 47 36
PIT
33 16 + 28= 44 30
CGY
43 12 + 21= 33 32
CAR
40 4 + 19= 23 30
DET
41 13 + 30= 43 10
Johan Franzen
DET
41 16 + 20= 36 34
Valtteri Filppula
DET
40 14 + 21= 35 10
Henrik Zetterberg
DET
41 8 + 24= 32 14
59
Note: When you first run the program, the execution might take a while
because the information is downloaded from the internet. Execution
should be quick after the first run.
Week 2
System.out.println(age); // prints 2
The age = age + 1 statement increments the value of the variable age by one.
It is also possible to increment a variable by one as bellow:
60
int age = 1;
System.out.println(age); // prints 1
age++;
System.out.println(age); // prints 2
Another example:
int length = 100;
System.out.println(length); // prints 100
length = length - 50;
System.out.println(length); // prints 50
length = length * 2;
System.out.println(length); // prints 100
length = length / 4;
System.out.println(length); // prints 25
length--;
System.out.println(length); // prints 24
if (read == 0) {
break;
}
// DO SOMETHING HERE
System.out.println("Sum now: " + sum);
}
System.out.println("Sum in the end: " + sum);
63
The example above can be read "as long as the variable number is less than
11, print the variable and increment it by one".
Above, the variable number was incremented in each iteration of the loop.
Generally the change can be anything, meaning that the variable used in the
condition does not always need to be incremented. For example:
64
66
Tip: Assign the variable you use in the condition of the loop a initial value
of 100 and then subtract one on each iteration of the loop.
Exercise 29: Even numbers
Create a program that prints all even numbers between 2 and 100.
2
4
6
(many rows of numbers here)
96
98
100
67
1
2
3
4
5
Tip: The number you read from the user now works as the upper limit in
the condition of the while statement. Remember that in Java a <= b means
a is less than or equal to b.
Exercise 31: Lower limit and upper limit
Create a program that asks the user for the first number and the last
number and then prints all numbers between those two.
First: 5
Last: 8
5
6
7
8
If the first number is greater than the last number, the program prints
nothing:
68
First: 16
Last: 12
Note: Remember that the lower and upper limits can also be negative!
length += 100;
// error!
int result = 0;
int i = 0;
while (i < 4) {
result = result + 3;
i++; // means the same as i = i + 1;
}
In the beginning result = 0. During the loop, the value of the variable is
incremented by 3 on each iteration. Because there are 4 iterations, the value
of the variable is 3*4 in the end.
Using the assignment operator introduced above, we can achieve the same
behavior as follows:
int result = 0;
int i = 0;
while (i < 4) {
result += 3; // this is the same as result = result + 3;
i++;
Example outputs:
First: 3
Last: 5
The sum 12
First: 2
Last: 8
The sum is 35
74
condition for the while loop can be any expression that results in a boolean
(truth value).
System.out.println("Type your age: ");
int age = Integer.parseInt(reader.nextLine());
while (age < 5 || age > 85) { // age less than 5 OR greater than 85
System.out.println("You are lying!");
if (age < 5) {
System.out.println("You are so young that you cannot know how to
write!");
} else if (age > 85) {
System.out.println("You are so old that you cannot know how to use a
computer!");
}
System.out.println("Type your age again: ");
age = Integer.parseInt(reader.nextLine();
}
System.out.println("Your age is " + age);
The program could also have been implemented using the good old while
(true) structure:
76
77
This set of exercises will form one larger program when put together. We
create the program by adding features exercise by exercise. If you do not
finish all the exercises you can still send them to be reviewed by the
exercise robot. To do that, click the "submit" button, which has a picture
of an arrow and is located on the right of the testing button. Even though
the exercise robot complains about tests in the incomplete exercises, you
will still get points for the parts you have completed.
Note: from now on every sub-exercise of a larger exercise (like 36.1) has
the same value as an exercise without sub-exercises. It means that
exercise 36 as a whole corresponds to five normal exercises.
Exercise 36.1: Reading numbers
Create a program that asks the user to input numbers (integers). The
program prints "Type numbers until the user types the number -1. When
the user types the number -1, the program prints "Thank you and see you
later!" and ends.
Type numbers:
5
2
4
-1
Thank you and see you later!
78
79
4
-1
Thank you and see you later!
The sum is 11
How many numbers: 3
Average: 3.666666666666
Even numbers: 2
Odd numbers: 1
execute the whole program after almost every new line of code you write.
This enables you to be sure that your solution is going in the right and
working direction.
12. Methods
We have so far used many different commands of Java: assignment,
calculations, comparison, if structures and while structures. We have been
using a "command" System.out.println() to print text. We can also count the
maximum of two numbers with the help of the "command" Math.max(). We
are also familiar with reader.nextLine(), usually seen together with
Integer.parseInt().
If we take a closer look, we notice that those commands differ from if and
while (etc). The first difference is that after the command there are brackets
() and sometimes an input for the command inside those brackets. Actually,
the commands ending with brackets are not called commands, but
methods.
Technically speaking, a method is a piece of code that can be called from
different places of the program code. The line of code System.out.println("I
am a parameter given to the method!") means that we call a method that
actually handles the printing. After the method has been executed we go
back to where we called the method, and continue executing. The input
given to the method inside the brackets is called a method parameter.
82
In addition to a parameter, the method can also have a return value, for
example, a familiar line of code:
int number = Integer.parseInt( reader.nextLine() );
includes two method calls. First the inner method reader.nextLine is called.
That method has the integer typed by the user as a return value. Next the
outer method Integer.parseInt is called. As a parameter for that method
there is the string of characters that was received from the reader.nextLine
method as a return value. The return value for the method Integer.parseInt
is the string of characters transformed into an integer (whole number).
Method names also seem to include a dot, for example reader.nextLine().
Actually the method name starts after the dot, here it is nextLine(). The first
part of the command that comes before the dot shows whose method is in
question. Here the method belongs to the reader, which means that we have
the reader's method nextLine. Later we will learn more precisely about the
owner of the method (or the name on the left side of the dot). An attentive
reader will notice that the method System.out.println() has two dots. Here,
the method name is println and System.out is the owner of the method.
Roughly System.out means the computer monitor.
This far we have been using ready-made methods from Java libraries. Next
we will learn how to create our own methods.
This far we have been using a programming style where code is written
(and read and executed) from top to bottom.
It was mentioned before that "a method is a piece of code that can be called
from different places of the program code". Ready-made methods of Java
have been used since our very first program.
In addition to using these ready-made methods programmers can write
their own methods for programs to call. In the real world, it is really
exceptional if the program does not include any self-written methods. From
now on almost every program we create during this course will include selfwritten methods.
The methods are written in the program body outside the main's braces ( {
and } ) but still inside the outermost braces, for example like this: :
import java.util.Scanner;
public class ProgramBody {
public static void main(String[] args) {
Scanner reader = new Scanner(System.in);
// program code
}
// self-written methods
}
Let us create a method greet.
84
85
the method is called. Our method greet only writes one line of text to the
screen.
It is easy to call a self-written method. It happens by writing the method
name, brackets () and a semicolon. In the next example main (or the main
program) calls for our method, first once and then several times.
import java.util.Scanner;
public class ProgramBody {
public static void main(String[] args) {
Scanner reader = new Scanner(System.in);
// program code
System.out.println("Let us try if we can get to the method world:");
greet();
System.out.println("It seems like we can, let us try again:");
greet();
greet();
greet();
}
// self-written methods
public static void greet() {
System.out.println("Greetings from the world of methods!");
86
}
}
When the program is executed, we see the following output:
Let us try if we can get to the method world:
Greetings from the world of methods!
It seems like we can, let us try again:
Greetings from the world of methods!
Greetings from the world of methods!
Greetings from the world of methods!
What is noteworthy here is the execution order of the program code. The
execution starts with the main program's (or main's) lines of code, from top
to bottom, one by one. When the line of code to be executed happens to be a
method call, the lines of code in the method block are executed again one by
one. When the method block ends, the execution continues from the place
where the method was called. To be exact, the execution continues from the
next line after the original method call.
To be even more exact, the main program is also a method. When the
program starts, the operation system calls for the main method. That means
that the main method is the starting point of the program and the execution
starts from the first code line of main. The program execution ends when it
reaches the end of main.
87
From now on when we introduce methods, we will not point out that they
need to be written in the right place inside the program code. For example,
a method cannot be defined inside another method.
Exercise 37: Printing out text
Create a method printText that prints the following string of characters:
"In the beginning there were the swamp, the hoe and Java." and a line
break.
public static void main(String[] args) {
printText();
}
public static void printText() {
// write your code here
}
88
Develop the program by adding the following feature: the main program
should ask the user how many times the text should be printed (meaning
how many times the method is called).
public static void main(String[] args) {
// ask the user how many times the text should be printed
// use the while structure to call the printText method several times
}
public static void printText() {
// write your code here
}
89
Note: you should print the assisting question How many? on its own line!
90
More complicated expressions can also be used as a parameter for our selfwritten methods, the same way we used them together with the readymade System.out.println() method.
public static void main(String[] args) {
String name1 = "Anne";
String name2 = "Green";
greet( name1 + " " + name2 );
int age = 24;
greet("John " + age + " years");
}
Hi Anne Green, greetings from the world of methods!
Hi John 24 years, greetings from the world of methods!
In both cases the method has only one parameter. The value for the
parameter is calculated before calling the method. In the first case the
parameter value comes from the String concatenation (a cool word that
means putting the text together) name1 + " " + name2. The value for the
concatenation is Anne Green. In the second case we get the parameter value
from the String concatenation "John " + age + " years".
91
92
}
public static void greetManyTimes(String name, int times) {
int i = 0;
while ( i < times ) {
greet(name);
i++;
}
}
public static void main(String[] args) {
greetManyTimes("Anthony", 3);
System.out.println("and");
greetManyTimes("Martin", 2);
}
Output:
Hi Anthony, greetings from the world of methods!
Hi Anthony, greetings from the world of methods!
Hi Anthony, greetings from the world of methods!
and
Hi Martin, greetings from the world of methods!
Hi Martin, greetings from the world of methods!
93
94
Note: you can return exercises that contain many parts to the exercise
robot even though you are not finished with all parts. In that case, the
robot complains about tests in the unfinished parts of the exercise, but
gives you points for all tests that pass.
Exercise 39.2: Printing a square
Create a method printSquare(int sideSize) that prints a square using our
previous method printStars. The method call printSquare(4), for example,
prints the following:
****
****
****
****
Note: in order to complete the exercise it is not enough that the outprint
looks good. Inside the printSquare method the printing must be done
using the printStars method.
When you are in the middle of making your program, you should verify
the correctness of your methods by writing some test code into your main
method.
Exercise 39.3: Printing a rectangle
95
96
97
***
*****
*******
***
***
99
Guess a number: 12
The number is greater
Guess a number: 66
The number is lesser
Guess a number: 42
Congratulations, your guess is correct!
hangman.gameOn()
Shows if the game is on
hangman.printStatus()
Prints the game status. Shows how many guesses have been made and
the letters that have not been used yet.
hangman.printWord()
Prints the word the user tries to guess. The letters that have not been
guessed yet are hidden as question marks, like "v?ri?ble".
hangman.printMan()
Prints the Hangman.
hangman.guess(String letter)
Guesses the letter that is given as a parameter.
You will get a program body from the exercise robot. It already contains
some functionalities:
Scanner reader = new Scanner(System.in);
Hangman hangman = new Hangman();
System.out.println("************");
System.out.println("* Hangman *");
System.out.println("************");
System.out.println("");
printMenu();
102
System.out.println("");
// ADD YOUR IMPLEMENTATION HERE
System.out.println("Thank you for playing!");
In addition to the program body, you will get the method called
printMenu:
public static void printMenu() {
System.out.println(" * menu *");
System.out.println("quit - quits the game");
System.out.println("status - prints the game status");
System.out.println("a single letter uses the letter as a guess");
System.out.println("an empty line prints this menu");
}
103
In the next set (week) of exercises, we will find out what this peculiarlooking condition for ending the loop is about.
This far the program should produce the following output:
************
* Hangman *
************
* menu *
quit - quits the game
status - prints the game status
a single letter uses the letter as a guess
an empty line prints this menu
Type a command:
do not quit
104
Type a command:
quit
Thank you for playing!
quit
Thank you for playing!
Type a command:
c
The letter c was found in the word!
Type a command:
quit
Thank you for playing!
107
If the user has not typed the command quit, you should call the Hangman
game commands hangman.printMan() and hangman.printWord() at the
end of the loop.
...
Type a command:
a
The letter a is not in the word.
____
|
|
|
|
/|\
Word to be guessed: ????
Type a command:
m
The letter m was found in the word!
____
|
|
|
|
/|\
Word to be guessed: m???
108
Type a command:
quit
Thank you for playing!
Week 3
number = number + 3;
System.out.println("Method parameter number holds the value: " +
number);
}
In the program above the method addThree has a parameter called number.
This parameter is copied (duplicated) for the method to use. When the
program above is executed we see the following output:
Main program variable number holds the value: 1
Method parameter number holds the value: 1
Method parameter number holds the value: 4
Main program variable number holds the value: 1
The number we gave as a parameter to the method was copied for the
method to use. If we would like the main program to be able to use the new
value generated by the method, the method needs to return that value.
When defining a method that returns a value, we also have to define the
type of the return value. We can define the type of the return value by
writing it just before the name of the method. Next, we have a method that
always returns the number 10 (type int). Returning a value is accomplished
with the command return:
public static int alwaysReturnTen() {
return 10;
}
If we want to use the returned value later, we have to catch the return value
and store it into a variable:
public static void main(String[] args) {
int number = alwaysReturnTen();
System.out.println( "method returned the number " + number );
}
The return value of the method is assigned to a variable of type int just like
any other integer. The return value can also be a part of a sentence:
double number = 4 * alwaysReturnTen() + (alwaysReturnTen() / 2) - 8;
System.out.println( "calculation total " + number );
112
Every variable type we have seen this far can be used as a return value:
public static void methodThatReturnsNothing() {
// method body
}
public static int methodThatReturnsInteger() {
// method body, needs a return statement
}
public static String methodThatReturnsText() {
// method body, needs a return statement
}
public static double methodThatReturnsFloatingpoint() {
// method body, needs a return statement
}
If the method is defined to have a return value, it also has to return a value.
The following method is incorrect:
public static String wrongMethod() {
System.out.println("I tell you that I will return a String but I do not!");
}
113
116
Example output:
sum: 14
Example output:
Least: 2
118
Example output:
Greatest: 7
Program output:
119
average: 3.5
Make sure you remember how you can transform a whole number (int)
into a decimal number (double)!
120
121
122
Note! Your program should be structured so that you put the search for
the first character in its own method: public static char
firstCharacter(String text). The tests will be testing both the method
firstCharacter and the program overall
Exercise 49: Last character
123
Create a program that asks for the user's name and gives the last
character.
Type your name: Paul
Last character: l
Type your name: Catherine
Last character: e
Note! Your program should be structured so that you put the search for
the last character in its own method: public static char
lastCharacter(String text). The tests will be testing both the method
lastCharacter and the program overall.
Exercise 50: Separating first characters
Create a program that asks for the user's name and gives its first, second
and third characters separately. If the name length is less than three, the
program prints nothing. You do not need to create methods in this
exercise.
Type your name: Paul
1. character: P
2. character: a
3. character: u
124
Note: watch closely at the output in this and the following exercise. The
print needs to contain a space after the dot and the colon!
Exercise 51: Separating characters
Create a program that asks for the user's name and gives its characters
separately. You do not need to create methods in this exercise.
Type your name: Paul
1. character: P
2. character: a
3. character: u
4. character: l
125
6. character: r
7. character: i
8. character: n
9. character: e
127
Note: Make your program outputs (prints) match exactly the example
above!
Exercise 56: Reversing text
129
Create the method reverse that puts the given string in reversed order.
Use the following program body for the method:
public static String reverse(String text) {
// write your code here
}
public static void main(String[] args) {
System.out.print("Type in your text: ");
String text = reader.nextLine();
System.out.println("In reverse order: " + reverse(text));
}
130
Program output:
Type a text: example
elpmaxe
16. Object
Strings and integers have some differences. Integers are "just values", they
can be used in calculations and they can be printed on the screen:
int x = 1;
int y = 2;
y = 3*x;
System.out.println( "value of y now: " + y );
Strings are a bit "cleverer" and for example know how long they are:
String word1 = "Programming";
String word2 = "Java";
System.out.println( "String "+ word1 +" length: " + word1.length() );
131
Program output:
String Programming length: 11
String Java length: 4
We can determine the length by calling the String method length(). Strings
have other methods as well. Integers (or whole numbers, variables of type
int) have no methods at all. They do not "know" anything.
Strings are objects, or "something that has methods and a value". Later we
will see many other objects as well.
As we can see in the previous example, an object's methods are called by
adding a dot and a method call after the name of the object:
word1.length() // String object's name is word1 and its method length()
is called
word2.length() // String object's name is word2 and its method length()
is called
The method call is made explicitly to the object. In the above example, we
have two objects and first we call the length() method of the String object
word1 and then do the same for the object word2.
132
// ...
String word10;
This would be such a good-for-nothing solution that it does not almost need
an explanation -- think of this approach for a word count of 100 or 1000!
Just like other modern programming languages, Java gives us different tools
to store many objects neatly in our programs. Now, we take a closer look at
ArrayList, which is probably the most used object container in Java.
The following lines of code make use of an ArrayList that holds specifically
objects of type String. A couple of strings are stored into the list.
import java.util.ArrayList;
public class ListProgram {
public static void main(String[] args) {
ArrayList<String> wordList = new ArrayList<String>();
wordList.add("First");
wordList.add("Second");
}
}
In the above main program method, the first row creates a new ArrayList
called wordList, which can be used as a container for String variables. The
134
given as a parameter. Second, remove(3) removes the 4th String from the
list.
At the end of the example, the method contains is called. This method is
used for asking the list if it contains the string given as a parameter. If it
does, the method returns the value true.
Program output:
the number of teachers 6
first teacher on the list Anthony
third teacher on the list Paul
Barto is not on the teachers list
Note! The methods remove and contains assume that the objects stored in
the ArrayList do have an equals method. We will get back to this later in the
course.
137
teachers.add("Paul");
teachers.add("John");
teachers.add("Martin");
System.out.println( teachers.get(0) );
System.out.println( teachers.get(1) );
System.out.println( teachers.get(2) );
System.out.println( teachers.get(3) );
}
This solution works, but is really clumsy. What if there were more items in
the list? Or less? What if we would not know how many items there are?
First, we create a temporary version:
public static void main(String[] args) {
ArrayList<String> teachers = new ArrayList<String>();
teachers.add("Anthony");
teachers.add("Paul");
teachers.add("John");
teachers.add("Martin");
teachers.add("Matt");
int place = 0;
System.out.println( teachers.get(place) );
138
place++;
System.out.println( teachers.get(place) ); // place = 1
place++;
System.out.println( teachers.get(place) ); // place = 2
place++;
System.out.println( teachers.get(place) ); // place = 3
}
Using our old friend the while command, we can increment the variable
place by one until it gets too big:
public static void main(String[] args) {
ArrayList<String> teachers = new ArrayList<String>();
teachers.add("Anthony");
teachers.add("Paul");
teachers.add("John");
teachers.add("Martin");
teachers.add("Matt");
int place = 0;
while ( place < teachers.size() ) // remember why place <=
teachers.size() doesn't work?
System.out.println( teachers.get(place) );
place++;
139
}
}
Now, printing works regardless of the amount of items in the list.
Using a while loop, and "self indexing" the locations in the list, is usually not
the best way to go through a list. A much more recommended way is to use
the for-each loop described below.
17.3 for-each
Even though the command is usually referred to as for-each, the real name
of the command is only for. There are two versions of for, the traditional
and the "for-each". The latter is used now.
Going through items in an ArrayList with for-each is easy:
public static void main(String[] args) {
ArrayList<String> teachers = new ArrayList<String>();
teachers.add("Anthony");
teachers.add("Paul");
teachers.add("John");
teachers.add("Martin");
teachers.add("Matt");
for (String teacher : teachers) {
140
System.out.println( teacher );
}
}
As we can see, the indexes of the list can be ignored if we go through the
content of the list "automatically".
In the code block of the for command (inside { }) a variable teacher is used.
It is defined in the for row, on the left side of the colon. What happens is that
every item in the list teachers becomes the value of the variable teacher,
one by one. It means that when for is entered, the first teacher is Anthony,
the second execution of for makes the teacher become Paul etc.
Even though the for command might seem a bit strange at first, you should
definitely get used to use it!
Exercise 57: Words
Create a program that asks the user to input words until the user types in
an empty String. Then the program prints the words the user gave. Try the
for repetition sentence here. Use an ArrayList structure in your program.
ArrayList is defined like this:
ArrayList<String> words = new ArrayList<String>();
Type a word: Mozart
Type a word: Schubert
Type a word: Bach
141
142
System.out.println( teacher );
}
}
Output:
Anthony
Barto
John
Martin
Matt
Paul
We give the list as a parameter for the method Collections.sort. The import
line import java.util.Collections; or import java.util.*; needs to be at the
beginning of the program in order to get tools of Collections working in our
program.
Collections also includes other useful methods:
shuffle shuffles the list items, can be useful for example in games
reverse reverses the order of list items
Exercise 59: Words in reverse order
144
Create a program that asks the user to input words, until the user gives an
empty string. Then the program prints the words the user gave in
reversed order, the last word is printed first etc.
Type a word: Mozart
Type a word: Schubert
Type a word: Bach
Type a word: Sibelius
Type a word: Liszt
Type a word:
You typed the following words:
Liszt
Sibelius
Bach
Schubert
Mozart
print(list);
}
The type of the parameter is defined as an ArrayList of String variables the
same way a String ArrayList is defined:
Note that the name of the parameter can be anything:
public static void print(ArrayList<String> printed) {
for (String word : printed) {
System.out.println( word );
}
}
public static void main(String[] args) {
ArrayList<String> programmingLanguages = new ArrayList<String>();
programmingLanguages.add("Java");
programmingLanguages.add("Python");
programmingLanguages.add("Ruby");
programmingLanguages.add("C++");
ArrayList<String> countries = new ArrayList<String>();
countries.add("Finland");
countries.add("Sweden");
countries.add("Norway");
147
parameter
}
The program now includes two lists, programmingLanguages and countries.
First the printing method is given the list programmingLanguages. The
method print internally refers to the list given as a parameter with the
name printed! Next, the printing method is given the list countries. Now, the
method uses again the name printed referring to the parameter list.
Exercise 61: Amount of items in a list
Create the method public static int countItems(ArrayList<String> list)
that returns the number of the items in the list. Your method should not
print anything. Use a return statement to return the number as shown in
the following example:
ArrayList<String> list = new ArrayList<String>();
list.add("Hallo");
list.add("Ciao");
list.add("Hello");
System.out.println("There are this many items in the list:");
148
System.out.println(countItems(list));
programmingLanguages.add("Python");
programmingLanguages.add("Ruby");
programmingLanguages.add("C++");
print(programmingLanguages);
removeFirst(programmingLanguages);
System.out.println(); // prints an empty line
print(programmingLanguages);
}
Output:
Pascal
Java
Python
Ruby
C++
Java
Python
Ruby
150
C++
Similarly a method could, for example, add more strings to the list it
received as a parameter.
Exercise 62: Remove last
Create the method public static void removeLast(ArrayList<String> list),
which removes the last item from the list. Example code:
ArrayList<String> brothers = new ArrayList<String>();
brothers.add("Dick");
brothers.add("Henry");
brothers.add("Michael");
brothers.add("Bob");
System.out.println("brothers:");
System.out.println(brothers);
// sorting brothers
brothers.sort();
// removing the last item
removeLast(brothers);
151
System.out.println(brothers);
Example output:
brothers:
[Dick, Henry, Michael, Bob]
[Bob, Dick, Henry]
152
numbers.add(4);
numbers.add(8);
// tries to remove the number from the index 4, does not work as
expected!
numbers.remove(4);
// this removes the number 4 from the list
numbers.remove(Integer.valueOf(4));
}
numbers.remove(4) tries to remove the item in the index 4 from the list.
There are only 2 items in the list, so the command generates an error. We
must use a slightly more complicated command if the number 4 needs to be
removed: numbers.remove( Integer.valueOf(4) );
ArrayLists can also be used to store doubles (decimal numbers) and
characters (char variables). The lists can be defined as follows:
153
Program output:
154
The sum: 14
The sum: 24
155
Program output:
list.add(num3);
return list;
}
public static void main(String[] args) {
ArrayList<Integer> numbers = addNumbersToList(3, 5, 2);
for (int number : numbers) {
System.out.println( number );
}
}
}
Exercise 65: The lengths of the Strings
Create the method lengths that gets a list of String variables as a
parameter and returns an ArrayList that contains the lengths of the
Strings in the same order as the original list.
public static ArrayList<Integer> lengths(ArrayList<String> list) {
// write your code here
}
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<String>();
157
list.add("Hallo");
list.add("Moi");
list.add("Benvenuto!");
list.add("badger badger badger badger");
ArrayList<Integer> lengths = lengths(list);
System.out.println("The lengths of the Strings: " + lengths);
}
Program output:
158
Program output:
Program output:
(The average of the numbers is 3.5, so the sample variance is ((3 - 3.5) +
(2 - 3.5) + (7 - 3.5) + (2 - 3.5))/(4 - 1) ? 5,666667.)
Note while testing your program! Sample variance for a list that
contains only one item is not defined! It causes a division by zero in the
160
161
the value of firstGreater to false. The later if sentence selects which string to
print based on the truth value.
As a matter of fact, using a truth value in a conditional sentence is easier
than the description in the previous example. We can write the second if
sentence as follows:
if (firstGreater) { // means the same as firstGreater==true
System.out.println("num1 was greater");
} else {
System.out.println("num1 was not greater");
}
If we want to check if the boolean variable holds the value true, we do not
need to write ==true, just writing the name of the variable is enough!
If we want to check if the boolean variable holds the value false, we can
check that using the negation operation ! (exclamation mark):
if (!firstGreater) { // means the same as firstGreater==false
System.out.println("num1 was not greater");
} else {
System.out.println("num1 was greater");
}
Truth values come in especially handy when we want to write methods that
check for validity. Let us create a method that checks if the list it gets as a
parameter includes only positive numbers (here 0 is considered positive).
The method returns the information as a boolean (i.e. truth value).
public static boolean allPositive(ArrayList<Integer> numbers) {
boolean noNegative = true;
for (int number : numbers) {
if (number < 0) {
noNegative = false;
}
}
// if one of the numbers on the list had a value that is below zero,
noNegatives becomes false.
return noNegative;
}
The method has a boolean helper variable called noNegative. First we assign
the helper variable the value true. The method checks all numbers on the
list one by one. If at least one number is less than 0, we assign the helper
variable the value false. In the end the method returns the value of the
helper variable. If no negative numbers were found, it has the value true,
otherwise it has the value false.
163
if (allPositive(numbers)) {
System.out.println("all numbers are positive");
} else {
System.out.println("there is at least one negative number");
}
165
When we are going through the list of numbers and we find a negative
number, we can exit the method by returning false. If there are no negative
numbers on the list, we get to the end and therefore can return the value
true. We now got rid of the helper variable inside the method!
Exercise 68: Is the number more than once in the list?
Create the method moreThanOnce that gets a list of integers and an
integer (i.e. number) as parameter. If the number appears on the list more
than once the method returns true and otherwise false.
The program body is the following:
public static boolean moreThanOnce(ArrayList<Integer> list, int number)
{
// write your code here
}
public static void main(String[] args) {
Scanner reader = new Scanner(System.in);
ArrayList<Integer> list = new ArrayList<Integer>();
list.add(3);
list.add(2);
list.add(7);
list.add(2);
System.out.println("Type a number: ");
166
Type a number: 2
2 appears more than once
Type a number: 3
3 does not appear more than once.
167
Example outputs:
Week 4
This program of ours does not work. The reason is that the method cannot
access the main program variable number.
169
This is because main program variables are not visible to methods. More
generally: no method variable is visible to other methods. As the main
program main is also a method, this constraint holds for the main program
as well. The only way to give information to a method is through
parameters.
Let us try to fix the above example by passing the main program variable
number to the method as a parameter.
public static void main(String[] args) {
int number = 1;
addThree(number);
System.out.println(number); // prints 1, the value did not change
}
public static addThree(int number) {
number = number + 3;
}
Still, the program does not function the way we want. The method
parameters are different variables than the ones introduced in the main
program. In the previous example, the method increments a variable with
the same name as the main program variable. The parameter has the same
name, but is not the same as the main program variable number.
170
171
The method can still naturally pass information to the caller, which happens
by using a return value (i.e. using a return command to return a variable
with a value). We can get the previous example to work by changing the
code a little bit:
public static void main(String[] args) {
int number = 1;
number = addThreeAndReturn(number);
System.out.println(number); // prints 4, because number has the
method return value as its value
}
public static int addThreeAndReturn(int number) {
number = number + 3;
return number;
}
The method still uses the copy of the main program variable number. In the
main program, we assign the variable number the method return value as a
new value, so that we can get the change to take effect in the main program.
Note that the name of the method variable plays no role here. The code
works exactly the same regardless of the variable names. Here follows an
example:
172
We have now found out that the parameters in methods are different
variables than the variables introduced in the method call. Only the
parameter value gets copied from the caller to the method.
Unfortunately this is not the whole story. If a method gets an ArrayList as a
parameter, the method sees the original list and all the changes the method
makes will take effect everywhere.
public static void removeFirst(ArrayList<Integer> list) {
list.remove(0); // removes the number from index 0
}
173
Unlike a parameter of int type, a list will not be copied and therefore the
method makes changes to the original list given as a parameter.
The picture below will clarify the example. ArrayList does not live in an
imagined "box" like an int. The variable name in the example numbers is
only a reference that refers to the place where the ArrayList is. One way to
visualize this is that an ArrayList is connected with a wire. The name of the
ArrayList is a "wire", and the list itself is located "at the other end of the
wire". When we give the ArrayList to a method as a parameter, we actually
give the method a wire. When the method uses its parameter, it finds the
original list at the other end of this wire. Actually the main program and the
174
method do have separate wires, but both wires have the same original list at
the end of them and all the changes will be made directly to the original list.
During and after this week we will find out that many things in Java are
"connected with a wire".
Note that again the parameter name inside the method can be anything. It
does not need to be the same as the name in the main program (or other
method that calls it). In the example above, the method uses the name list
but the method caller sees the same list with a different name: numbers.
Now, you probably start to wonder why does the value of the parameter get
copied and the original variable stay intact when the parameter is of int
type, but the original list is given to the method when the parameter is of
ArrayList type? In Java only the values of primitive data types (which are
175
int, double, char, boolean and a couple of others that we have not yet
discussed) get copied to the method. When the method parameters are of
other types only the references are copied to the method. A reference is like
a "wire", therefore the method can access the list using it directly. The
variables that are not of primitive data types are of reference data types
and are "wired" just like the ArrayList in the previous example. The method
is given the wire and the method can access the parameter directly.
Exercise 70: Combining ArrayLists
Create the method public static void combine(ArrayList<Integer> first,
ArrayList<Integer> second) that inserts the items in a list called second to
a list called first. The order of the items can be anything and the same
item can appear in the list more than once. An example on using the
method:
ArrayList<Integer> list1 = new ArrayList<Integer>();
ArrayList<Integer> list2 = new ArrayList<Integer>();
list1.add(4);
list1.add(3);
list2.add(5);
list2.add(10);
list2.add(7);
combine(list1, list2);
176
We can use the method addAll provided by the ArrayList class to add one
list in another list. The list gets the other list, whose items are to be added,
as a parameter.
Exercise 71: Smart combining
Create the method smartCombine that works like the previous combine
method except that numbers can be on the list only once. This means that
the method adds a new number to the list only if the list does not already
contain that number. You might find the method contains from the
ArrayList class useful. You can use that method to check if a number is in
the list.
177
Beck: "I'm not a great programmer, I'm just good a programmer with great
habits."
[Update: previously both quotes were credited to Kent Beck. Our thanks go
to Esko Luontola for pointing out this mistake]:
We are now taking the first steps towards becoming good programmers.
numbers.remove(Integer.valueOf(3));
}
System.out.println("The numbers after removal:");
for (int number : numbers) {
System.out.println(number);
}
Even though the unindented code works, it is unpleasant to read. Let us
indent the code (you can get NetBeans to auto-indent your code by pressing
Alt+Shift+F) and separate logical parts with line breaks:
public static void main(String[] args) {
ArrayList<Integer> numbers = new ArrayList<Integer>();
numbers.add(4);
numbers.add(3);
numbers.add(7);
numbers.add(3);
System.out.println("The numbers in the beginning:");
// here we print numbers
for (int number : numbers) {
System.out.println(number);
}
// checks if the list contains the number 3
179
while (numbers.contains(Integer.valueOf(3))) {
numbers.remove(Integer.valueOf(3)); // if yes, it is removed
}
// we use a while structure to get all the threes removed!
System.out.println("The numbers after removal:");
// here we print numbers
for (int number : numbers) {
System.out.println(number);
}
}
Now, the code starts to make sense. For example, the printing and the
number removal are two logical parts, therefore they are separated with
line breaks. The code is airy and reading the code is much more pleasant.
There are even comments in the code to help the reader understand what
happens and where!
180
its own method. Then the printing method should be called from the main
program:
public static void main(String[] args) {
ArrayList<Integer> numbers = new ArrayList<Integer>();
numbers.add(4);
numbers.add(3);
numbers.add(7);
numbers.add(3);
System.out.println("The numbers in the beginning:");
// here we print numbers
print(numbers);
while (numbers.contains(Integer.valueOf(3))) {
numbers.remove(Integer.valueOf(3));
}
System.out.println("The numbers after removal:");
// here we print numbers
print(numbers);
}
public static void print(ArrayList<Integer> numbers) {
181
182
Kent Beck might be proud of what we have accomplished! The code is easy
to understand, easy to modify and does not include any copy-paste.
21.1 Object
We have already used many of the ready-made objects in Java. For example,
ArrayLists are objects. Each separate list consists of information related to
it; that is, the state of the object. Functionality is also contained in the
184
ArrayList objects: the methods by which the state of the object can be
altered. As an example, there are two ArrayList objects in the following
piece of code, cities and countries :
public static void main(String[] args) {
ArrayList<String> cities = new ArrayList<String>();
ArrayList<String> countries = new ArrayList<String>();
countries.add("Finland");
countries.add("Germany");
countries.add("Netherlands");
cities.add("Berliini");
cities.add("Nijmegen");
cities.add("Turku");
cities.add("Helsinki");
System.out.println("number of countries " + countries.size() );
System.out.println("number of cities " + cities.size() );
}
Both the countries object and the cities object live a life of their own. The
state of each is not related to the state of the other. For example, the state of
the countries object consists of the Strings "Finland", "Germany" and
"Netherlands" that are in the list, probably also the information of how
many countries are in the list.
185
21.2 Class
186
It is clear that all objects are not similar to one another. For example,
ArrayList objects differ drastically from String objects. All ArrayLists have
the same methods add, contains, remove, size, ... and respectively all String
objects have the same methods (substring, length, charAt, ...). Arraylist and
String objects do not have the same methods because they are different
types of objects.
The type of a certain group of objects is called a class. ArrayList is a class, as
are String, Scanner, and so forth. Objects, on the other hand, are instances of
classes.
Objects of the same class all have the same methods and a similar state. For
example, the state of an ArrayList object consists of elements inserted to the
list while the state of a String object consists of a string of characters.
187
way dictate the shape and size of it. The blueprints are the class, they define
the general characteristics of the objects created out of that class:
Individual objects, the houses in our analogy, are made from that same
blueprint. They are instances of the same class. The state of individual
objects, the attributes, can vary (color of walls, building material of the roof,
doors, windowsills, etc...). Here is one instance of a House object:
188
An object is always created from its class by calling the method - the
constructor - that creates the object with the command new. For example, a
new instance is created from the class Scanner by calling new Scanner(..):
Scanner reader = new Scanner(System.in);
Constructors take parameters the way any other method does.
Exercise 72: Accounts
You are handed a ready-made class Account along with your exercise files.
The object of the class Account represents a bank account that has a
balance (meaning some amount of money). The accounts are used as
follows:
Account bartosAccount = new Account("Barto's account",100.00);
Account bartosSwissAccount = new Account("Barto's account in
Switzerland",1000000.00);
System.out.println("Initial state");
System.out.println(bartosAccount);
System.out.println(bartosSwissAccount);
bartosAccount.withdrawal(20);
System.out.println("Barto's account balance is now:
"+bartosAccount.balance());
bartosSwissAccount.deposit(200);
189
192
194
}
}
The constructor always has the same name as the class. In the code above,
the class is Person and the constructor is public Person(String initialName).
The value the constructor receives as a parameter is in parentheses after
the name of the constructor. You can imagine the constructor as a method
that Java runs when an object is created with the command new
Person("Bob"); Whenever an object is created from a class, the constructor
of that class is called.
A few notes: within the constructor there is a command this.age = 0.
Through it, we set a value for this particular object; we define the internal
variable age of "this" object. Another command we use is this.name =
initialName;. Again, we give the internal variable called name the String that
is defined in the constructor. The variables age and name are automatically
visible in the constructor and elsewhere in the object. They are referred to
with the this prefix. Due to the private modifier, the variables cannot be
seen from outside the object.
One more thing: if the programmer does not create a constructor for her
class, Java will automatically create a default constructor for it. A default
constructor is a constructor that does nothing. So, if you for some reason do
not need a constructor you do not need to write one.
We already know how to create and initialize objects. However, objects are
useless if they cannot do anything. Therefore, objects should have methods.
Let us add to the Person class a method that prints the object on the screen:
public class Person {
private String name;
private int age;
public Person(String nameAtStart) {
this.age = 0;
this.name = nameAtStart;
}
public void printPerson() {
System.out.println(this.name + ", age " + this.age + " years");
}
}
As seen above, the method is written within the class. The method name is
prefixed with public void since it is assumed that users of the object should
be capable of using the method and the method should not return anything.
With objects the keyword static is not used in method definitions. Next
week, we will clarify the reason behind that.
Inside the method printPerson, there is a single line of code that uses the
object variables name and age. The prefix this is used to emphasize that we
196
are referring to the name and age of this object. All the object variables are
visible from all the methods of the object.
Let us create three persons and ask them to print themselves:
public class Main {
public static void main(String[] args) {
Person pekka = new Person("Pekka");
Person brian = new Person("Brian");
Person martin = new Person("Martin");
pekka.printPerson();
brian.printPerson();
martin.printPerson();
}
}
The output is:
Pekka, age 0 years
Brian, age 0 years
Martin, age 0 years
Exercise 73: Product
197
198
}
}
Output:
Pekka, age 0 years
Andrew, age 0 years
Pekka, age 2 years
Andrew, age 0 years
When born, both objects have age 0 due to the line this.age = 0; in the
constructor. The method becomeOlder of object pekka is called twice. As the
output shows, this causes the age of pekka to increase by two. It should be
noted that when the method becomeOlder is called in the object pekka, the
other object andrew is not touched at all and he remains at age 0. The state
of an object is independent of the other objects!
Also, the object methods can return a value to the caller of the method. Let
us define a method that can be used to ask for the age of a person:
public class Person {
// ...
public int getAge() {
return this.age;
200
}
}
Now the void in the method definition is replaced with int since the value
the method returns has the type integer. The following example
demonstrates, how the value returned by a method can be used:
public class Main {
public static void main(String[] args) {
Person pekka = new Person("Pekka");
Person andrew = new Person("Andrew");
pekka.becomeOlder();
pekka.becomeOlder();
andrew.becomeOlder();
System.out.println( "Age of Pekka: "+pekka.getAge() );
System.out.println( "Age of Andrew: "+andrew.getAge() );
int total = pekka.getAge() + andrew.getAge();
System.out.println( "Pekka and Andrew total of "+total+ " years old" );
}
201
}
Output:
Age of Pekka: 2
Age of Andrew: 1
Pekka and Andrew total of 3 years old
Exercise 74: Multiplier
Implement the class Multiplier that has:
a constructor public Multiplier(int number).
a method public int multiply(int otherNumber) that returns
otherNumber multiplied by number (i.e., the constructor parameter).
Example of usage:
Multiplier threeMultiplier = new Multiplier(3);
System.out.println("threeMultiplier.multiply(2): " +
threeMultiplier.multiply(2));
Multiplier fourMultiplier = new Multiplier(4);
System.out.println("fourMultiplier.multiply(2): " +
fourMultiplier.multiply(2));
202
System.out.println("threeMultiplier.multiply(1): " +
threeMultiplier.multiply(1));
System.out.println("fourMultiplier.multiply(1): " +
fourMultiplier.multiply(1));
Output
threeMultiplier.multiply(2): 6
fourMultiplier.multiply(2): 8
threeMultiplier.multiply(1): 3
fourMultiplier.multiply(1): 4
}
}
206
Output:
value: 100
value: 0
value: 0
Implement the method public void setInitial(), which returns the counter
to its initial value:
public class Main {
public static void main(String[] args) {
DecreasingCounter counter = new DecreasingCounter(100);
counter.printValue();
counter.decrease();
counter.printValue();
counter.decrease();
counter.printValue();
counter.reset();
counter.printValue();
counter.setInitial();
counter.printValue();
}
}
Output:
208
value: 100
value: 99
value: 98
value: 0
value: 100
Hint: add to the class a new object variable that remembers the initial
value of the counter
Exercise 76: Menu
In this assignment, we will implement a class Menu that holds
information about meals that are available in a cafeteria.
Our starting point is the following class skeleton:
import java.util.ArrayList;
public class Menu {
private ArrayList<String> meals;
public Menu() {
this.meals = new ArrayList<String>();
}
209
210
211
212
int i = 0;
while ( i < 30 ) {
bob.becomeOlder();
i++;
}
andy.becomeOlder();
System.out.println("");
if ( andy.isAdult() ) {
System.out.print("adult: ");
andy.printPerson();
} else {
System.out.print("minor: ");
andy.printPerson();
}
if ( bob.isAdult() ) {
System.out.print("adult: ");
bob.printPerson();
} else {
System.out.print("minor: ");
bob.printPerson();
}
}
213
int i = 0;
while ( i < 30 ) {
bob.becomeOlder();
i++;
}
andy.becomeOlder();
System.out.println("");
if ( andy.isAdult() ) {
System.out.println( andy.getName() + " is an adult" );
} else {
System.out.println( andy.getName() + " is a minor" );
}
if ( bob.isAdult() ) {
System.out.println( bob.getName() + " is an adult" );
} else {
System.out.println( bob.getName() + " is a minor" );
}
}
The print is starting to look pretty clean:
215
andy is a minor
bob is an adult
21.9 toString
We have been guilty of bad programming style; we have created a method
that prints an object, printPerson. The recommended way of doing this is by
defining a method that returns a "character string representation" of the
object. In Java, a method returning a String representation is called toString.
Let us define this method for person:
public class Person {
// ...
public String toString() {
return this.name + ", age " + this.age + " years";
}
}
The method toString works just like printPerson, but instead of printing it
the method returns the string representation. The call to the method can be
used for printing it if necessary.
The method is used in a slightly surprising way:
public static void main(String[] args) {
216
217
System.out.println( andy.toString() );
What happens is that the object is asked for its string representation. The
string representation the object is returned and is printed normally with
the System.out.println command.
We can get rid of the obsolete printObject method.
Exercise 77: Lyyra-card
The University of Helsinki students use a so-called Lyyra cards to pay for
their meals in student cafeterias. In this assignment, we implement the
class LyyraCard that simulates the Lyyra card.
Exercise 77.1: Class skeleton
Start by adding the class LyyraCard to your project.
Then implement the LyyraCard constructor that gets the starting balance
of the card as parameter. The card saves the balance in the object variable
balance. Implement also the toString method that returns a string of the
form "The card has X euros".
The skeleton of class LyyraCard looks like this:
public class LyyraCard {
private double balance;
public LyyraCard(double balanceAtStart) {
218
221
}
}
Above, the second call payGourmet does not alter the balance since there
is not enough money on the card for a gourmet lunch.
Exercise 77.4: Loading money to card
Add the LyyraCard the following method:
public void loadMoney(double amount) {
// write code here
}
The method should increase the balance of the card by the given amount.
However, the maximum balance on a card is 150 euros. In case the
balance after loading money would be more than that, it should be
truncated to 150 euros.
222
223
225
227
}
// ...
}
We added object variables height and weight, and methods setHeight and
setWeight that can be used to give values to the variables. In naming the
methods, we follow the Java convention to call a method that just sets a new
value to a variable setVariableName. This type of methods are usually called
setter methods.
The new methods in use:
public static void main(String[] args) {
Person matti = new Person("Matti");
Person john = new Person("John");
matti.setHeight(180);
matti.setWeight(86);
john.setHeight(175);
john.setWeight(64);
System.out.println(matti.getName() + ", body mass index: " +
matti.bodyMassIndex());
228
229
Now, the name height means the parameter height and the identically
named object variable is referred to as this.height. The following would not
work since the object variable height is not at all referred to in the code:
public void setHeight(int height) {
// DOES NOT WORK!
height = height;
// this just assigns the value of the parameter to the parameter itself
}
230
Note: you cannot return an integer value directly from the method
toString since the method should return a string. Integer variable value
can be turned into a string by prefixing it with an empty string: "" + value.
A main program that uses the counter:
public class Main {
public static void main(String[] args) {
232
Value: 3
Value: 4
Value: 0
value at start: 00
value: 01
value: 02
value: 03
value: 04
value: 05
value: 06
value: 07
value: 08
value: 09
value: 10
value: 11
value: 12
value: 13
value: 14
value: 00
value: 01
235
First you should implement the method getValue for the counters in the
class:
public int getValue() {
// write here code that returns the value
}
Then implement the clock in your main method in the following style:
public class Main {
public static void main(String[] args) {
BoundedCounter minutes = new BoundedCounter(59);
BoundedCounter hours = new BoundedCounter(23);
int i = 0;
while ( i < 121 ) {
System.out.println( hours + ":" + minutes); // the current time
printed
// advance minutes
// if minutes become zero, advance hours
i++;
}
}
}
236
Ensure that all works as expected when starting e.g. with time 23:59:50.
238
239
while ( true ) {
System.out.println( hours + ":" + minutes + ":" + seconds );
Thread.sleep(1000);
// put here the logic to advance your clock by one second
}
}
}
Now, the clock goes on forever and the value is updated as it should be,
once in a second. The clock estimates the duration of a second with the
command Thread.sleep(1000); The parameter in the command is the time
to sleep in milliseconds. In order to use the sleep command, you should do
an addition to the definition of main: public static void main(String[] args)
throws Exception {
You can end the eternal clock by pressing the red box in the NetBeans
console (i.e. the area in NB where the output of programs gets printed).
Important notes regarding the use of objects. You should definately
read these.
Object-oriented programming is mostly about turning concepts into their
own entities, or in other words forming abstractions. One might think that it
is pointless to create an object that only holds one number in it, and that the
same could be achieved with simple int variables. This is not the case. If a
clock consists of just 3 int variables that are then increased, the program
240
loses some human readability. It becomes more difficult to "see" what the
program is about. Earlier in the material we mentioned the advice of the
renown programmer Kent Beck: "Any fool can write code that a computer
can understand. Good programmers write code that humans can understand",
since the hand of a clock is its own clearly definable concept, it is a good
idea to create it an own class - BoundedCounter - for the sake of human
readability.
Turning a concept into a class of its own is a good idea for a lot of reasons.
Firstly, some details (i.e. when the counter makes a full round) can be
hidden inside the class (abstracted). Instead of writing an if-clause and an
assignment operation, it is enough that the user of the counter calls the
descriptively named method next(). In addition to clocks, the created
counter might be good for being used as a building block for other projects
too, so a class made from a clear concept can be very versatile. Another
huge advantage we gain by writing code this way, is that when the details of
the mechanics are hidden, they can be changed if need be.
We established that a clock contains three hands, it consists of three
concepts. Actually the clock itself is a concept too and next week we will
make the class Clock. Then, we can create distinct Clock objects. Clock will
be an object which functionality is based on "simpler" objects, the hands.
This is the grand idea of object-oriented programming: a program is built
out of small, clearly defined co-operating objects.
Now, we will take some careful first steps in the object world. Towards the
end of the course, objects will start to come to you naturally and the idea of
programs being built out of small, well defined, co-operating pieces - which at
241
this point might feel incomprehensible - will become something you will
take for granted.
A usage example:
public class Main {
public static void main(String[] args) {
NumberStatistics stats = new NumberStatistics();
stats.addNumber(3);
stats.addNumber(5);
stats.addNumber(1);
stats.addNumber(2);
System.out.println("Amount: " + stats.amountOfNumbers());
}
}
244
sum returns the sum of the added numbers (if no numbers added, the
sum is 0)
average returns the average of the added numbers (if no numbers added,
the average is 0)
The class skeleton now:
public class NumberStatistics {
private int amountOfNumbers;
private int sum;
public NumberStatistics() {
// initialize here the object variable amountOfNumbers
}
public void addNumber(int number) {
// code here
}
public int amountOfNumbers() {
// code here
}
public int sum() {
// code here
}
245
A usage example:
public class Main {
public static void main(String[] args) {
NumberStatistics stats = new NumberStatistics();
stats.addNumber(3);
stats.addNumber(5);
stats.addNumber(1);
stats.addNumber(2);
System.out.println("Amount: " + stats.amountOfNumbers());
System.out.println("sum: " + stats.sum());
System.out.println("average: " + stats.average());
}
}
sum: 11
average: 2.75
numbers and the third the odd numbers. Remember also that you should
not make any changes to class NumberStatistics!
The tests does not work if you do not create the objects in the order
mentioned above!!
The program should work as follows:
Type numbers:
4
2
5
2
-1
sum: 13
sum of even: 8
sum of odd: 5
22. Randomness
When programming, you may occasionally need to simulate random events.
Situations such as the unpredictability of weather, or surprising moves on
the AI's part in a computer game can often be simulated with random
number generators, running on a computer. In Java, there is a ready-made
class Random, which you can use in the following way:
248
import java.util.Random;
public class Randomizing {
public static void main(String[] args) {
Random randomizer = new Random(); // creates a random number
generator
int i = 0;
while (i < 10) {
// Generates and prints out a new random number on each round of
the loop
System.out.println(randomizer.nextInt(10));
i++;
}
}
}
In the code above, you first create an instance of the class Random with the
keyword new -- exactly as when creating objects implementing other
classes. An object of type Random has the method nextInt that can be given
an integer value as parameter. The method returns a random integer within
the range 0..(the integer given as parameter- 1).
The printout of this program could be as follows:
2
249
2
4
3
4
5
6
0
7
8
We will need floating point numbers, for example when dealing with
probability calculations. In computing, probabilities are usually calculated
with numbers within the range [0..1]. An object of the class Random can
return random floating point numbers with the method nextDouble. Let us
consider the following probabilities of weather conditions:
Sleet with the probability 0.1 (10%)
Snow with the probability 0.3 (30%)
Sunny with the probability 0.6 (60%)
Using the estimates above, let us create a weather forecaster.
import java.util.ArrayList;
import java.util.Random;
250
The method roll tells the result of a roll (which depends on the number
of its sides)
The frame of the program is as follows:
import java.util.Random;
public class Dice {
private Random random;
private int numberOfSides;
public Dice(int numberOfSides){
this.numberOfSides = numberofSides;
random = new Random();
}
public int roll() {
// we'll get a random number in the range 1-numberOfSides<
}
}
Expand the class Dice so that with each roll the dice returns a random
number between 1...number of sides. Here is a main program that tests
the dice:
254
255
Tip 1: this is how you turn the integer number into a character:
257
259
import java.util.ArrayList;
public class Program {
public static void main(String[] args) {
LotteryNumbers lotteryNumbers = new LotteryNumbers();
ArrayList<Integert> numbers = lotteryNumbers.numbers();
System.out.println("Lottery numbers:");
for (int number : numbers) {
System.out.print(number + " ");
}
System.out.println("");
}
}
260
Note! a number can be in one set of numbers only once (per draw of
course).
Exercise 83: Game logic for Hangman
Your Finnish friend designed a Hangman game that looks like the
following:
Your friend has programmed the user interface and also a skeleton for the
game logic. Now, she asks you to finish the remaining pieces of the game
logic.
The Finnish words sana, virheit, viesti, hvisit and arvatut (kirjaimet)
translate into word, (number of) faults, message, you lost and guessed
(letters) respectively.
261
Amongst other stuff, with TMC you get the following skeleton for the class
HangmanLogic
public class HangmanLogic {
private String word;
private String guessedLetters;
private int numberOfFaults;
public HangmanLogic(String word) {
this.word = word.toUpperCase();
this.guessedLetters = "";
this.numberOfFaults = 0;
}
public int numberOfFaults() {
return this.numberOfFaults;
}
public String guessedLetters() {
return this.guessedLetters;
}
public int losingFaultAmount() {
return 12;
}
262
l.guessLetter("A"); // correct
l.guessLetter("D"); // wrong
l.guessLetter("S"); // correct
l.guessLetter("F"); // wrong
l.guessLetter("D"); // This should not have any effect on the number of
faults since D was already guessed
System.out.println("guessed letters: "+l.guessedLetters());
System.out.println("number of faults: "+l.numberOfFaults());
guessing: A, D, S, F, D
guessed letters: ADSF
number of faults: 2
Now, you can test the game by using class Main. You can change the
guessed word by changing the constructor parameter of the game logic:
266
The game is played with the keyboard. You can end the game by pressing
x in the upper left corner of the game window.
Week 5
this.name = name;
this.age = 0;
this.weight = 0;
this.height = 0;
}
public void printPerson() {
System.out.println(this.name + " I am " + this.age + " years old");
}
public void becomeOlder() {
this.age++;
}
public boolean adult(){
if ( this.age < 18 ) {
return false;
}
return true;
}
public double weightIndex(){
double heightInMeters = this.height/100.0;
return this.weight / (heightInMeters*heightInMeters);
268
}
public String toString(){
return this.name + " I am " + this.age + " years old, my weight index is "
+ this.weightindex();
}
public void setHeight(int height){
this.height = height;
}
public int getHeight(){
return this.height;
}
public int getWeight() {
return this.weight;
}
public void setWeight(int weight) {
this.weight = weight;
}
public String getName(){
return this.name;
}
269
}
All person objects are 0 years old at creation, since the constructor sets it to
0:
public Person(String name) {
this.name = name;
this.age = 0;
this.weight = 0;
this.height = 0;
}
We also want to create a person so that in addition to name, can be given an
age as a parameter. This can be achieved easily, since multiple constructors
can exist. Let us make an alternative constructor. You do not need to
remove the old one.
public Person(String name) {
this.name = name;
this.age = 0;
this.weight = 0;
this.height = 0;
}
public Person(String name, int age) {
this.name = name;
270
this.age = age;
this.weight = 0;
this.height = 0;
}
Now, creating objects can be done in two different ways:
public static void main(String[] args) {
Person pekka = new Person("Pekka", 24);
Person esko = new Person("Esko");
System.out.println( pekka );
System.out.println( esko );
}
Pekka, age 24 years
Esko, age 0 years
The technique in which a class has two constructors is called constructor
overloading. A class can have multiple constructors, which are different
from one another according to parameter quanitities and/or types.
However, it is not possible to create two different constructors that have
exactly the same type of parameters. We cannot add a constructor public
Person(String name, int weight) on top of the old ones, since it is impossible
for Java to tell the difference between this one and the one in which the
integer stands for the age.
271
272
paste the code from the constructor below and that 0 is entered to the age
parameter.
System.out.println(pekka);
pekka.becomeOlder(10);
System.out.println(pekka);
}
Prints:
Pekka, age 24 years
Pekka, age 25 years
Pekka, age 35 years
Now, a person has two becomeOlder methods. The method that is chosen to
be run depends on the amount of parameters entered in to the method call.
The method becomeOlder can also be run through the method
becomeOlder(int years):
public void becomeOlder() {
this.becomeOlder(1);
}
public void becomeOlder(int years) {
this.age = this.age + years;
}
Exercise 84: Overloaded counter
274
275
object is 'at the end of a wire' that is attached to a variable named pekka.
The concept could be visualized like this:
Let us add to the program a variable person of the type Person and set its
starting value to pekka. What happens now?
public static void main(String[] args) {
Person pekka = new Person("Pekka", 24);
System.out.println( pekka );
Person person = pekka;
person.becomeOlder(25);
System.out.println( pekka );
}
Prints:
Pekka, age 24 years
Pekka, age 49 years
277
In the beginning, Pekka was 24 years old. Then a Person object at the end of
a wire attached to a Person variable is aged by 25 years and as a
consequence of that Pekka becomes older! What is going on here?
The command Person person = pekka; makes person refer to the same
object that pekka refers to. So, a copy of the object is not born, but instead
both of the variables refer to the same object. With the command Person
person = pekka; a copy of the wire is born. The same thing as a picture
(Note: in the picture p refers to the variable pekka, and h to the variable
person in the main program. The variable names have also been
abbreviated in some of the following pictures.):
person.becomeOlder(25);
System.out.println( pekka );
pekka = new Person("Pekka Mikkola", 24);
System.out.println( pekka );
}
Prints:
Pekka, age 24 years
Pekka, age 49 years
Pekka Mikkola, age 24 years
The variable pekka refers to one object, but then begins to refer to another.
Here is the situation after running the previous line of code:
279
280
Nothing refers to the second object. The object has become 'garbage'. Java's
garbace collector cleans up the garbage every now and then by itself. If this
did not happen, the garbage would pile up in the computer's memory until
the execution of the program is done.
We notice this on the last line whine we try to print 'nothing' (null) on the
last line:
Pekka, age 24 years
Pekka, age 49 years
Pekka Mikkola, age 24 years
null
What happens if we try to call a "nothing's" method, for example the
method weightIndex:
public static void main(String[] args) {
Person pekka = new Person("Pekka", 24);
281
System.out.println( pekka );
Person person = null;
System.out.println( person.weightIndex() );
}
Result:
Pekka, age 24 years
Exception in thread "main" java.lang.NullPointerException
at Main.main(Main.java:20)
Java Result: 1
Not good. This might be the first time in your life that you see the text
NullPointerException. But we can assure you that it will not be the last.
NullPointerException is an exception state, when we try to call methods of
an object with the value null.
282
People whose weight index exceeds a certain limit are accepted into the
Weight Watchers. The limit is not the same in all Weight Watchers
associations. Let us make a class corresponding to the Weight Watchers
association. As the object is being created, the lowest acceptance limit is
passed to the constructor as a parameter.
public class WeightWatchersAssociation {
private double lowestWeightIndex;
public WeightWatchersAssociation(double indexLimit) {
this.lowestWeightIndex = indexLimit;
}
}
Next we will create a method, with which we can check if a person is eligible
to the association, in other words we check if a person's weight index is
large enough. The method returns true if the person that is passed in as a
parameter is eligible and false if not.
public class WeightWatchersAssociation {
// ...
public boolean isAcceptedAsMember(Person person) {
if ( person.weightIndex() < this.lowestWeightIndex ) {
return false;
283
}
return true;
}
}
The method isAcceptedAsMember of the WeightWatchersAssociation object
gets a Person object as its parameter (or more accurately the wire to the
person), and then calls the method weightIndex of the person that it
received as a parameter.
In the following, is a test main program in which a person object matti and a
person object juhana is passed to the weight watchers association's method:
public static void main(String[] args) {
Person matti = new Person("Matti");
matti.setWeight(86);
matti.setHeight(180);
Person juhana = new Person("Juhana");
juhana.setWeight(64);
juhana.setHeight(172);
WeightWatchersAssociation kumpulasWeight = new
WeightWatchersAssociation(25);
284
if ( kumpulasWeight.isAcceptedAsMember(matti) ) {
System.out.println( matti.getName() + " is accepted as a member");
} else {
System.out.println( matti.getName() + " is not accepted as a member");
}
if ( kumpulasWeight.isAcceptedAsMember(juhana) ) {
System.out.println( juhana.getName() + " is accepted as a memberksi");
} else {
System.out.println( juhana.getName() + " is not accepted as a
member");
}
}
The program prints:
Matti is accepted as a member
Juhana is not accepted as a member
A few NetBeans-tips
All NetBeans-tips are found here
The automatic generating of constructors, getters and setters.
Go inside of the code block of the class, but outside of all methods and
simultaneously press Ctrl+Space. If your class, for example, has an
285
Next, an example where first the weight of Pekka and Brian is measured
and printed. Then Reformatory feeds Brian three times and after that the
weights are measured and printed again.
public static void main(String[] args) {
Reformatory eastHelsinkiReformatory = new Reformatory();
Person brian = new Person("Brian", 1, 110, 7);
Person pekka = new Person("Pekka", 33, 176, 85);
System.out.println(brian.getName() + " weight: " +
eastHelsinkiReformatory.weight(brian) + " kilos");
System.out.println(pekka.getName() + " weight: " +
eastHelsinkiReformatory.weight(pekka) + " kilos");
eastHelsinkiReformatory.feed(brian);
eastHelsinkiReformatory.feed(brian);
eastHelsinkiReformatory.feed(brian);
System.out.println("");
System.out.println(brian.getName() + " weight: " +
eastHelsinkiReformatory.weight(brian) + " kilos");
System.out.println(pekka.getName() + " weight: " +
eastHelsinkiReformatory.weight(pekka) + " kilos");
}
288
289
eastHelsinkiReformatory.weight(brian);
eastHelsinkiReformatory.weight(pekka);
System.out.println("total weights measured
"+eastHelsinkiReformatory.totalWeightsMeasured());
eastHelsinkiReformatory.weight(brian);
eastHelsinkiReformatory.weight(brian);
eastHelsinkiReformatory.weight(brian);
eastHelsinkiReformatory.weight(brian);
System.out.println("total weights measured
"+eastHelsinkiReformatory.totalWeightsMeasured());
}
In the last set of exercises, we implemented the class LyyraCard. The card
had methods for paying economical and gourmet lunches and a method
for loading money.
Last week's version of the card is however somehow problematic. The
card knew the lunch prices so that it could take the right price from the
balance if a lunch was paid. What if the lunch prices change? Or what if it
is decided that LyyraCards could also be used to purchase coffee? A
change like these would mean that all the existing LyyraCards should be
replaced with the new ones with the right prices and/or new methods.
This does not sound good at all!
A better solution is to store only the balance on the card and have all the
inteligence in a cash register.
We will soon program the cash register but let us start by completing the
"stupid" version of the Lyyra card. The card holds the balance and has
only two methods, public void loadMoney(double amount) that is already
implemented and public boolean pay(double amount) that you should
complete according to the instructions below:
public class LyyraCard {
private double balance;
public LyyraCard(double balance) {
this.balance = balance;
}
291
292
293
sold
private int gourmetSold;
public CashRegister() {
// at start the register has 1000 euros
}
public double payEconomical(double cashGiven) {
// the price of the economical lunch is 2.50 euros
// if the given cash is at least the price of the lunch:
// the price of lunch is added to register
// the amount of the sold lunches is incremented by one
// the method returns cashGiven - lunch price
// if not enough money is given, all is returned and nothing else
happens
}
public double payGourmet(double cashGiven) {
// the price of the gourmet lunch is 4.00 euros
// if the given cash is at least the price of the lunch:
294
295
theChange = unicafeExactum.payGourmet(4);
System.out.println("the change was " + theChange );
System.out.println( unicafeExactum );
}
}
should output:
the change was 7.5
the change was 2.5
the change was 0.0
money in register 1009.0 economical lunches sold: 2 gourmet lunches
sold: 1
Note: card payments do not affect the amount of money in the register!
Example main and output:
public class Main {
public static void main(String[] args) {
CashRegister unicafeExactum = new CashRegister();
297
298
To complete the assignment, extend the cash register with a method that
can be used to load cash to Lyyra Cards. When a certain amount is loaded
to the card, the amount stored in the register increases correspondingly.
Remember that the amount to be loaded needs to be positive! The method
skeleton:
public void loadMoneyToCard(LyyraCard card, double sum) {
// ...
}
299
unicafeExactum.loadMoneyToCard(cardOfJim, 100);
succeeded = unicafeExactum.payGourmet(cardOfJim);
System.out.println("payment success: " + succeeded);
System.out.println("the card balance " + cardOfJim.balance() + "
euros");
System.out.println( unicafeExactum );
}
}
money in register 1000.0 economical lunches sold: 0 gourmet lunches
sold: 0
money on the card 2.0 euros
payment success: false
payment success: true
the card balance 98.0 euros
money in register 1100.0 economical lunches sold: 0 gourmet lunches
sold: 1
301
The program gets a person object as its parameter (or more accurately a
reference to a person object, which is at 'the end of a wire') and then
compares its own age this.age to the age of the compared compared.age.
The implementation looks like this:
public class Person {
// ...
public boolean olderThan(Person compared) {
if ( this.age > compared.age ) {
return true;
}
return false;
}
}
Even though age is a private object variable, we can read the value of the
variable by writing compared.age. This is because private variables can be
read in all methods that the class in question contains. Note that the syntax
resembles the call of a method of an object. Unlike calling a method, we
refer to a field of an object, in which case we do not write the parentheses.
Within an object, the date is represented with three object variables. Let us
also make a method, which can compare whether the date is earlier than a
date that is given as a parameter:
public class MyDate {
private int day;
private int month;
private int year;
public MyDate(int day, int month, int year) {
this.day = day;
this.month = month;
this.year = year;
}
public String toString() {
return this.day + "." + this.month + "." + this.year;
}
public boolean earlier(MyDate compared) {
// first we'll compare years
if ( this.year < compared.year ) {
return true;
}
// if the years are the same, we'll compare the months
304
305
this.squareMeters = squareMeters;
this.pricePerSquareMeter = pricePerSquareMeter;
}
}
//
false
System.out.println( fourAndKitchenBronx.larger(twoRoomsBrooklyn) );
// true
307
// 71600
System.out.println(
fourAndKitchenBronx.priceDifference(twoRoomsBrooklyn) ); // 35400
308
// false
System.out.println(
fourAndKitchenBronx.moreExpensiveThan(twoRoomsBrooklyn) ); //
true
name:
Alan Turing (017635727)
Linus Torvalds (011288989)
Steve Jobs (013672548)
So the program asks for student information from the user until the user
gives a student an empty name. After the student info has been enteres, all
the students are printed. From each inputted name-studentnumber-pair,
the program should create a Student object. The program should store the
students in an ArrayList which is defined as follows:
ArrayList<Student> list = new ArrayList<Student>();
TIP: in the search you should iterate (using for or while) through the
student list and by using the method contains of String check if a student's
name (obtained with method getName) matches the search term.
}
And then let's test how the renewed Person class works:
public static void main(String[] args) {
Person martin = new Person("Martin", 24, 4, 1983);
Person juhana = new Person("Juhana", 17, 9, 1985);
System.out.println( martin );
System.out.println( juhana );
}
Prints:
Martin, born 24.4.1983
Juhana, born 17.9.1985
In chapter 24.4, we noted that objects are 'at the end of a wire'. Take a look
at that chapter again for good measure.
Person objects have the object variables name, which is a String-object and
birthMyDate, which is a MyDate object. The variables of person are
consequently both objects, so technically speaking they don't actually exist
within a person object, but are 'at the end of a wire'. In other words a
316
person has a reference to the objects stored in its object variables. The
concept as a picture:
The main program now has two person programs at the ends of wires. The
persons have a name and a birthdate. Because both are objects, both are at
the ends of wires the person holds.
Birthday seems like a good expansion to the Person class. We notice,
however, that the object variable age is becoming obsolete and should
probably be removed since the age can be determined easily with the help
of the current date and birthday. In Java, the current day can be figured out,
for example, like this:
int day = Calendar.getInstance().get(Calendar.DATE);
int month = Calendar.getInstance().get(Calendar.MONTH) + 1; // January is
0 so we add 1
317
}
public String toString() {
// returns the string representation
}
}
320
}
return true;
}
public void addAsMember(Person person) {
if ( !isAccepted(person) ) { // same as isAccepted(person) == false
return;
}
this.members.add(person);
}
public String toString() {
String membersAsString = "";
for ( Person member : this.members ) {
membersAsString += " " + member.getName() + "\n";
}
return "Weightwatchers association " + this.name + " members: \n" +
membersAsString;
}
}
322
The method addAsMember uses the method isAccepted that was creater
earlier.
Let's try out the expanded weightwatchers association:
public static void main(String[] args) {
WeightWatchersAssociation weightWatcher = new
WeightWatchersAssociation("Kumpulan paino", 25);
Person matti = new Person("Matti");
matti.setWeight(86);
matti.setHeight(180);
weightWatcher.addAsMember(matti);
Person juhana = new Person("Juhana");
juhana.setWeight(64);
juhana.setHeight(172);
weightWatcher.addAsMember(juhana);
Person harri = new Person("Harri");
harri.setWeight(104);
harri.setHeight(182);
weightWatcher.addAsMember(harri);
Person petri = new Person("Petri");
petri.setWeight(112);
petri.setHeight(173);
323
weightWatcher.addAsMember(petri);
System.out.println( weightWatcher );
}
In the output we can see that Juhana wasn't accepted as a member:
The members of weight watchers association 'kumpulan paino':
Matti
Harri
Petri
Exercise 90: Team and Players
Exercise 90.1: Class Team
Implement a class Team. At this stage team has only a name (String) and
the following functionality:
a constructor that sets the team name
getName, that returns the name
With the code:
public class Main {
public static void main(String[] args) {
Team barcelona = new Team("FC Barcelona");
324
}
}
331
// ..
Person heaviest = weightWatcher.personWithHighestWeightIndex();
System.out.print("member with the greatest weight index: " +
heaviest.getName() );
System.out.println(" weight index " + String.format( "%.2f",
heaviest.weightIndex() ) );
}
Prints:
member with the greatest weight index: Petri
weight index 37,42
332
public Counter(){
this(0);
}
public Counter(int initialValue){
this.value = initialValue;
}
public void grow(){
this.value++;
}
public String toString(){
return "value: "+value;
}
public Counter clone(){
// lets create a new counter object, that gets as its initial value
// the value of the counter that is being cloned
Counter clone = new Counter(this.value);
// return the clone to the caller
return clone;
}
}
333
// prints 2
// prints 2
// prints 2
counter.grow();
counter.grow();
counter.grow();
counter.grow();
System.out.println(counter);
System.out.println(clone);
// prints 6
// prints 2
clone.grow();
System.out.println(counter);
System.out.println(clone);
// prints 6
// prints 3
334
The value of the object being cloned and the value of the clone - after the
cloning has happened - are the same. However they are two different
objects, so in the future as one of the counters grows the value of the other
isn't affected in any way.
Exercise 91: Extending MyDate
In this assignment we will extend the class MyDate, that was developed in
chapter 24.7. The code of the class:
public class MyDate {
private int day;
private int month;
private int year;
public MyDate(int day, int month, int year) {
this.day = day;
this.month = month;
this.year = year;
}
public String toString() {
return this.day + "." + this.month + "." + this.year;
}
public boolean earlier(MyDate compared) {
// first we'll compare years
335
should print:
Friday after 1 weeks is 2.3.2011
Friday after 2 weeks is 9.3.2011
Friday after 3 weeks is 16.3.2011
Friday after 4 weeks is 23.3.2011
Friday after 5 weeks is 30.3.2011
Friday after 6 weeks is 7.4.2011
Friday after 7 weeks is 14.4.2011
This week's Friday is 25.2.2011
The date 790 days from this week's Friday is 5.5.2013
338
339
// since 2011-2009 = 2
340
// since 2011-2010 = 1
Calculation of the previous version was not very exact, e.g. the difference
of dates 1.1.2011 and 25.12.2010 was claimed to be one year. Modify the
method so that it can calculate the difference properly. Only the full
years in difference count. So if the difference of two dates would be 1 year
and 364 days, only the full years are counted and the result is thus one.
The method still needs to work only in the case where the date given as
parameter is before the date for which the method is called
The output for the previous example is now:
1.1.2011 and 24.12.2009 difference in years: 1
25.12.2010 and 24.12.2009 difference in years: 1
1.1.2011 and 25.12.2010 difference in years: 0
System.out.println( second + " and " + first + " difference in years: " +
first.differenceInYears(second) );
System.out.println( first + " and " + third + " difference in years: " +
third.differenceInYears(first) );
System.out.println( third + " and " + first + " difference in years: " +
first.differenceInYears(third) );
System.out.println( third + " and " + second + " difference in years: " +
second.differenceInYears(third) );
System.out.println( second + " and " + third + " difference in years: " +
third.differenceInYears(second) );
}
}
342
// Calendar.getInstance().get(Calendar.DATE);
// Calendar.getInstance().get(Calendar.MONTH) + 1; // January is 0
so we add one
// Calendar.getInstance().get(Calendar.YEAR);
}
public String getName() {
return this.name;
}
public String toString() {
return this.name +", born "+ this.birthday;
}
}
You can use the following program to test your method. Add also yourself
to the program and ensure that your age is calculated correctly.
public class Main {
public static void main(String[] args) {
Person pekka = new Person("Pekka", 15, 2, 1993);
Person steve = new Person("Thomas", 1, 3, 1955);
344
Output:
Thomas age 59 years
Pekka age 21 years
Output:
Pekka, born 15.2.1983
Steve, born 9.2.2012
Note: The last line depends on the day when the code is executed!
347
Week 6
Pekka Mikkola
040-123123
Pekka Mikkola number: 040-123123
Pekka Mikkola number: 050-333444
349
output:
040-123123
number not known
351
implement a class that represents money. We'll start with the following
class skeleton:
public class Money {
private final int euros;
private final int cents;
public Money(int euros, int cents) {
if (cents > 99) {
euros += cents / 100;
cents %= 100;
}
this.euros = euros;
this.cents = cents;
}
public int euros(){
return euros;
}
public int cents(){
return cents;
}
352
Notice that the instance variables euros and cents have been defined as
final meaning that once the variables have been set, the value of those can
not be changed. An object value of which can not be changed is said to be
immutable. If we need to e.g. calculate the sum of two money objects, we
need to create a new money object that represents the sum of the
originals.
In the following we'll create three methods that are needed in operating
with money.
Exercise 95.1: Plus
Let us start by implementing the method public Money plus(Money
added), that returns a new Money object that has a value equal to the sum
of the object for which the method was called and the object given as
parameter.
353
that
//
//
is assigned to variable a.
The Money object 10.00e that variable a used to hold
//
System.out.println(a); // 25.00e
System.out.println(b); // 5.00e
System.out.println(c); // 15.00e
354
355
c = c.minus(a);
25. Array
During the course, we've used ArrayLists numerous times to store different
kinds of objects. ArrayList is easy to use because it offers a lot of readymade tools that make the programmer's life a little easier: automatic
growing of a list, thanks to the list which doesn't run out of space (unless of
course the list grows so large that it makes the program take up all the
memory that is reserved for it), for example.
Array is an object that can be understood as a series of pigeonholes for
values. The length or size of an array is the number of spots in that array the number of items you can put in the array. The values of an array are
called cells of the array. Unlike with ArrayLists, the size of the array (the
amount of cells in an array) cannot be changed, growing an array always
requires creating a new array and copying the cells of the old array to the
new one.
357
An array can be created in two ways. Let's take a look at the way in which
we give content to the array at creation. An array of the integer type that
consists of 3 cells is defined as follows:
int[] numbers = {100, 1, 42};
The type of the Array object is denoted asint[], which stands for an array,
the cells of which are of the type int. In the example the name of the arrayobject is numbers and it holds 3 number values {100, 1, 42}. The array is
formatted with a block, in which the values to be inserted into the array are
separated by commas.
The values of the array can be of any variable type that we've seen earlier.
Below we've first introduced an array containing character strings and then
an array containing floating numbers.
String[] characterStringArray = {"Matti P.", "Matti V."};
double[] floatingNumberArray = {1.20, 3.14, 100.0, 0.6666666667};
The cells of the array are referred to with indexes that are integers. The
index tells the position of the cell in the array. The first item in an array is in
position 0, the next one in position 1, and so forth. When inspecting a
certain value of an array, the index is given after the name of the array
object in brackets.
// index
0 1 2 3 4 5
358
array - to an index that is smaller than 0, or larger or equals the size of the
array.
We'll notice that the array clearly is related to ArrayList. Arrays, as with
lists, have their cells in a certain order!
When iterating through an array it isn't always necessary to list the indexes
of it, the only interesting thing is the values of the array. In this case we can
use the for-each-structure - that we became familiar with earlier - to go
through the values. Now only the name of a variable is given in the frame of
the loop, to which each of the values of the array are set one after the other.
The name of the array is separated with a colon.
int[] numbers = {1,8,10,3,5};
for (int number : numbers) {
System.out.println(number);
}
String[] names = {"Juhana L.", "Matti P.", "Matti L.", "Pekka M."};
for (String name : names) {
System.out.println(name);
}
Notice: when using a for-each-type of loop you cannot set values to the cells
of the array! With the format of the for-sentence we inspect next that can be
done too.
361
when handling arrays. In the following we print the numbers 0, 1 and 2 with
a for loop:
for (int i = 0; i < 3; i++ ) {
System.out.println(i);
}
The for in the example works exactly as the while below:
int i = 0; // formatting the variable that will be used in the loop
while ( i < 3 ) { // condition
System.out.println(i);
i++; // updating the variable that is used in the loop
}
a for command, as shown in for (int i = 0; i < 3; i++ ) above, has three parts
to it: formatting the loop variables; condition; updating the loop variables:
In the first part, the variables that are used in the loop are formatted. In the
example above we formatted the variable i with int i=0. The first part is
run only once, at the beginning of a for run.
In the second part the condition is defined, which defines how long the
code is run in the code block that is related to the for loop. In our
example the condition was i < 3. The validity of the condition is checked
before each round of the loop. The condition works exactly the same as
the a condition of a while loop works.
362
The third part, which in our example is i++ , is always run once at the end
of each round of the loop.
Compared to while, for is a slightly clearer way of implementing loops of
whose amount of runs is based on, for example, growing a counter. When
going through an array the case is usually exactly this. In the following we
print the contents of the numbers array with for:
int[] numbers = {1, 3, 5, 9, 17, 31, 57, 105};
for(int i = 3; i < 7; i++) {
System.out.println(numbers[i]);
}
Naturally with for you don't have to start from 0 and the iteration can be
done 'from top down'. For example, the cells in indexes 6, 5, 4, and 3 can be
printed like this:
int[] numbers = {1, 3, 5, 9, 17, 31, 57, 105};
for(int i = 6; i>2 ; i--) {
System.out.println(numbers[i]);
}
}
public static void main(String[] args) {
int[] numbers = { 1, 2, 3, 4, 5 };
listCells(numbers);
}
As we already know, the name of the parameter within a method can be
freely chosen. The name does not need to be the same as in the one used in
calling it. Above, the array is called integerArray within the method and the
caller of the method knows the array as numbers.
Exercise 96: Sum of the array
Implement the method public static sum(int[] array), which returns the
sum of the numbers in the array given as parameter.
Program skeleton:
public class Main {
public static void main(String[] args) {
int[] array = {5, 1, 3, 4, 2};
System.out.println(sum(array));
}
public static int sum(int[] array) {
// write code here
365
return 0;
}
}
NOTE: in this and some of the following assignments methods are static
as the they used to be in the assignments for weeks 2 and 3. The reason
for this is that the methods are not instance methods, i.e. not operating
with instance variables of objects, instead they are working at "class level"
and operating just with the values and objects given as parameter. In
chapter 31 we'll elaborate more on the question whether a method
should be static or not.
Exercise 97: Elegant printing of an array
Implement the method public static int printElegantly(int[] array), which
prints the numbers in the array on the same row. In the printout all the
numbers should be separated with comma and whitespace and there
should not be a comma trailing the last number.
Program skeleton:
366
367
368
369
As seen in the output, the change made to the copy does not affect the
original:
original: [1, 2, 3, 4]
371
copied: [99, 2, 3, 4]
373
int number = 5;
if( number == 5 ) {
number = 6;
}
System.out.println(number); // prints 6
You can have any kind of code within a block. For example, a for loop can
have another for loop within it or say, a while loop. Let's inspect the
following program:
for(int i = 0; i < 3; i++) {
System.out.print(i + ": ");
for(int j = 0; j < 3; j++) {
System.out.print(j + " ");
}
System.out.println();
}
The program prints the following:
0: 0 1 2
1: 0 1 2
374
2: 0 1 2
So what happens in the program? If we only think about the outer for loop,
its functionality is easy to understand:
for(int i = 0; i < 3; i++) {
System.out.print(i + ": ");
// the inner for-loop
System.out.println();
}
So first i=0 prints 0: and a carriage return. After this i grows and 1 is printed
and so forth, so the outer for makes this happen:
0:
1:
2:
The inner for loop is also easy to understand separately. It prints out 0 1 2.
When we combine these two, we'll notice that the inner for loop carries out
its print just before the outer for loop's carriage return.
3 6 9 12 15
4 8 12 16 20
5 10 15 20 25
Exercise 99: Array to stars
Implement the method public static printArrayAsStars(int[] array), which
prints a line with stars for each number in the array. The line length is
determined by the number.
The program skeleton:
public class Main {
public static void main(String[] args) {
int[] array = {5, 1, 3, 4, 2};
printArrayAsStars(array);
}
public static void printArrayAsStars(int[] array) {
// code here
}
}
*
***
****
**
As seen the first line has 5 stars and the reason for that is that is that the
first element of the array is 5. The next line has one star since the second
element of the array is 1, etc.
Exercise 100: Night sky
Let us implement a program that prints the Night sky. The sky has a star
density. If the density is e.g. 0.1, roughly 10% of the sky is covered with
stars.
Stars print out as *-characters. Below an example that demonstrates how
the NightSky could be used when all the steps of the assignment are done.
NightSky NightSky = new NightSky(0.1, 40, 10);
NightSky.print();
System.out.println("Number of stars: " + NightSky.starsInLastPrint());
System.out.println("");
NightSky = new NightSky(0.2, 15, 6);
NightSky.print();
System.out.println("Number of stars: " + NightSky.starsInLastPrint());
380
**
**
*
*
*
* *
**
* **
*
*
* * **
* *
Number of stars: 36
***
** *
*
*
* *
*
* **
* ** **
Number of stars: 22
Note! in the assignment use the for-clause. Despite that the previous
chapter described nested loops, in this assignment we "hide" the nested
loop within a method.
381
382
*
Number of stars: 1
*
*
*
Number of stars: 3
table[i] = 0;
}
public static void main(String[] args) {
int[] values = { 1, 2, 3, 4, 5 };
for ( int number : values ) {
System.out.print( number + " " ); // prints 1, 2, 3, 4, 5
}
System.out.println();
resetArray(values);
for ( int number : values ) {
System.out.print( number + " " ); // prints 0, 0, 0, 0, 0
}
}
}
We notice that the method definition now has the keyword static. The
reason for that is that the method does not operate on any object, instead it
is a class method or in other words static methods. In contrast to instance
methods, static methods are not connected to any particular object and thus
the reference this is not valid within static methods. A static method can
385
387
388
389
antti.becomeOlder();
if ( antti.isAdult() ) {
System.out.println( antti.getName() + " is an adult" );
} else {
System.out.println( antti.getName() + " is a minor" );
}
if ( pekka.isAdult() ) {
System.out.println( pekka.getName() + " is an adult" );
} else {
System.out.println( pekka.getName() + " is a minor" );
}
if ( juhana.isAdult() ) {
System.out.println( juhana.getName() + " is an adult" );
} else {
System.out.println( juhana.getName() + " is a minor" );
}
}
}
We'll notice that the piece of code that reports the matureness of persons is
copy-pasted twice in the program. It looks really bad!
390
392
publishing year. The title and the publisher are of the type String and the
publishing year is represented as an integer.
Now implement the class Book. The class should have the constructor
public Book(String title, String publisher, int year) and methods public
String title(), public String publisher(), public int year() and public String
toString().
Example usage:
Book cheese = new Book("Cheese Problems Solved", "Woodhead
Publishing", 2007);
System.out.println(cheese.title());
System.out.println(cheese.publisher());
System.out.println(cheese.year());
System.out.println(cheese);
394
Note: when you do the search by a string (title or publisher), do not look
for exact matches (with the method equals) instead use the method
contains of the class String.
395
Example usage:
Library Library = new Library();
Library.addBook(new Book("Cheese Problems Solved", "Woodhead
Publishing", 2007));
Library.addBook(new Book("The Stinky Cheese Man and Other Fairly
Stupid Tales", "Penguin Group", 1992));
Library.addBook(new Book("NHL Hockey", "Stanley Kupp", 1952));
Library.addBook(new Book("Battle Axes", "Tom A. Hawk", 1851));
ArrayList<Book> result = Library.searchByTitle("Cheese");
for (Book book: result) {
System.out.println(book);
}
System.out.println("---");
for (Book book: Library.searchByPublisher("Penguin Group ")) {
System.out.println(book);
}
System.out.println("---");
for (Book book: Library.searchByYear(1851)) {
System.out.println(book);
}
396
397
about trailing and ending white spaces in the string searched. If either of
the strings is null, the method should return false.
Tip: The methods trim and toUpperCase() of the class String might be
helpful.
When you have completed the method, use it in the search functionality of
the class Library.
Use the method as follows:
if(StringUtils.included(book.title(), searchedTitle)) {
// Book found!
}
System.out.println(book);
}
System.out.println("---");
for (Book book: Library.searchByPublisher("PENGUIN ")) {
System.out.println(book);
}
28. Assignments where you are free to decide how to structure the
program.
Exercise 102: Grade distribution
This assignment corresponds to three assignment points.
399
Note1: Your program should use only one Scanner object, i.e., it is allowed
to call new Scanner only once. If you need scanner in multiple places, you
can pass it as parameter:
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
// ...
doSomething(scanner);
}
public static void doSomething(Scanner scanner) {
String riw = scanner.nextLine();
// ...
}
After the scores have been read, the program prints the grade distribution
and acceptance percentage of the course in the following form:
Grade distribution:
5: **
4:
3: ***
2: *
1: *
0: *
Acceptance percentage: 87.5
401
? Statistics
Seagull (Dorkus Dorkus): 2 observations
Raven (Corvus Corvus): 0 observations
? Show
What? Seagull
Seagull (Dorkus Dorkus): 2 observations
? Quit
Note you may structure your program freely, it is only required that the
output of the program is as in the above example.
404
import java.util.Arrays;
If you forget to write the import line, NetBeans will offer help with writing it.
Try clicking the picture of the "bulp" that appears to the left from the line of
code that is underlined with red.
The following program creates arrays and sorts the values in the array with
the Arrays.sort -command.
int[] values = {-3, -111, 7, 42};
Arrays.sort(values);
for(int value: values) {
System.out.println(value);
}
-111
-3
7
42
Note: in this assignment you're supposed to sort the array yourself. You
can't use the help of the Arrays.sort()-method or ArrayLists!
Exercise 104.1: Smallest
Implement a method smallest, which returns the smallest value in the
array.
The frame of the method is as follows:
public static int smallest(int[] array) {
// write the code here
}
NOTE: You can't change the array that gets passed into the method!
The following code demonstrates the functionality of the method:
int[] values = {6, 5, 8, 7, 11};
System.out.println("smallest: " + smallest(values));
smallest: 5
406
NOTE: You can't change the array that gets passed into the method as a
parameter!
The following code demonstrates the functionality of the method:
// indexes: 0 1 2 3 4
int[] values = {6, 5, 8, 7, 11};
System.out.println("Index of the smallest: " +
indexOfTheSmallest(values));
Index of the smallest: 1
The smallest value of the table is 2 and its index (its location) in the array
is 1. Remember that the numbering of an array begins from 0.
Exercise 104.3: Index of the smallest at the end of an array
Implement a method indexOfTheSmallestStartingFrom, which works just
like the method of the previous assignment, but only takes into
consideration the end of an array starting from a certain index. In
407
addition to the array the method gets as parameter an index, from which
the search for the smallest will be started.
The frame of the method is as follows:
public static int indexOfTheSmallestStartingFrom(int[] array, int index) {
// write the code here
}
NOTE: You can't change the array that gets passed into the method as a
parameter!
The following code demonstrates the functionality of the method:
// indexes: 0 1 2 3 4
int[] values = {-1, 6, 9, 8, 12};
System.out.println(indexOfTheSmallestStartingFrom(values, 1));
System.out.println(indexOfTheSmallestStartingFrom(values, 2));
System.out.println(indexOfTheSmallestStartingFrom(values, 4));
1
3
4
408
In the example, the first method call finds the index of the smallest value
starting from index 1. Starting from index 1 the smallest value is 6, and its
index is 1. Respectively the second method call looks for the index of the
smallest value starting from index 2. In this case the smallest value is 8
and its index is 3. The last call starts from the last cell of the array, in this
case there is no other cells so the smallets value is in index 4.
Exercise 104.4: Swapping values
Create a method swap, to which will be passed an array and two of its
indexes. The method swaps the values in the indexes around.
The frame of the method looks like this:
public static void swap(int[] array, int index1, int index2) {
// code goes here
}
System.out.println( Arrays.toString(values) );
swap(values, 0, 3);
System.out.println( Arrays.toString(values) );
[3, 2, 5, 4, 8]
[2, 3, 5, 4, 8]
[4, 3, 5, 2, 8]
410
Inspect the array starting from index 1. Swap the value in index 1 and the
smallest value in the array starting from index 1.
Inspect the array starting from index 2. Swap the value in index 2 and the
smallest value in the array starting from index 2.
and so forth
Implement the method sort, which is based on the idea above. The
method ought to have a loop that goes through the indexes of the array.
The methods smallestIndexStartingFrom and swap are surely useful. Also
print the contents of the array before sorting and after each round to be
able to make sure that the algorithm works correctly.
Body of the method:
public static void sort(int[] array) {
}
The program should print the following. Notice that you're to print the
content of the array after each swap!
411
[8, 3, 7, 9, 1, 2, 4]
[1, 3, 7, 9, 8, 2, 4]
[1, 2, 7, 9, 8, 3, 4]
[1, 2, 3, 9, 8, 7, 4]
[1, 2, 3, 4, 8, 7, 9]
[1, 2, 3, 4, 7, 8, 9]
[1, 2, 3, 4, 7, 8, 9]
You'll notice how the array little by little gets sorted out starting from the
beginning and advances towards the end.
30. Searching
In addition to sorting, another very typical problem that a programmer runs
into is finding a certain value in an array. Earlier, we've implemented
methods that search for values in lists and arrays. In the case of arrays,
values and strings can be searched for in the following way:
public static boolean isInArray(int[] array, int searchingFor) {
for ( int value : array ) {
if ( value == searchingFor ) {
return true;
}
}
412
return false;
}
public static boolean isWordInArray(String[] array, String searchingFor) {
for ( String word: array ) {
if ( word.equals(searchingFor) ) {
return true;
}
}
return false;
}
An implementation like this is the best we've been able to do so far. The
downside of the method is that, if the array has a very large amount of
values in it, the search will take a lot of time. In the worst case scenario the
method goes through every single cell in the array. This means that going
through an array that has 16777216 cells does 16777216 cell inspections.
On the other hand, if the values in an array are ordered by size, the search
can be done in a notably faster way by applying a technique called binary
search. Let's investigate the idea of binary search with this array:
// indexes 0 1 2 3 4 5 6 7 8 9 10
// values
-7 -3 3 7 11 15 17 21 24 28 30
413
Let's assume that we want to find the value 17. Let's utilize the information
that the values of the array are in order instead of going through the array
from the beginning. Let's inspect the middle cell of the array. The middle
cell is 5 (the largest index 10 divided by two). The middle cell is marked
with the asterisk:
*
// indexes 0 1 2 3 4 5 6 7 8 9 10
// values
-7 -3 3 7 11 15 17 21 24 28 30
At the middle is the value 15, which was not the value we were looking for.
We're looking for the value 17, so since the cells of the array are ordered by
size, the value cannot be on the left side of the 15. So we can determine that
all indexes that are smaller or equal to 5 do not have the value we are
looking for.
The area where we are searching for the value we want to find can now be
limited to values that are on the right side of the index 5, or in other words,
in the indexes [6, 10] (6, 7, 8, 9, 10). In the following, the searched value
cannot be in the part of the array which is grey:
// indexes 0 1 2 3 4 5 6
// values
7 8 9 10
-7 -3 3 7 11 15 17 21 24 28 30
Next, let's inspect the middle index of the area that we have left; the middle
index of indexes 6-10. The middle index can be found by getting the sum of
414
the smallest and largest index and dividing it by two: (6+10)/2 = 16/2 = 8.
The index 8 is marked with the asterisk below.
*
// indexes 0 1 2 3 4 5 6 7 8 9 10
// values
-7 -3 3 7 11 15 17 21 24 28 30
In index 8, we have the value 24, which was not the value we were looking
for. Because the values in the array are ordered by size, the value we are
searching for can not, in any case, be on the right side of the value 24. We
can deduce that all indexes that are larger or equal to 8 can not contain the
value we are looking for. The search area gets narrowed down again, the
grey areas have been dealt with:
// indexes 0 1 2 3 4 5 6 7 8 9 10
// values
-7 -3 3 7 11 15 17 21 24 28 30
The search continues. Let's inspect the middle index of the area that we
have left to search, that is, the middle index of indexes 6-7. The middle
index can again be found out by getting the sum of the smallest and largest
index of the search area and then dividing it by two: (6+7)/2 = 6.5, which is
rounded down to 6. The spot has been marked with the asterisk.
*
// indexes 0 1 2 3 4 5 6 7 8 9 10
// values
-7 -3 3 7 11 15 17 21 24 28 30
415
In the index 6 we have the value 17, which is the same as the value we've
been looking for. We can stop the search and report that the value we
searched for is in the array. If the value wouldn't have been in the array - for
example if the searched-for value would've been 16 - the search area would
have eventually been reduced to nothing.
*
// indexes 0 1 2 3 4 56 7 8 9 10
// values
-7 -3 3 7 11 1517 21 24 28 30
So for the idea of binary search to become clear to you, simulate with pen
and paper how the binary search works when the array is the one below
and first you're searching for value 33 and then value 1.
// indexes 0 1 2 3 4 5 6 7 8 9 10 11 12 13
// values
-5 -2 3 5 8 11 14 20 22 26 29 33 38 41
With the help of binary search we look for cells by always halving the
inspected area. This enables us to search in a very efficient way. For
example, an array of size 16 can be divided in half up to 4 times, so 16 -> 8 > 4 -> 2 -> 1. On the other hand, an array that has 16777216 cells can be
halved up to 24 times. This means that with binary search we only need to
inspect up to 24 cells in an array that has 16777216 cells in order to find
our desired cell.
The efficiency of binary search can be inspected with logarithms. A base two
logarithm (log2) of the number 16777216 is 24 -- with the base two logarithm
416
we can calculate how many times a number can be halved. Respectively the
base two logarithm of the number 4294967296 (log2 4294967296) is 32. This
means that searching from a sorted array of 4294967296 different values
would only take up to 32 cell inspections. Efficiency is an essential part of
computer science.
Exercise 105: Guessing game
In this assignment we'll make an AI, which guesses the number the player
is thinking about. The AI assumes that the number is between
lowerLimit...upperLimit. The start of the game provides these limits to the
method as parameters that makes the game happen. The AI asks the
player questions in the format "Is your number greater than X?" and
deduce the correct answer from the answers the player gives.
The AI keeps track of the search area with the help of the variables
lowerLimit and upperLimit. The AI always asks if the player's number is
greater than the average of these two numbers, and based on the answers
the search area gets halved each time. In the end the lowerLimit and
upperLimit are the same and the number the user is thinking of has been
revealed.
In the following example the user chooses the number 44:
Think of a number between 1...100.
I promise you that I can guess the number you are thinking of with 7
questions.
417
In the above example the possible value range is first 1...100. When the
user tells the program that the number is not greater than 50 the possible
range is 1...50. When the user says that the number is greater than 25, the
range is 26...50. The deduction proceeds in the same fashion until the
number 44 is reached.
In accordance to the principles of halving, or binary search, the possible
search area is halved after each question in which case the number of
418
419
420
The method returns the value true if the user replies "y", otherwise false.
Test your method
GuessingGame game = new GuessingGame();
System.out.println(game.isGreaterThan(32));
Is your number greater than 32? (y/n)
y
true
I promise you that I can guess the number you are thinking of with 2
questions.
Next I'll present you with a series of questions. Answer them honestly.
Is your number greater than 2? (y/n)
k
Is your number greater than 3? (y/n)
k
The number you're thinking of is 4.
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
// Here you can test binary search
int[] array = { -3, 2, 3, 4, 7, 8, 12 };
Scanner reader = new Scanner(System.in);
System.out.print("Values of the array: " + Arrays.toString(array));
System.out.println();
System.out.print("Enter searched number: ");
String searchedValue = reader.nextLine();
System.out.println();
boolean result = BinarySearch.search(array,
Integer.parseInt(searchedValue));
// Print the binary search result here
}
}
424
425
person.becomeOlder();
}
// or persons.get(0).becomeOlder();
//
persons.get(1).becomeOlder();
//
...
}
for ( Person person : persons ) {
reportMaturity(person);
}
}
In most situations it's better to use ArrayList instead of an array. However
there can be cases where an array is adequate and is simpler to use.
A week always consists of seven days. It would be meaningful to form it out
of exactly 7 Day objects. Since there's always 7 Day objects, an array will
suit the situation very well:
public class Day {
private String name;
// ...
}
public class Week {
427
428