On completion of this section you will be familiar with
Of the classes we have created up until now some of them contained only data and the methods for only updating that data or returning its values out of the class. Others however contained quite a large amount of processing. One example of the former type of class is our class Person which only contained variables for name, address and age as well as the get and set methods for updating those variables. If we want to process such things as a list of employees then having a series of Person objects is a good way of doing this. To deal with a large number of objects of Person we could have an array in which we could store the pointers to those objects. This would work fine but then we would need to write the code for processing the array, such as working out how many elements are currently there, how to add pointers either to the end of the array or somewhere in the middle, and how to delete elements from the array.
Fortunately we don’t need to write this code as Java provides a class for us called Vector which provides methods for such things as adding new pointers to the array, removing pointers etc. An object of the class contains an extendible array of pointers and we simply add pointers to our own objects to this array. Unlike arrays that we create ourselves there is no danger of going past the end of this array as it is automatically extended once it gets filled up. Similarly if we wish to conserve memory space we can remove elements of the array that don’t contain pointers.
As a first example we shall create an application that allows us to create a number of objects of the class Person, store pointers to those objects in a Vector object and finally use the utilities of the Vector object to navigate those objects, delete them or modify their contents. In fact our application will be like a simple filing system.
The class Person, whose objects we shall use to store our data in is shown in Listing 16.1 below. As it contains no new processing or features we shall not discuss it any further. It is included here for reference purposes only.
Listing 16.1
|
1 |
public class Person |
|
2 |
{ |
|
3 |
private String name,address; |
|
4 |
private int age; |
|
5 |
public Person(){} |
|
6 |
public Person(String n, String a, int ag) |
|
7 |
{ |
|
8 |
name = n; |
|
9 |
address = a; |
|
10 |
age = ag; |
|
11 |
} |
|
12 |
public void setName(String n) |
|
13 |
{ |
|
14 |
name = n; |
|
15 |
} |
|
16 |
public void setAddress(String a) |
|
17 |
{ |
|
18 |
address = a; |
|
19 |
} |
|
20 |
public void setAge(int ag) |
|
21 |
{ |
|
22 |
age = ag; |
|
23 |
} |
|
24 |
public String getName() |
|
25 |
{ |
|
26 |
return name; |
|
27 |
} |
|
28 |
public String getAddress() |
|
29 |
{ |
|
30 |
return address; |
|
31 |
} |
|
32 |
public int getAge() |
|
33 |
{ |
|
34 |
return age; |
|
35 |
} |
|
36 |
public String toString() |
|
37 |
{ |
|
38 |
String msg; |
|
39 |
msg = "Name "; |
|
40 |
msg = msg.concat(name); |
|
41 |
msg = msg.concat("\nAddress "); |
|
42 |
msg = msg.concat(address); |
|
43 |
msg = msg.concat("\nAge "); |
|
44 |
msg = msg.concat(Integer.toString(age)); |
|
45 |
return msg; |
|
46 |
} |
|
47 |
} |
Listing 16.2 below contains the class Organisation, which contains very little data, but contains an
large amount of code for processing a Vector.
Listing 16.2
|
1 |
import java.util.Vector; |
|
2 |
public class
Organisation |
|
3 |
{ |
|
4 |
private Vector people; |
|
5 |
private int current; |
|
6 |
public Organisation() |
|
7 |
{ |
|
8 |
people = new Vector(30,20); |
|
9 |
current = -1; |
|
10 |
} |
|
11 |
public boolean add(Person p) |
|
12 |
{ |
|
13 |
try |
|
14 |
{ |
|
15 |
people.add(p); |
|
16 |
return true; |
|
17 |
} |
|
18 |
catch(Exception e) |
|
19 |
{ |
|
20 |
return false; |
|
21 |
} |
|
22 |
} |
|
23 |
public boolean modify(Person p) |
|
24 |
{ |
|
25 |
try |
|
26 |
{ |
|
27 |
people.setElementAt(p, current); |
|
28 |
return true; |
|
29 |
} |
|
30 |
catch(Exception e) |
|
31 |
{ |
|
32 |
return false; |
|
33 |
} |
|
34 |
} |
|
35 |
public boolean delete() |
|
36 |
{ |
|
37 |
try |
|
38 |
{ |
|
39 |
people.remove(current); |
|
40 |
return true; |
|
41 |
} |
|
42 |
catch(Exception e) |
|
43 |
{ |
|
44 |
return false; |
|
45 |
} |
|
46 |
} |
|
47 |
public Person first() |
|
48 |
{ |
|
49 |
if(people.size()>0) |
|
50 |
{ |
|
51 |
current = 0; |
|
52 |
return
(Person)people.elementAt(current); |
|
53 |
} |
|
54 |
else |
|
55 |
{ |
|
56 |
current = -1; |
|
57 |
return null; |
|
58 |
} |
|
59 |
} |
|
60 |
public Person next() |
|
61 |
{ |
|
62 |
if(people.size()>0) |
|
63 |
{ |
|
64 |
current++; |
|
65 |
if(current >= people.size()) |
|
66 |
current = people.size()-1; |
|
67 |
return
(Person)people.elementAt(current); |
|
68 |
} |
|
69 |
else |
|
70 |
{ |
|
71 |
current = -1; |
|
72 |
return null; |
|
73 |
} |
|
74 |
} |
|
75 |
public int getCurrent() |
|
76 |
{ |
|
77 |
return current; |
|
78 |
} |
|
79 |
public int getSize() |
|
80 |
{ |
|
81 |
return people.size(); |
|
82 |
} |
|
83 |
} |
The class has only two private variables, the Vector pointer called people and the int variable called current. The latter variable will be used to tell us which element of the Vector we are currently looking at once we are navigating its contents.
Lines 6 – 10 contain the class’ constructor. All that happens here is that at line 8 a new Vector object is created and its pointer is stored in people. The two values we pass to the constructor determine the initial size of the Vector object. The first value, 30, determines the initial size of theVector’s internal array, 30 in this case. The second value determines by how much the same internal array is extended once it has become full. Thus when 30 elements are added to the array its size will still be 30 but once the 31st element is added its size is increased to 50. Similarly when we try to add the 51st element its size is increased to 70.
The first method, add, spans lines 11 – 22. The method has a single argument, which is a pointer to an object of the class Person. It is this pointer that will be added to the Vector. The body of the method is a try..catch block. At line 15 the add method of the Vector object is called and the pointer p is passed to it. This simply causes that pointer to be stored in the first available element of the internal array of the Vector object. On the other hand if an exception has been thrown for any reason the body of the catch will return a false value at line 20.
The method modify spans lines 23 – 34. It has the same basic structure as the add method and thus we shall only discuss the body of its try block. In our case when we wish to modify the contents of a Person object we simply replace its pointer in the array with the pointer of another Person object that contains the modified data. Thus at line 27 the method setElementAt of the Vector class replaces the pointer at the position indicated by current with the new pointer stored in p. Due to Java’s internal organization the old object, once it loses its pointer is automatically destroyed, or in other words the memory space allocated to it is freed up for other applications to use.
The delete method spans lines 35 – 46 and again contains a try..catch construct. Again only the element specified by current can be removed. To do this we call the remove method of the Vector object. This method removes the element at the position specified. If this happens to be in the middle of the array all pointers following it are move up one position in order to close the gap.
Now we come to the first of our navigation methods, the method first. This method returns a pointer to an object of the class Person. Its body consists of a if..else construct. At first the size of the array is checked for being greater than zero, at line 49. This is to prevent us trying to navigate an empty array. If the test is true then the variable current is set to zero. This is because, like the arrays we have seen earlier, the Vector starts counting its elements beginning at zero. At line 52 the elementAt method of the Vector object is used to return a pointer to the element stored at position zero. This pointer is then returned out of the method to whichever piece of code that calls it. Notice that between the keyword return and the rest of the line we have (Person). This an example of what is referred to as type casting. The reason for it is that in a Vector pointers to any type of objects can be stored. Thus the method elementAt returns a pointer to the class Object which is the parent class of all other classes. The method first however has been designed to return pointers to objects of the class Person and the type casting here simply converts a pointer to the class Object to pointer to Person.
The method next spans lines 60 – 74. For the same reason as its predecessor, its body consists of an if..else construct. In the body of the if at line 64 the variable current is incremented. This is in order that it will point to the next element of the Vector’s array. Continuously doing this could however eventually make current point beyond the end of the array. For that reason, at lines 65 and 66, the value of current is tested for being greater than the size of the internal array or in other words of pointing beyond the array. If this is the case then at line 66 current is revalued to point to the last element of the array.
Below in Fig 16.1 is a form that we can use as a user interface for our Vector application. The three text fields will be used to hold the name, address and age as they are entered by the user at the keyboard while the buttons will activate the code for processing the data in the text fields.

Fig 16.1
In Listing 16.3 below is part of the code behind the form. Only the parts required for explanation have been included here.
Listing 16.3
| 1 |
JTextField nameField = new JTextField(); |
| 2 |
JTextField addressField = new JTextField(); |
| 3 |
JTextField ageField = new JTextField(); |
| 4 |
JLabel jLabel1 = new JLabel(); |
| 5 |
JLabel jLabel2 = new JLabel(); |
| 6 |
JLabel jLabel3 = new JLabel(); |
| 7 |
JButton addButton = new JButton(); |
| 8 |
JButton modifyButton = new JButton(); |
| 9 |
JButton deleteButton = new JButton(); |
| 10 |
JButton firstButton = new JButton(); |
| 11 |
JButton nextButton = new JButton(); |
| 12 |
JButton lastButton = new JButton(); |
| 13 |
JButton previousButton = new JButton(); |
| 14 |
JButton exitButton = new JButton(); |
| 15 |
Organisation org = new Organisation(); |
| 16 |
public void addButton_actionPerformed(ActionEvent
e) |
| 17 |
{ |
| 18 |
org.add(new Person(nameField.getText(),addressField.getText(),Integer.parseInt(ageField.getText().trim()))); |
| 21 |
} |
| 22 |
public void firstButton_actionPerformed(ActionEvent
e) |
| 23 |
{ |
| 24 |
displayData(org.first()); |
| 25 |
} |
| 26 |
public void nextButton_actionPerformed(ActionEvent
e) |
| 27 |
{ |
| 28 |
displayData(org.next()); |
| 29 |
} |
| 30 |
public void modifyButton_actionPerformed(ActionEvent
e) |
| 31 |
{ |
| 32 |
if(org.modify(new Person(nameField.getText(),addressField.getText(),Integer.parseInt(ageField.getText().trim())))) |
| 35 |
this.setTitle("Record modified"); |
| 36 |
else |
| 37 |
this.setTitle("Cannot modify record"); |
| 38 |
} |
| 39 |
public void deleteButton_actionPerformed(ActionEvent
e) |
| 40 |
{ |
| 41 |
if(org.delete()) |
| 42 |
this.setTitle("Record deleted"); |
| 43 |
else |
| 44 |
this.setTitle("Cannot delete record"); |
| 45 |
} |
| 46 |
private void displayData(Person p) |
| 47 |
{ |
| 48 |
if(p != null) |
| 49 |
{ |
| 50 |
nameField.setText(p.getName()); |
| 51 |
addressField.setText(p.getAddress()); |
| 52 |
ageField.setText(Integer.toString(p.getAge())); |
| 53 |
String title = "Record "; |
| 54 |
title = title.concat(Integer.toString(org.getCurrent()+1)); |
| 55 |
title = title.concat(" of "); |
| 56 |
title = title.concat(Integer.toString(org.getSize())); |
| 57 |
this.setTitle(title); |
| 58 |
} |
| 59 |
} |
The first line to pay attention to is line 15. Here, after visual objects such as the text fields, labels and buttons have been created we insert ourselves an object of the class Organisation. Remember that once we create such an object, its constructor runs, which creates a Vector object so that we shall be able to add Person objects to it.
Modifying a record means overwriting its contents with the data currently
on the screen. The code for it spans lines 30 – 38. Its logic is similar to
adding a new record. A new Person object is crated and its constructor is
passed the values extracted from the name, address, and age fields. The pointer
to this object is passed to the modify method of the object org.
Browsing the data is simply using the actionPerformed events of the first,
last, next and previous buttons. These simply call the first, last, next and
previous methods of the object org. these methods return a pointer to an object
of Person. This pointer is then passed to the method displayData.
The method displayData spans lines 46 – 58. The body of the method consists
of an if construct which checks whether the pointer passed to it is null.
If it is not null then the name, address and age is extracted from the Person
object and stored in the name, address and age text fields of the form. Lines
53 – 57 build up a string to indicate where in the vector we are and display
the value of the string in the title bar of the form. If we were half ways
through a vector that had 20 objects attached to it then our display would
read Record 10 of 20.
A vector is an object that holds an array of pointers to other objects. It
has facilities for adding more pointers to the array, deleting individual
pointers and scanning the array by moving forward, backwards, going to the
first pointer or to the last one.
Create a new project and copy the codes from listings 16-1 and 16-2 into it.
Next create a form as in Fig 16.1. Ensure that you name the objects in the
form appropriately. Now add your own code to the form so that an Organsiation
object will be attached to the form, then add code to the actionPerformed
events of all of the buttons so that the data can be processed correctly.
Use listing 16.3 as a reference for adding this code.
Exercise 16.1
Extend Exercise 15.1 as follows: