ZeePedia

JAVA: Modification of Address Book Code

<< JAVA: Streams
JAVA: Graphical User Interfaces >>
img
Web Design & Development ­ CS506
VU
Lesson 9
Modification of Address Book Code
Adding Persistence Functionality
Hopefully, your address book you built previously is giving you the required results except one i.e.
persistence. You might have noticed that after adding some person records in the address book; if you
exit form the program next time on re-executing address book all the previous records are no more
available.
To overcome the above problem, we will modify our program so that on exiting/starting of address
book, all the previously added records are available each time. To achieve this, we have to provide the
persistence functionality. Currently, we will accomplish this task by saving person records in some text
file.
Supporting simple persistence by any application requires handling of two scenarios. These are
On start up of application ­ data (person records ) must be read from file
On end/finish up of application ­ data (person records) must be saved in file
To support persistence, we have to handle the above mentioned scenarios
Scenario 1 ­ Start Up
Establish a data channel with a file by using streams
Start reading data (person records) from file line by line
Construct PersonInfo objects from each line you have read
Add those PersonInfo objects in arraylist persons.
Close the stream with the file
Perform these steps while application is loading up
We will read records from a text file named persons.txt. The person records will be present in the file in
the following format.
Ali,defence,9201211
Usman,gulberg,5173940
Salman,LUMS,5272670
persons.txt
As you have seen, each person record is on a separate line. Person's name, address &
phone number is separated using comma (,).
We will modify our AddressBook.java by adding a new method loadPersons into it. This method
will provide the implementation of all the steps. The method is shown below:
public void loadPersons ( ){
String tokens[] = null;
String name, add, ph;
65
img
Web Design & Development ­ CS506
VU
try {
FileReader fr = new FileReader("persons.txt");
BufferedReader br = new BufferedReader(fr);
String line = br.readLine();
while ( line != null ) {
tokens = line.split(",");
name = tokens[0];
add = tokens[1];
ph = tokens[2];
PersonInfo p = new PersonInfo(name, add, ph);
persons.add(p);
line = br.readLine();
}
br.close();
fr.close();
}catch(IOException ioEx){
System.out.println(ioEx);
}
}
First, we have to connect with the text file in order to read line by line person records from it. This
task is accomplished with the following lines of code
FileReader fr = new FileReader("persons.txt"); BufferedReader br = new
BufferedReader(fr);
FileReader is a character based (node) stream that helps us in reading data in the form of
characters. As we are using  streams, so we have to import the  java.io package in the
AddressBook class.
We passed the file name persons.txt to the constructor of the FileReader.
Next we add BufferedReader (filter stream) on top of the FileReader because BufferedReader
facilitates reading data line by line. (As you can recall from the lecture that filter streams are
attached on top of node streams). That's why the constructor of BufferedReader is receiving the
fr ­ the FileReader object.
The next line of code will read line from file by using readLine( ) method of
BufferedReader and save it in a string variable called line.
String line = br.readLine( );
After that while loop starts. The condition of while loop is used to check whether the file is reached
to end (returns null) or not. This loop is used to read whole file till the end. When end comes (null),
this loop will finish.
66
img
Web Design & Development ­ CS506
VU
while (line != null)
Inside loop, the first step we performed is tokenizing the string. For this purpose, we have used
split method of String class. This method returns substrings (tokens) according to the regular
expression or delimiter passed to it.
tokens = line.split(",");
The return type of this method is array of strings that's why we have declared tokens as a String
array in the beginning of this method as
String tokens[];
For example, the line contains the following string
Ali,defence,9201211
Now by calling split(",") method on this string, this method will return back three substrings ali
defence and 9201211 because the delimiter we have passed to it is comma. The delimiter itself
is not included in the substrings or tokens.
The next three lines of code are simple assignments statements. The tokens[0] contains the name
of the person because the name is always in the beginning of the line, tokens[1] contains address
of the person and tokens[2] contains the phone number of the person.
name = tokens[0];
add = tokens[1];
ph = tokens[2];
The name, add and ph are of type String and are declared in the beginning of this method.
After that we have constructed the object of PersonInfo class by using parameterized constructor
and passed all these strings to it.
PersonInfo p = new PersonInfo(name, add, ph);
Afterward the PersonInfo object's p is added to the arraylist i.e. persons. persons.add(p);
The last step we have done inside loop is that we have again read a line form the file by using the
readLine() method.
By summarizing the task of while loop we can conclude that it reads the line from a file,
tokenizethat line into three substrings followed by constructing the PersonInfo object by
using these tokens. And adding these objects to the arraylist. This process continues till the file
reaches its end.
The last step for reading information from the file is ordinary one ­ closing the streams,
because files are external resources, so it's better to close them as soon as possible.
Also observe that we used try/catch block because using streams can result in raising exceptions
that falls under the checked exceptions category ­ that needs mandatory handling.
The last important step you have to perform is to call this method while loading up. The most
67
img
Web Design & Development ­ CS506
VU
appropriate place to call this method is from inside the constructor of AddressBook.java. So
the constructor will now look like similar to the one given below:
..................
public AddressBook () {
Persons = new ArrayList();
loadPersons();
}
..................
AddressBook.java
Scenario 2 ­ End/Finish Up
Establish a datachanel(stream) with a file by using streams
Take out PersonInfo objects from ArrayList (persons)
Build a string for each PersonInfo object by inserting commas (,) between name
& address and address & phone number.
Write the constructed string to the file
Close the connection with file
Perform these steps while exiting from address book.
Add  another  method  savePersons  into  AddressBook.java.  This  method  will provide
the
implementation of all the above mentioned steps. The method is shown below:
Public void savePersons ( ){
try {
PersonInfo p;
String line;
FileWriter fw = new FileWriter("persons.txt");
PrintWriter pw = new PrintWriter(fw);
for(int i=0; i<persons.size(); i++)
{
p = (PersonInfo)persons.get(i);
line = p.name +","+ p.address +","+ p.phoneNum;
// writes line to file (persons.txt)
pw.println(line);
}
pw.flush();
pw.close();
68
img
Web Design & Development ­ CS506
VU
fw.close();
}catch(IOException ioEx){
System.out.println(ioEx);
}
}
As you can see, that we have opened the same file (persons.txt) again by using a set of streams.
After that we have started for loop to iterate over arraylist as we did in
searchPerson and deletePerson methods.
Inside for loop body, we have taken out PersonInfo object and after type casting it we have assigned its
reference to a PersonInfo type local variable p. This is achieved by the help of following line of code
p = (PersonInfo)persons.get(i);
Next we build a string and insert commas between the PersonInfo attributes and assign the newly
constructed string to string's local variable line as shown in the following line of code.
line = p.name +","+ p.address +","+ p.phoneNum;
Note: Since, we haven't declare PersonInfo attributes private, therefore we are able to directly access
them inside AddressBook.java.
The next step is to write the line representing one PersonInfo object's information, to the file. This
is done by using println method of PrintWriter as shown below
pw.println(line);
After writing line to the file, the println method will move the cursor/control to the next line.
That's why each line is going to be written on separate line.
The last step for saving information to the file is ordinary one ­ closing the streams but before
that notice the code line that you have not seen/performed while loading persons records from file.
That is
pw.flush( );
The above line immediately flushes data by writing any buffered output/data to file. This step is
necessary to perform or otherwise you will most probably lose some data for the reason that
PrintWriter is a Buffered Stream and they have their own internal memory/storage capacity for
efficiency reasons. Buffered Streams do not send the data until their memory is full.
Also we have written this code inside try-catch block.
The last important step you have to perform is to call this method before exiting from the address
book. The most appropriate place to call this method is under case 4
(exit scenario) in Test.java. So the case 4 will now look like similar to the one given below:
69
img
Web Design & Development ­ CS506
VU
case 4:
ab.savePersons();
System.exit(0);
Test.java
Compile & Execute
Now again after compiling all the classes, run the Test class. Initially we are assuming that out
persons.txt file is empty, so our arraylist persons will be empty on the first start up of address book.
Now add some records into it, perform search or delete operations. Exit from the address book
by  choosing  option  4.  Check  out  the persons.txt file. Don't get surprised by seeing that it
contains all the person records in the format exactly we have seen above.
Next time you will run the address book; all the records will be available to you. Perform the search or
delete operation to verify that.
Finally You have done it !!!
References
Example code, their explanations and corresponding figures for this handout are taken from the book
JAVA A Lab Course by Umair Javed. This material is available just for the use of VU students of the
course Web Design and Development and not for any other commercial purpose without the consent of
author.
Abstract Classes and Interfaces
Problem and Requirements
Before moving on to abstract classes, first examine the following class hierarchy shown below:
Circle
Square
·
Suppose that in order to exploit polymorphism, we specify that 2-D objects must be able to
compute their area.
­ All 2-D classes must respond to area() message.
·
How do we ensure that?
­ Define area method in class Shape
­ Force the subclasses of Shape to respond area() message
·
Java's provides us two solutions to handle such problem
­ Abstract Classes
­ Interfaces
70
img
Web Design & Development ­ CS506
VU
Abstract Classes
Abstract classes are used to define only part of an implementation. Because, information is not
complete therefore an abstract class cannot be instantiate. However, like regular classes, they can
also contain instance variables and methods that are full implemented. The class that inherits from
abstract class is responsible to provide details.
Any class with an abstract method (a method has no implementation similar to pure virtual
function in C++) must be declared abstract, yet you can declare a class abstract that has no abstract
method.
If subclass overrides all abstract methods of the super class, than it becomes a concrete (a class whose
object can be instantiate) class otherwise we have to declare it as abstract or we can not compile it.
The most important aspect of abstract class is that reference of an abstract class can point to the object of
concrete classes.
Code Example of Abstract Classes
The Shape class contains an abstract method calculateArea() with no definition.
public abstract class Shape{
public abstract void calculateArea();
}
Class Circle extends from abstract Shape class, therefore to become concrete class it must provides
the definition of calculateArea() method.
public class Circle extends Shape {
private int x, y;
private int radius;
public Circle() {
x = 5;
y = 5;
radius = 10;
}
// providing definition of abstract method
public void calculateArea () {
double area = 3.14 * (radius * radius);
System.out.println("Area: " + area);
}
}//end of class
The Test class contains main method. Inside main, a reference s of abstract Shape class is created. This
reference can point to Circle (subclass of abstract class Shape) class object as it is a concrete class.
With the help of reference, method calculateArea() can be invoked of Circle class. This is all shown
in the form of code below
public class Test {
71
img
Web Design & Development ­ CS506
VU
public static void main(String args[]){
//can only create references of A.C.
Shape s = null;
//Shape s1 = new Shape(); //cannot instantiate
//abstractclass reference can point to concrete subclass
s = new Circle();
s.calculateArea();
}
}//end of class
The compilation and execution of the above program is shown below:
Interfaces
As we seen one possible java's solution to problem discussed in start of the tutorial. The second possible
java's solution is Interfaces.
Interfaces are special java type which contains only a set of method prototypes, but doest not provide
the implementation for these prototypes. All the methods inside an interface are abstract by default thus
an interface is tantamount to a pure abstract class ­ a class with zero implementation. Interface can
also contains static final constants
Defining an Interface
Keyword interface is used instead of class as shown below:
public interface Speaker{
public void speak();
}
Implementing (using) Interface
Classes implement interfaces. Implementing an interface is like signing a contract. A class that
implements an interface will have to provide the definition of all the methods that are present inside
72
img
Web Design & Development ­ CS506
VU
an interface. If the class does not provide definitions of all methods, the class would not compile.
We have to declare it as an abstract class in order to get it compiled.
Relationship between a class and interface is equivalent to "responds to" while "is a"
relationship exists in inheritance.
Code Example of Defining & Implementing an Interface
The interface Printable contains print() method.
public interface Printable{
public void print();
}
Class Student is implementing the interface Printable. Note the use of keyword implements after the
class name. Student class has to provide the definition of print method or we are unable to compile.
The code snippet of student class is given below:
public class Student implements Printable {
private String name;
private String address;
public String toString () {
return "name:"+name +" address:"+address;
}
//providing definition of interface's print method
public void print() {
System.out.println("Name:" +name+" address"+address);
}
}//end of class
Interface Characteristics
Similar to abstract class, interfaces imposes a design structure on any class that uses the interface.
Contrary to inheritance, a class can implement more than one interfaces. To do this separate the
interface names with comma. This is java's way of multiple inheritance.
class Circle implements Drawable , Printable { .......... }
Objects of interfaces also cannot be instantiated.
Speaker s = new Speaker(); // not compile
However, a reference of interface can be created to point any of its implementation class. This is
interface based polymorphism.
Code Example: Interface based polymorphism
Interface Speaker is implemented by three classes Politician, Coach and Lecturer. Code snippets of all
these three classes are show below:
73
img
Web Design & Development ­ CS506
VU
public class Politician implements Speaker{
public void speak(){
System.out.println("Politics Talks");
}
}
public class Coach implements Speaker{
public void speak(){
System.out.println("Sports Talks");
}
}
public class Lecturer implements Speaker{
public void speak(){
System.out.println("Web Design and Development Talks");
}
}
As usual, Test class contains main method. Inside main, a reference sp is created of Speaker class.
Later, this reference is used to point to the objects of Politician, Coach and Lecturer class. On calling
speak method with the help of sp, will invoke the method of a class to which sp is pointing.
public class Test{
public static void main (String args[ ]) {
Speaker sp = null;
System.out.println("sp pointing to Politician");
sp = new Politician();
sp.speak();
System.out.println("sp pointing to Coach");
sp = new Coach();
sp.speak();
System.out.println("sp pointing to Lecturer");
sp = new Lecturer();
sp.speak();
}
}
The compilation and execution of the above program is shown below:
74
img
Web Design & Development ­ CS506
VU
References
Example code, their explanations and corresponding figures for this handout are taken from the book
JAVA A Lab Course by Umair Javed. This material is available just for the use of VU students of the
course Web Design and Development and not for any other commercial
purpose without the
consent of author.
75