Chapter 6 Notes - More sophisticated Behaviour

November 28, 2021

Jack Madden

More-Sophisticated behaviour

Throughout this chapter, the main point is reading documentation of the library classes. A good programmer will learn to read the documentation, and understand it well.

The Java library is arranged in relationships. So items in the java.util.* collection will all have a relationship, Like ArrayList does as one class. Throughout this chapter, several new classes will be discussed. Such as

  • Random
  • String (class)
  • Hashset
  • Hashmap

We will also have a look at writing our own documentation, for classes that we write ourselves.

Code is more secure, if it only has access to the data it needs to fulfil its function. There are Java mechanisms for this.

And we will also look at storing data and defining methods to be used on the class itself.

Aims

  • Using library classes
  • Reading documentation
  • Writing documentation

Documentation for the library classes

The Java Standard class library contains many classes. It is important to know how to use the library.

The Java library is extensive, it includes thousands of classes. It is impossible to try and remember them all, so a good programmer will

  • Know some of the important library classes by name (such as ArrayList)
  • Be able to find out other classes by looking up their details.

During this section of the book, we will show you how to look up important classes from the library. The library is available in HTML format. We will also look at writing our own documentation for our own classes.

The TechSupport system v1

As always we shall explore these items with an example.

The TechSupport v1 system is three classes

  • SupportSystem - This is the main class
  • InputReader - This is the reader of the terminal
  • Responder - This is the responder

Reading the code

The most interesting piece of the software is the method in the middle start

Which looks a little like this

boolean finished = false;
while(!finished) {
    do something
    if(exit condition) {
        finished = true;
    } else {
        do something more
    }
}

This is a classic while loop, with the initial finished flag set to false. The loop repeatedly

  • Reads user input
  • Asks the responder to generate a response
  • Prints out the response

The last bit of the code reads the exit condition.

String input = reader.getInput();
if(input.startsWith("bye")) {
    finished = true;
}

And the program will then decide if the user wants to exit or not? But the code can be improved in certain ways. If the user enters the word “Bye” or ” bye” then the program will fail to exit. But we can solve these problems, if we know more about the String class.

Reading class documentation

The Java class library documentation shows details about all classes in the library. Using this documentation is essential in order to make good use of the library classes.

Choose java class libraries from the Bluej help menu. This will open up a new browser interface with three frames.

  • List of packages - top left
  • List of classes- bottom left
  • Details of package/class - large frame on the right

Interfaces vs implementation

Documentation includes many pieces of information

  • The name of the class
  • A general description of the class
  • A list of the classes constructors/methods
  • The parameters and return types for the constructors/methods
  • A description of the constructor/method

The interface of a class describes what a class does and how it can be used without showing the implementation.

All this together is called the interface. Note that this does not show the class source code. This is abstraction.

The source code behind the scene is called the implementation.

The complete source code that defines a class is called the implementation of that class

Using a library class methods

The documentation of the String class tells us that we need to call the trim method. This will remove the white space around the string.

An object is said to be immutable if its contents or state cannot be changed once it has been created. Strings are an example of immutable objects.

String objects are immutable, please note that the trim method returns a new String. A common error is to put

input.toUpperCase();

Where as the proper way is to use

input = input.toUpperCase();

So the proper way to use trim is to

input = input.trim();

So now we can build the proper way to ensure that the string is correct

String input = reader.getInput();
input = input.trim().toLowerCase();
if(input.startsWith("bye")) {
    finished = true;
} else {
    *code omitted*   
}

Adding random behaviour

We will add a Random behavior to our responder class. To do this, we will need an ArrayList and pick one via our random number generator.

The random class

The Random class is located in java.util.Random;.

To generate a random number

import java.util.random;

public class GenerateRandom
{
    private Random randomGenerator;
    
    public GenerarateRandom()
    {
        randomGenerator = new Random();
    }
    
    public void generate()
    {
        System.out.println(randomGenerator.nextInt());
    }
}

Random numbers with limited range

It is possible to generate numbers within a limited range. When getting random numbers, you must check whether the boundaries are inclusive or Exclusive.

  • inclusive is when the number is included
  • exclusive is when the number is not included

The .nextInt method of the random class is set to 0(inclusive) up to the next number of n-1(exclusive).

Generating random responses

Now we can look at generating random responses.

  • Declare a field of type Random
  • Declare a field of type ArrayList
  • Create the Random and the ArrayList in our classes constructor
  • Fill out the responders list with phrases
  • Select and return a random phrase when generateResponse is called

The most interesting part of the generate response method

public String generateResponse()
{
    int index = randomGenerator.nextInt(responses.size());
    return responses.get(index);
}

The first line of the code does three things

  • Gets the size of the response list
  • Generates a random number from 0 (inclusive) to the size of the responses
  • Stores that value in a int called index

The last line in the method does two things

  • Retrieves the response at position index using the get method
  • Returns the selected string.

Reading documentation for parameterized classes

The angle brackets <> in ArrayList<E> or HashMap<K, V> or any other class, are known as parameterized classes or generic classes. This tells us that the class name is incomplete until we pass it a parameter.

Packages and Imports

Lets look at the top of the class at the import statements.

Class library’s are not available for use without an import statement. This is called importing the class and is done via the import statement. Because the library holds thousands of classes, Java uses packages to contain them. ArrayList and Random both belong in the package java.util. The full name of a class is the name of the package, followed by a dot,followed by the class name.

The conditional operator

The conditional operator is used to select one of two alternative values based on a boolean expression.

It looks like this

ticketType = age < 18 ? "child" : "adult";

This is a ternary operator.

  • The first operator is a boolean condition
  • The second operator (after the ?) is returned if the boolean results in true
  • The third operator (after the :) is returned if the boolean results in false

The Switch statement

The switch statement uses three keywords: switch, case, (and optionally) default.

It looks like this

public void choice(response){
    switch (response) {
        case 0: myResponse = "Yes";
            break;
        case 1: myResponse = "No";
            break;
        default: myResponse = "Maybe";
            break;
    }
}

The default part deals with the cases that switch cannot answer.

Using maps for associations

For this we will use a HashMap (dictionary) which is a specialization of Map.

The concept of a map

A map is a collection that stores key/value pairs as entries. Values can be looked up by providing the key.

A map is a collection of key/value pairs of objects. It is flexible with the number of entries it can take. A map entry is a pair of objects. This pair is a key and a value.

  • Looking up a value for a key is easy
  • Looking up a key with a value is hard

Using a HashMap

The most important methods of a HashMap are put and get.

The put method inserts an entry into the map. The get method retrieves that entry from the map.

It looks like this

HashMap<String, String> contacts = new HashMap<>();
contacts.put("Jack Madden", "07777 777777");
contacts.put("Kirsty Madden", "07888 999000");
String number = contacts.get("Jack Madden");

Using sets

A set is a collection that stores each individual item at most once. It does maintain any specific order.

The Java library includes different versions of sets. The class we will look at is called a HashSet.

Using a HashSet

A HashSet looks like this

HashSet<String> mySet = new HashSet<>();
mySet.add("One");
mySet.add("Two");
mySet.add("Three);
boolean x = mySet.contains("Two");

A set does not maintain any particular order. It ensures that the most you can enter into the set is once. Entering an item two or more times into the set does nothing.

By iterating over a set one by one, each object in the set can be accessed one at a time.

Iterating over a map

The Java method keySet is used to return all of its keys. This will return a set of keys from the map.

The following code can be used to iterate over the map.

for (String aKey : myMap.keySet()) {
    System.out.println(aKey);
}

This will print out the keys one at a time.

Dividing Strings

We can use the String.split() method to split the string.

That looks something like this

String[] wordArray= inputLine.split(" "); // Split at spaces

This will return an array of strings.

Autoboxing and wrapper classes

Wrapper classes provide a way to use primitive data types as reference data types. Reference data types contain useful methods that can be used with collections.

Autoboxing is performed automatically when a primitive-type value is used in a context requiring a wrapper type

All primitive types are noted in the books Appendix b Primitive types in Java must be wrapped up before any type of work can be carried out. This is done automatically with a process called autoboxing

As well as autoboxing there is unboxing which is also performed automatically. Unboxing does the opposite to autoboxing.

Maintaining usage counts

In this section we have a go with the getOrDefault method of the HashMap. The getOrDefault method helps to avoid possible null values returned from a map when using the default get method.

Maps with sets as values

A map with a set as a value looks like this

This goes at the top of the file

HashMap<String, HashSet<String>> animalMap;

This goes in the constructor

animalMap = new HashMap<>();

And these go elsewhere

animalMap.put("Reptiles", new HashSet<>());
animalMap.put("Chelonians", new HashSet<>());
animalMap.put("Mammals", new HashSet<>());

Writing class documentation

It is important to write documentation for your clases as you develop them.

The documentation of a class should be detailed enough for other programmers to use the class without the need to read the implementation.

When using a class from the library such as HashMap we relied upon the documentation to find out how to use them. This is true for our own classes.

Java systems use a tool called javadoc.

Elements of a classes documentation

The document of the class should hopefully include

  • The class name
  • A comment describing the overall purpose of the class
  • A version number
  • Author name
  • Documentation for the constructor and methods

The documentation of a constructor/method should include

  • The name of the method
  • The return type
  • Parameter types and names
  • Description of the function of the method
  • Description of each parameter
  • Description of the value that is returned

Each project will also have a ReadMe file. This is where you will write your overall project comment.

The tags are called “annotations”

The javadoc comments look like this

/**
 This is a javadoc comment
 */

In Java we use an “@” symbol to highlight bits of the documentation. These include, but are not limited to

  • @version
  • @author
  • @param
  • @return

Public vs Private

Public or Private are the Access modifiers at the beginning of field/method declarations. If a method is public it can be invoked from the same class or any other class. If a method is private it can only be used by the same class.

Access modifiers define the visibility of a field, constructor or method. Public elements are accessible from inside the same class or other classes. Private elements are only accessible from within the same class.

There are times when we need to use private methods/constructors. These are called Helper methods.

Information hiding

In many programming languages the internals of a class (implementation) are hidden from the user. The object has become a ‘black box’ with its data only being accessible through a limited set of public methods. There are two aspects to this

  • The programmer should not need to know this
  • The programmer is not allowed to know this

Not needing to know - is about abstraction and modularization. Not allowed to know - is about modularization in a different way. This ensures that one class does not depend on another.

Information Hiding is a principle that states that internal details of a classes implementation should be hidden from other classes. It ensures better modularization of an application.

This is very important for maintenance work and fixing bugs. This issue is known as coupling. Weak coupling is a good thing. If it was up to the maintainer to change change the ArrayList you will not have to make changes to any of your code because you have not made any references to the implementation of ArrayList in your file.

The programming of both classes (even if there both you) should be loosely coupled.

Access modifiers

Java has four different access modifiers

  • default (no access modifier)
    • This is used when no access modifier is given
  • protected
    • This gives the subclasses access to the variable
  • public
    • This means any class can use the variable
  • private
    • This means that only this class can use the variable

Code completion

Typing CTRL-space will bring up a pop-up menu of all methods we have available. Hitting return enters the method into our source code.

Class variables and constants

We will look at the keywords static and final.

The static keyword

The keyword static defines a class variable. These are stored in the class itself, not an object.

Classes can have fields. These are known as Class variables or Static variables. Exactly one copy of a class variable exists at all times, independent of the number of created instances.

Static variables are written in all caps to let the user know what they are. They look like this

public class BouncingBall
{
    // Effect of gravity
    private static final int GRAVITY = 3;
    private int xPosition;
    private int yPosition;
}

Static variables can be accessed by any instance of the class. The objects share this variable.

The final keyword

Constants are defined with the keyword final. For example

private final int SIZE = 10;

The look the same as a field declaration but

  • They include the keyword final before the type
  • They must be initialised with a value

Constants are written in all caps. Constants are frequently used with all instances of a class. They are called class constants.

Class methods

Just as static variables belong to a class, so do static methods. They look like this

public static int getNumberOfDaysThisMonth()
{
    ...
}

Note the static keyword in the methods header. So if this was a method in Calender, it would be called like this

int days = Calender.getNumberOfDaysThisMonth();

Note that Calendar is used, not the instance of the class.

Limitations of class methods

There are two limitations with class methods

  • They may not access any instance fields.
  • They will not call an instance method.

Executing without BlueJ

We will need a main method to do this

The main method

Firstly the user must specify a class to launch the program. The Java system will look for a method called main This looks like

public static void main(String args[])

Please see Appendix E of the book.

Further advanced material

Now we will look at some more advanced material

Polymorphic collection types (Advanced)

In object-oriented programming, relationships between classes are expressed via inheritance. So a

List<Track> tracks = new LinkedList<>();

Is said to be of type List, even though the object stored in it is of type LinkedList. These are called polymorphic variables.

So a call to add, get, clear, remove or size on tracks would all have the same syntax. The point of polymorphic variables is that if we ever needed to change type, the only place in the code we would have to change would be the place where the object is created.

The collect method of streams (Advanced)

The collect method is a terminal operation. So we will use it as a final operation on a stream.

There are two collect methods, but here we will be talking about the simplest. The collect method takes a collector. This is something that can accumulate elements of its input stream.

The easiest way to use a collector, is to use one of the static methods available in the collectors class. This can be either toList, toMap or toSet.

So for example

public List<Sighting> getSighting(String animal)
{
    return sightings.stream()
                    .filter(record -> animal.equals(record.getAnimal()))
                    .collect(Collectors.toList());
}

Method references (Advanced)

If we want to collect the object into a particular type of collection, we must do this differently.

This is how we do it

public List<Sighting> getSightingOf(String animal)
{
    return sightings.stream()
                    .filter(record -> animal.equals(record.getAnimal()))
                    .collect(Collectors.toCollection(ArrayList::new));
}

This parameter uses a notation which is called a method reference. A method reference uses a new style of syntax, :: double colons.

There are four cases of method references

  • A reference to a constructor
    • () -> new ArrayList<>()
  • A reference to a method call
    • System.out::println
  • A reference to a static method
    • Math::abs
  • A reference to an instance method of a particular type
    • String::length

Concept Summary

  • java library The java standard class library contains many classes that are very useful. It is important to know how to use the library.
  • library documentation The java class library documentation shows detail about all classes in the library. Using this documentation is essential in order to make good use of library classes.
  • interface The interface of a class describes what a class does and how it can be used with out showing the implementation.
  • implementation The complete source code that defines a class is called the implementation of that class.
  • immutable An object is said to be immutable if it contents or state cannot be changed once it has been created. Strings are an example of immutable objects.
  • Map A map is a collection that stores key/value pairs as entries. Values can be looked up by providing the key.
  • Set A set is a collection that stores each individual element at most once. It does not maintain any specific order.
  • Autoboxing Autoboxing is performed automatically when a primitive-type value is used in a context requiring a wrapper type.
  • Documentation The documentation of a class should be detailed enough for other programmers to use the class without the need to read the implementation.
  • Access Modifier Access modifiers define the visibility of a field, constructor or method. Public elements are accessible from inside the same class and from other classes. Private elements are accessible only from within the same class.
  • Information Hiding Information hiding a principle that states the internal details of a class’s implementation should be hidden from other classes. It ensures better modularization of an application.
  • Class Variable, Static Variable Classes can have fields. These are known as class variables or static variables. Exactly one copy exists of a class variable at all times, independent of the number of created instances.

Links to other pages

Chapter 1

Chapter 2

Chapter 3

Chapter 4

Chapter 5

Chapter 6

Chapter 7

Chapter 8

Chapter 9

Chapter 10

Chapter 11

Chapter 12

Chapter 13

Chapter 14