Object-Oriented Programming with Java, part I + II

cc

This material is licensed under the Creative Commons BY-NC-SA license, which means that you can use it and distribute it freely so long as you do not erase the names of the original authors. If you make changes in the material and want to distribute this altered version of the material, you have to license it with a similar free license. The use of the material for commercial use is prohibited without a separate agreement.

Authors: Arto Hellas, Matti Luukkainen
Translators to English: Emilia Hjelm, Alex H. Virtanen, Matti Luukkainen, Virpi Sumu, Birunthan Mohanathas, Etiënne Goossens
Extra material added by: Etiënne Goossens, Maurice Snoeren, Johan Talboom
Adapted for Informatica by: Ruud Hermans

The course is maintained by Technische Informatica Breda


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.

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.

Self-written 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 self-written 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.

public static void greet() {
    System.out.println("Greetings from the world of methods!");
}

And let us place it in the right spot.

import java.util.Scanner;

public class ProgramBody {
    public static void main(String[] args) {
        Scanner reader = new Scanner(System.in);
        // program code
    }

    // self-written methods
    public static void greet() {
        System.out.println("Greetings from the world of methods!");
    }
}

In order to define a new method we need to write two things. In the first row of the method definition, you will find the name of the method, in this case greet. On the left side of the name you will find the definitions public static void. On the next line, the code block marked by the braces ({ and }). Inside it, the method’s code, or the commands that will be executed when 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!");
    }
}

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.

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 method-1: 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
}

The program output:

In the beginning there were the swamp, the hoe and Java.

Exercise method-2: Many prints

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
}

The program output:

How many?
~~7~~
In the beginning there were the swamp, the hoe and Java.
In the beginning there were the swamp, the hoe and Java.
In the beginning there were the swamp, the hoe and Java.
In the beginning there were the swamp, the hoe and Java.
In the beginning there were the swamp, the hoe and Java.
In the beginning there were the swamp, the hoe and Java.
In the beginning there were the swamp, the hoe and Java.

Note: you should print the assisting question How many? on its own line!

Method parameters

We can make our methods more useful by giving it parameters! Parameters are variables that we define inside brackets in the first line, just after the method name. When the method is called, the parameters are assigned values.

In the next example we define a method with a parameter, its name will be greet and its parameter will be a variable of the type String called name.

public static void greet(String name) {
    System.out.println("Hi " + name + ", greetings from the world of methods!");
}

Let us next call the greet method so that on the first try we give its parameter the value Matt and on the second try Arthur.

public static void main(String[] args) {
    greet("Matt");
    greet("Arthur");
}
Hi Matt, greetings from the world of methods!
Hi Arthur, greetings from the world of methods!

More complicated expressions can also be used as a parameter for our self-written methods, the same way we used them together with the ready-made 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".

Many parameters

A method can be defined to have more than one parameter. In this case, the parameters are always listed in the same order.

public static void greet(String name, String greetingsFrom) {
    System.out.println("Hi " + name + ", greetings from " + greetingsFrom);
}

public static void main(String[] args)
{
    String who = "Matt";
    String greetings = "Alabama";

    greet(who, greetings);
    greet(who, greetings + " from Nevada");
}

In the last greet function (or method) call the second parameter is formed by concatenating (or adding) the text “from Nevada” to the variable greetings. This is done before the actual function call.

Hi Matt, greetings from Alabama
Hi Matt, greetings from Alabama from Nevada

Method calling another method

Methods can also be called outside of main. Methods can call each other! Let us create a method greetManyTimes that greets the user many times getting assistance from the method greet:

public static void greet(String name) {
    System.out.println("Hi " + name + ", greetings from the world of methods!");
}

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);
}

Exercise method-3: Printing

Exercise method-3.1: Printing stars

Create a method printStars that prints the given amount of stars and a line break.

Create the method in the following body:

public static void printStars(int amount) {
   // you can print one star with the command
   // System.out.print("*");
   // call this command amount times
}

public static void main(String[] args) {
   printStars(5);
   printStars(3);
   printStars(9);
}

The program output:

*****
***
*********

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 method-3.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 method-3.3: Printing a rectangle

Create a method printRectangle(int width, int height) that prints a rectangle using the printStars method. The call printRectangle(17,3), for example, has the following output:

*****************
*****************
*****************

Exercise method-3.4: Printing a left-aligned triangle

Create the method printTriangle(int size) that prints a triangle using the printStars method. The method call printTriangle(4), for example, has the following output:

*
**
***
****

Exercise method-4: Printing Like A Boss

like a boss

Exercise method-4.1: Printing stars and whitespaces

Create a method printWhitespaces(int size) that prints the given amount of whitespaces. Them method should not print a line break.

Reimplement or copy the method printStars(int size) from the previous exercise. Make sure this method prints a line break (newline)

Exercise method-4.2: Printing a right-aligned triangle

Create the method printTriangle(int size) that prints a triangle using the methods printWhitespaces and printStars. Note: do not print anything in the method itself, just call the helper methods to do the actual printing.

For example, the method call printTriangle(4) has the following output:

   *
  **
 ***
****

Exercise method-4.3: Printing a Christmas tree

Create the method xmasTree(int height) that prints a Christmas tree using the methods printWhitespaces and printStars. A Christmas tree consists of a triangle of given height and a stand. The stand is two stars tall and three stars wide and it is located in the center of the bottom of the triangle. Note: do not print anything in the method itself, just call the helper methods to do the actual printing.

The method call xmasTree(4), for example, has the following output:

   *
  ***
 *****
*******
  ***
  ***

The method call xmasTree(10) has the following output:

         *
        ***
       *****
      *******
     *********
    ***********
   *************
  ***************
 *****************
*******************
        ***
        ***

Second note: You don’t need to worry about heights below 3!

Exercise method-5: Guessing a number game

In this exercise the following game is created:

Guess a number: ~~73~~
The number is lesser, guesses made: 1
Guess a number: ~~22~~
The number is greater, guesses made: 2
Guess a number: ~~51~~
The number is greater, guesses made: 3
Guess a number: ~~62~~
The number is greater, guesses made: 4
Guess a number: ~~68~~
The number is greater, guesses made: 5
Guess a number: ~~71~~
The number is lesser, guesses made: 6
Guess a number: ~~70~~
Congratulations, your guess is correct!

Exercise method-5.1: Guessing a number

The program that comes with the exercise contains a command called drawNumber. It draws a number, which is in the range 0 to 100 (both 0 and 100 are possible). Create a program that draws a number. Then the user has the chance to guess once, what the number is. The program should to print “The number is lesser”, “The number is greater” or “Congratulations, your guess is correct!” depending on the number the user typed.

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!

Exercise method-5.2: Repeated guessing

Develop your program by adding the following functionality: the guessing should be made repeatedly until the user types the right number. Note that you need to draw the number by using the drawNumber command before the repetition. Why? What happens if you draw the number inside the repetition?

In the example below, the command call drawNumber returned the value 83.

Guess a number: ~~55~~
The number is greater
Guess a number: ~~85~~
The number is lesser
Guess a number: ~~77~~
The number is greater
Guess a number: ~~81~~
The number is greater
Guess a number: ~~83~~
Congratulations, your guess is correct!

Exercise method-5.3: Counting the guesses

Develop your program by adding the following functionality: the program needs to include a variable of type int, which is used to count the guesses the user has made. The program should always print the number of guesses along with the answer.

Guess a number: ~~55~~
The number is greater, guesses made: 1
Guess a number: ~~85~~
The number is lesser, guesses made: 2
Guess a number: ~~77~~
The number is greater, guesses made: 3
Guess a number: ~~81~~
The number is greater, guesses made: 4
Guess a number: ~~83~~
Congratulations, your guess is correct!

Exercise method-6: A text-based user interface for the Hangman game

Your friend has programmed a Hangman game for you, but the game lacks the user inferface. The Hangman has the following methods:

  • 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();
        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");
    }

The exercise is completed in small steps.

Exercise method-6.1: Loops and ending loops

Create a loop in the program that works as a base for the rest of the user interface. Ask the user to submit the command inside the loop. If the command is “quit”, break the loop.

Use the command hangman.gameOn as the condition for the while structure. The loop should look like:

while (hangman.gameOn()) {
    String command = reader.nextLine();
    // ...
}

In the next set (week) of exercises, we will find out what this peculiar-looking 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

Type a command:
quit
Thank you for playing!

Exercise method-6.2: Printing the status

If the user gives the command “status”, print the status using the method hangman.printStatus().

************
* 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:
status
You have not made any guesses yet.
Unused letters: abcdefghijklmnopqrstuvwxyz

Type a command:
quit
Thank you for playing!

Exercise method-6.3: Making a guess

If the user types in a single letter as a command, use it to make a guess. Guessing a letter occurs in the method hangman.guess(command). The guessing command has its own printing functionality, which it uses to print more information about the guess.

Hint: finding out if the command is a single letter is done as follows:

String command = reader.nextLine();

if(command.length() == 1) {  // command has only one letter, so it must be a guess
    hangman.guess(command);
}
...
Type a command:
a
The letter a is not in the word.

Type a command:
b
The letter b is not in the word.

Type a command:
c
The letter c was found in the word!

Type a command:
quit
Thank you for playing!

Exercise method-6.4: Printing out the menu

If the user types an empty string of characters, meaning a string that has zero length, you need to call the method printMenu. Note that the method printMenu is not in the Hangman game but in your own program.

Note: checking if the string is empty is done as follows:

String winnie = "the pooh";
if(winnie.isEmpty()) {
    System.out.println("String was empty");
} else {
    System.out.println("I found something!");
}

Exercise 2-21.5: Printing the man and the word

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???

Type a command:
quit
Thank you for playing!

Math Library

A lot of functionality can be implemented by now, using the basic code stuctures that we’ve encountered so far. We could for example, write a method to determine the absolute value of a number. The code for such a method could be as follows

public static int abs(int number)
{
    if(number < 0) {
        return -number;
    } else {
        return number;
    }
}

Writing these methods for all basic math concepts is not very hard, but it is a lot of work to write them. Fortunately, a lot of this has already been written, and combined in the Math structure. We can find a lot of information on this in the documentation. In this documentation, we can typically find some very important information on these method. The document starts with a long list of available methods, followed by a short description. Clicking on a method will show a longer description

abs

In the line public static int abs(int a) we can see the parameter type, and a description of the parameter. We can also see the return type, which will be covered next week. Also a precise description is available, to see exactly what this method will do.

Some convenient methods are:

Also you can use Math.PI as a value of