Escolar Documentos
Profissional Documentos
Cultura Documentos
Reference:
For more information on the material covered in this handout, you should take some
time to look at the Sun Java Tutorial, for which there is a link on the intranet, under
the materials listing for this course. See in particular the topics 'Object Basics and
Simple Data Objects', under 'Learning the Java Language'. See also the 'Collections'
topic, under 'Specialized Trails'. Some of the code examples in this handout are taken
from this tutorial.
1 Overview
This handout covers some important information about the life cycle of objects
(garbage collection and finalisers) and also briefly describes some useful built-in Java
classes (for working with strings and collections).
This is because Java automatically carries out a process called garbage collection.
An object becomes eligible for garbage collection when there are no longer any
references to it.
References held in a variable are usually dropped when the variable goes out of scope.
It is also possible to explicitly drop an object reference in code by setting the variable
to the special value null.
The Java interpreter keeps track of objects and arrays that it allocates to memory
addresses. It also tracks the objects and arrays that local variables refer to and what
objects and arrays refer to other objects and arrays.
Because it tracks all this information, the interpreter can determine when an allocated
object is no longer referred to by any other object or variable.
When the interpreter finds an object that is no longer referenced by any other object
or variable, it can safely destroy the object and release any resources used by the
object. It can also detect where there is a circular reference between objects not
referenced anywhere else i.e. where object A refers to object B and object B refers to
object A and destroy those objects.
1
A memory leak occurs when memory is allocated and never reclaimed. Many memory leaks in a
program could lead to worsening performance.
Page 1 of 13
8966480.doc FBE – Computer Science Dept
The garbage collector runs in the background – doing most of its work when other
processes are not using system resources. This means that the process of garbage
collection does not generally slow down the system.
It is possible to explicitly run the garbage collector e.g. after a piece of code that is
known to create a large amount of garbage. It can be run by calling the gc method of
the System class.
3 Finalizers
The Java garbage collector is efficient and is usually sufficient to ensure that all
allocated resources are released back to the system.
However, there are some resources that are not automatically released by the garbage
collector. These are resources that are outside the control of Java, for example if an
object opens a file or a network connection.
In these cases, it is necessary to explicitly release the resources in the code.
This is done using a finalizer method (which is similar to a destructor in C++).
The finalizer method takes no arguments and does not return a value. Finalizer
methods are usually declared protected but can also be public.
Every object inherits a standard finalize method from the Object super class. If a class
needs to explicitly release resources, it overrides this method and should call
super.finalize() as part of the implementation, to ensure that the Object.finalize()
method is eventually called.
For example, a class that may have created a text file that is used only by this class
should delete the file when it is finished. The finalizer method for this class might
look like the following.
You should note that generally, you do not need to worry about finalizer methods but
if your class deals with files or network objects, then it is necessary.
Note that the finalizer method is invoked at some time after the object becomes
unused (i.e. no references remain to the object) but before the garbage collector
destroys the object.
Page 2 of 13
8966480.doc FBE – Computer Science Dept
Both result in a new string object containing the characters '13 Months of Sunshine'
being created.
String objects are immutable – that is, once a String object is created, it does not
change. If you assign a different set of characters to a variable of type String, a new
object is created. The String object is not very efficient for working with changing
strings.
The StringBuffer class represents a string of characters that can change i.e. the
characters can be changed, added to and removed from the string. Therefore it is said
that a StringBuffer is mutable.
If you are writing code that needs to manipulate the data in a string e.g. adding more
characters to a string, changing the order of the characters, then you should use a
StringBuffer as it is more efficient (using the String class would result in more objects
being allocated to memory).
The StringBuffer class has different constructors – one that takes a string value and
one that takes an integer value that specifies the length i.e. the number of characters
the object can hold. The signatures for these constructors are as follows:
The table below lists some useful methods on String and StringBuffer classes.
Page 3 of 13
8966480.doc FBE – Computer Science Dept
The comparison operator for equality is = =. However, when used with reference data
types, this tests whether the operands refer to the same object or array. When used
with primitive data types, it tests whether the operand values themselves are identical.
Using = = with strings can lead to unexpected results.
To compare the actual characters of String objects, the equals() method of the String
class should be used. For example:
Page 4 of 13
8966480.doc FBE – Computer Science Dept
See the class DemoEquality in Code Examples\Demos for an example showing where
= = returns an unexpected result for two strings that contain the same characters.
All Java objects have a method toString(), inherited from the super class Object, that
converts the object to a string representation. For example, to convert a StringBuffer
to a String:
For many objects, the default string representation is not very meaningful – it may
consist of an internal identifier assigned by the Java interpreter. Many classes in the
java.lang package override toString() to provide more meaningful representations e.g.
the Exception classes and the wrapper classes for the primitive data types (Boolean,
Character, Integer etc)
You can override the toString() method on your classes also, which can be useful for
passing references as String parameters or for debugging.
The String class also has a class (static) method valueOf() that can be used to convert
variables of different types to strings. For example, to print the value of pi:
System.out.println(String.valueOf(Math.PI));
4.2 java.util.StringTokenizer
The StringTokenizer class can be used to break a string of text into the words that
make up the text. The default behaviour is for the tokenizer to separate words at space
characters. It can be set to look for a different separator character e.g. a colon.
A tokenizer is often required to parse entered data e.g. a program that accepts
commands from the input needs to be able to parse the command string.
Page 5 of 13
8966480.doc FBE – Computer Science Dept
The above program would output each token on a new line, like this:
13
Months
of
Sunshine
4.3 Collections
Java has a number of classes that can be used when working with collections of
objects. These are the Collection classes; they are all part of the java.util package.
A collection can hold an arbitrary number of elements, with each element being
another object.
There are various collection objects that provide different types of functionality, such
as storing the objects in order, sorting and preventing duplicate entries.
The elements in a collection are zero-index based i.e. the first element is always at
index 0.
The List interface represents an ordered collection of objects – each element in a List
has an index, or position, in the list. When elements are inserted into the List, the
Page 6 of 13
8966480.doc FBE – Computer Science Dept
order of the elements is maintained in the List – when the elements are returned from
the List, they are in the same order in which they were added into it. Elements can be
inserted, queried and removed by index.
Another interface, Map, does not extend the Collection interface but is another class
often used for handling collections of objects. Each item in a Map consists of two
objects - a key object and a value object. Items in a Map can be referenced by their
key values. The set of key objects in a Map cannot contain duplicates, but the value
objects can. Each key object can map to at most one value object.
An example of a map is a list of names and phone numbers. When you want to find a
phone number, you look up the name in a phone book and then read the number for
that name.
The SortedMap interface extends the Map interface and keeps its set of key objects
in sorted order.
The Iterator interface defines methods for iterating (looping) through a collection
from the first element to the last element. Any class that implements the Collection
interface (or one of its sub-interfaces) implements an iterator() method that returns an
iterator for that collection. The iterator can be used to loop through all the elements in
the collection.
Methods on an Iterator object are shown in the table below.
Method Description
hasNext() Returns true if there is another element in the collection
next() Returns the next object (element) in the collection
remove() Deletes from the collection the last item that was returned using next()
In earlier versions of Java (prior to 1.2), the Vector class provided similar
functionality to an ArrayList. Vector may still be used, but generally, an ArrayList is
better.
The ArrayList class is an implementation of the List interface, so it inherits various
methods from the interface and implements them. Objects of any class can be placed
into an ArrayList.
Unlike an array, the type of objects that will be placed into the ArrayList does not
have to be declared, and the object types can be different.
Page 7 of 13
8966480.doc FBE – Computer Science Dept
The constructor for an ArrayList can take no parameters, or it can take a value for the
capacity (how many elements it can hold) of the ArrayList or it can take another
Collection object.
If the capacity is not specifed, the ArrayList will grow automatically as new elements
are added. However, this means that a new array to hold the values is created when it
is grown. Therefore, it is more efficient to specify the capacity if it is known.
Useful methods on the ArrayList class are shown below. The column 'Inherited From'
shows which methods are inherited from the Collection interface and which from the
List interface. Methods inherited from the Collection interface are also available on
classes that implement the Set interface, as Set extends Collection also.
Note that because a List is ordered, elements can be referenced by their position in the
collection i.e. by index e.g. set(), get(), remove() methods can all take an index value
as a parameter. This is not possible with a Set.
Page 8 of 13
8966480.doc FBE – Computer Science Dept
For example, to create an ArrayList named items and to add an object (from some
class, let us call it SomeClass – its declaration is not shown here) as the first element:
Note that in the iteration above, the type declared for the item variable is Object – this
should be used if there are different types of object in the array. However, if the
objects are all of the same type i.e. from the same class or super class, then that type
can be used. Remember also that System.out.println will invoke the toString() method
of the item parameter if it is not a String object.
The HashSet class is an implementation of the Set interface. Any type of object can be
added to a HashSet and null objects can also be added.
Unlike the ArrayList, it does not allow duplicate elements i.e. two objects that are the
same. The add(Object o) method returns a boolean – true if the object is successfully
added, false if not (because the object already exists in the set).
As a Set is an unordered collection, the order in which the items in the set are returned
by the iterator() method may not be the same as the order in which the objects were
added.
Some of the methods of the HashSet class are shown in the table below. The interface
from which they are inherited is also shown. Note that the methods inherited from the
Set interface implement the standard mathematical set operations such as union,
intersection, subset and difference.
Page 9 of 13
8966480.doc FBE – Computer Science Dept
in the HashSet
contains(Object o) Returns true if the HashSet Collection
contains the specified object o
toArray() Returns an array containing all Collection
the objects in the HashSet – this is
useful if you need to pass the
collection of objects to some
other method, as an array can be
more efficient
isEmpty() Returns true if the HashSet is Collection
empty i.e. if it has no elements in
it
iterator() Returns an Iterator object for the Collection
collection; as a List is ordered, the
order of the elements in the
iterator is the same as the order in
which they were added.
containsAll (Collection c) Returns true if the HashSet Set
contains all the objects in c i.e. if
c is a subset of the HashSet
addAll(Collection c) Adds the objects in c to the Set
HashSet but does not add
duplicates i.e. performs set union
retainAll (Collection c) Retains in the HashSet only those Set
objects that are also in c i.e.
performs a set intersection
removeAll (Collection c) Removes from the HashSet any Set
objects that are in c i.e. performs
a set difference
The two examples below show some of the set methods in use on a HashSet object.
Note that this code declares the variable to be of the type Set (an interface) but creates
an object from the HashSet class (e.g. Set s = new HashSet()). Because HashSet
inherits from, or implements, Set, this is allowed. In this case, Set is the static type of
the variable and HashSet is the dynamic type of the variable.
Using the interface type (Set) as the variable type is a good idea because it allows the
programmer to change the implementation type from HashSet to some other
implementation of Set later on, if necessary.
Example 1 – using the add() method – run this class with a set of words on the
command line – it detects any duplicate words:
import java.util.*;
Page 10 of 13
8966480.doc FBE – Computer Science Dept
import java.util.*;
The HashMap class is an implementation of the Map interface. Java uses an internal
hashtable to store a hashmap. A key-value pair is added to a Map using the put()
method; the get() method returns the value object for a given key.
The Map interface provides three views that return different Collections – keySet,
values and entrySet – these can be used to iterate through the keys and/or the values.
The existence of a given key or value can be checked for using the containsKey() and
containsValue() methods.
Page 11 of 13
8966480.doc FBE – Computer Science Dept
The Collections class defines various static methods and constants that are useful for
working with collections, for example methods to sort a collection.
See the DemoHashMap class for an example of usage of the Collections.sort()
method.
Method Description
Collections.sort Sorts the list object. This sort uses the natural order of the objects. For
(java.util.list list) strings, this is alphabetical, for numerical values it is the numerical
order.
4.4 java.util.Random
The Random class, part of the java.util package, is a class that can be used to generate
random numbers. Some of the methods on this class are shown below.
Method Description
Random() Constructor
nextInt() Returns a random integer value
nextInt(int n) Returns a random integer value between 0 and n (>=0, < n)
nextLong() Returns a random long value
nextBoolean() Returns a random boolean value
If you need to generate random numbers in a program, create one instance of the
Random class and use it each time you need to generate a number. If you create a new
instance each time, the numbers may not be very random.
Page 12 of 13
8966480.doc FBE – Computer Science Dept
For example:
Random randomGenerator;
randomGenerator = new Random();
int theNumber = randomGenerator.nextInt();
//use theNumber
………
//generate another random number
theNumber = randomGenerator.nextInt();
The implementation of the Random class in Java uses an algorithm that generates
pseudo-random numbers. This means that they are not truly random. This is because it
is difficult to generate truly random numbers on a computer – because computers
work in a way that is very well-defined and deterministic.
The algorithms often used to generate random numbers actually follow rules, but the
rules are very complicated. Unless you are working on a program that requires
extremely high security, the Random class should produce sufficiently random
numbers for you!
Page 13 of 13