|
|
As mentioned, String is a system-defined class--not a primitive--defined in java.lang, the core package of supplemental class definitions included with all Java(TM) distributions. The lang package is considered so essential that no steps are neccessary by the programmer to use its classes. A quick examination of java.lang.String shows an extensive number of methods for string manipulation. The lang package also provides a complementary class, java.lang.StringBuffer. String instances are immutable; that is, they cannot be modified. To use equivalent terminology, String operations are nondestructive. A programmer simply creates strings, uses them, and when there is no further reference to them, the Java interpreter's garbage collection facility (Garbage collection) recovers the storage space. Most of the string-oriented tasks necessary for normal programming can be accomplished with instances of String (which is quite efficient), for example, creating string constants, concatenating strings, and so on. StringBuffer, on the other hand, is more powerful. It includes many methods for destructive string operations, for example, substring and character-level manipulation of strings such as splicing one or more characters into the middle of a string. A good rule of thumb is to use String wherever possible, and consider StringBuffer only when the functionality provided by String is inadequate. In an earlier panel, we performed a common display operation involving strings, namely:
System.out.println("x = " + x);
This simple line of code demonstrates several string-related issues. First, note that println() accepts one argument, which is satisfied by the result of the expression evaluation that includes +. In this context, + performs a string concatenation. Because + is recognized by the Java compiler as a string concatenation operator, the compiler will automatically generate the code to convert any non-String operands to String instances. In this case, if x is an int with the value 5, its value will be converted, generating the string constant "5". The latter is concatenated with "x = " producing "x = 5", the single argument to println(). Thus, in the earlier example, we had the code
int x = 4;
x++; // same effect as ++x
System.out.println("x = " + x);
which produced the output:
x = 5
Note that you can use this automatic conversion and concatenation anywhere, not just as an argument to a method such as println(). This feature is incredibly powerful and convenient, demonstrating once again Java's syntactic power:
String waterCoolerGreeting;
if (employee.getAge() > 40) {
waterCoolerGreeting =
employee.getFirstName() +
"! Wow, what's it like to be " +
employee.getAge() + "?";
}
else
waterCoolerGreeting =
"Hi, " + employee.getFirstName() + "!"
Another issue is the use of a double quote-delimited character sequence directly, for example, "x = ". Because String is a class, the general way to create a string instance is:
String prompt = new String("x = ");
Note that we have to provide a string in order to create a string! As a convenience for the programmer, Java always recognizes a sequence of characters between double quotes as a string constant; hence, we can use the following short-cut to create a String instance and assign it to the reference variable prompt:
String prompt = "x = ";
String barkSound = "Woof.";
One final issue is that automatic conversion to a String instance works for objects as well as for integers and other primitives. How? All Java classes are a specialization of the most general Java class java.lang.Object, which implies that all classes automatically inherit its toString() method. (Class inheritance is beyond the scope of this tutorial, but this one issue is quite interesting and useful now.) During automatic conversions of objects to strings, the Java compiler invokes an object's toString() method to do this object-specific conversion. The toString() method inherited from Object does very little--a placeholder method really. For every class we design, we can (and should) provide a simple toString() method that concatenates together pertinent information for that instance. It is definitely worth the effort to provide toString() because it is incredibly useful in debugging operations. Assuming the existence of several additional instance variables and access methods that distinguish one dog from another, let's define a toString() method that returns a collection of descriptive information about an instance of Dog:
class Dog {
String barkSound = "Woof.";
String name = "none";
String breed = "unknown";
boolean gentle = true;
boolean obedienceTrained = false;
int age = 0;
...
public String toString() {
return "[name = " + name + "] " +
"[breed = " + breed + "] " +
"[age = " + age + "] ";
}
...
The test program TestDogToString uses the Dog instance directly in a display statement:
public class TestDogToString {
public static void main(String[] args) {
Dog bruno = new Dog();
bruno.setBark("RRUUFFFF.");
bruno.setName("Bruno");
bruno.setBreed("Newfoundland");
bruno.setAge(14);
bruno.bark();
System.out.println(bruno); // automatic conversion
}
}
Running this program displays:
RRUUFFFF.
[name = Bruno] [breed = Newfoundland] [age = 14]
For now, note that the toString() method must have the public modifier. Java is a powerful language and many of its features such as inheritance, data and method accessibility, and others are discussed elsewhere. The toString() functionality is convenient and warrants early coverage, despite these unaddressed issues. It's a very good idea to include a toString() method for every user-defined data type. Exercisecopyright 1996-2000 Magelang Institute dba jGuru |
|