PROBLEMS
(Top)
An instance of a String is immutable. It can not be changed. An instance of a StringBuffer contains a string that can be changed.
public class FormatBuffer extends StringBuffer
{
... see assignment
}
The purpose of the FormatBuffer class is to create objects that have all of the operations of a StringBuffer plus an operation that can append an integer right justified in a specified width.
The problem is that StringBuffer is declared a final class so that it can not be extended.
Because String and StringBuffer are heavily used, they should be as efficient as possible. Making them final allows the compiler to generate more efficient code because there is no chance that a subclass might override one of it methods.
The best that we can do is to create a new class that uses an associated StringBuffer. The only way to get the new class to have all of the operations of StringBuffer is to also implement them in the new class. But, at least we can delegate the work to the associated buffer. This will give something like:
public class FormatBuffer
{
private StringBuffer buffer;
public FormatBuffer(int initSize)
{
buffer = new StringBuffer(initSize);
}
public void append(int inum, int width)
{
String snum = String.valueOf(inum);
int fill = width - snum.length();
while (fill-- > 0)
buffer.append(' ');
buffer.append(snum);
}
//StringBuffer operations
public FormatBuffer append(boolean boo)
{
buffer.append(boo);
}
public FormatBuffer append(char ch)
{
buffer.append(ch);
}
......
......
}
Perhaps this new class should have some additional capabilities
including such things as:
public class Equation ...
Equation = 3.0*X*X + 2.0*X + 1.0 for x = 1.0, value = 6.0 x value greater than 10.0
The String mess, isBad(), and getMessage() all deal with handling errors. They can be eliminated if exceptions are used. The best solution is to code an EquationException class. In an exam where time is critical, we might cut corners and just use a generic Exception. Here, we will do it right. The code for the exception class is:
public class EquationException extends Exception
{
public EquationException()
{
super();
}
|
The code for the revised equation class is:
public class Equation
{
//Coefficients
private double aCoef;
private double bCoef;
private double cCoef;
|
Note that in the event of an error, the orignal test program just quit using the System.exit() operation. So, it is not necessary to have multiple try blocks since only one error message can ever be printed.
public static void main(String[] args)
{
double value;
//Create equation
Equation eq = new Equation(3.0,2.0,1.0);
System.out.println("Equation = " + eq.toString());
//Evaluate
try
{
value = eq.evaluate(1.0);
show(1.0,value);
value = eq.evaluate(12.0);
show(12.0,value);
}
catch (EquationException error)
{
System.out.println(error.getMessage());
}
}
|
EXERCISES
(Top)
The solution to this exercise is contained in the following source files:
Two of the new methods are worth exploring. One is setMailName():
public void setMailName(String mailName)
throws PersonNameException
{
//Construct parser
StringTokenizer parser = new StringTokenizer(mailName);
//Examine number of parts
int parts = parser.countTokens();
if (parts < 2)
throw new PersonNameException
(this,"Mail name has too few parts");
if (parts > 3)
throw new PersonNameException
(this,"Mail name has too many parts");
//Parse name into parts
firstName = parser.nextToken();
if (parts == 3)
midName = parser.nextToken();
else
midName = null;
lastName = parser.nextToken();
//Invalidate formatted names
invalidate();
}
|
Note the use of an instance of the StringTokenizer class to parse the components of the mail name. This class makes it relatively easy to program the method. It also makes it easier to understand what the method is trying to accomplish.
Also note the use of a private invalidate() method to invalidate the formatted names. Rather than duplicate the code that sets the formatted names to null, that code was "factored" out of setName(). This means that if we ever change the way we invalidate the formatted names, there will only be one place that hase to be changed.
The other method is equals():
public boolean equals(Object obj)
{
//False if different object type
if (!(obj instanceof PersonName))
return(false);
//Cast to PersonName
PersonName other = (PersonName)obj;
//Compare names
if (!other.firstName.equals(this.firstName))
return(false);
if (!other.midName.equals(this.midName))
return(false);
return(other.lastName.equals(this.lastName));
}
|
Since we need to override the method as declared in the Object class, the parameter can not be typed as a PersonName. So, the method must ensure that the object that is passed is a PersonName before it can do the compare. In practice, you might want to consider both overriding and overloading the equals method:
public boolean equals(PersonName other)
{
//Compare names
if (!other.firstName.equals(this.firstName))
return(false);
if (!other.midName.equals(this.midName))
return(false);
return(other.lastName.equals(this.lastName));
}
public boolean equals(Object obj)
{
//If a PersonName return equals result
if (obj instanceof PersonName)
return(equals((PersonName)obj)));
//Not a PersonName so it can't be equal
return(false);
}
If you compile the classes and execute PersonNameTest,
you should get the following output:
-- INIT TEST NAME
Person: Name: last=March first=David mid=L.
getFirstName: David
getMidName: L.
getLastName: March
getMailName: David L. March
getListName: March, David L.
Person: Name: last=Doe first=John mid=null
getFirstName: John
getMidName: null
getLastName: Doe
getMailName: John Doe
getListName: Doe, John
Person: Name: last=April first=David mid=L.
getFirstName: David
getMidName: L.
getLastName: April
getMailName: David L. April
getListName: April, David L.
Person: Name: last=April first=David mid=L.
getFirstName: David
getMidName: L.
getLastName: April
getMailName: David L. April
getListName: April, David L.
Person: Name: last=Smith first=Robert mid=null
getFirstName: Robert
getMidName: null
getLastName: Smith
getMailName: Robert Smith
getListName: Smith, Robert
** PersonName error Mail name has too many parts
PersonName: Name: last=null first=null mid=null
PersonNameException: Mail name has too many parts
at java.lang.Throwable.(Compiled Code)
at PersonName.setMailName(Compiled Code)
at PersonName.(Compiled Code)
at PersonNameTest.execute(PersonNameTest.java:40)
at PersonNameTest.main(PersonNameTest.java:50)
-- TERM TEST NAME
Type any char to exit ...
Prepared by David L. March -- Last Revised on September 25, 1998
COPYRIGHT © 1998 BY DAVID L. MARCH