| ## Java 1.1 Unleashed # - 10- The Language Package by Michael Morrison IN THIS CHAPTER The Object Class Data Type Wrapper Classes The Math Class The String Classes The System and Runtime Classes The Class Classes The Java language package is the heart of the Java language. In this chapter, you learn more about some of the classes that make up the language package (`java.lang`). You'll find that many of the classes in the language package are indispensable when you are writing Java programs. The language package contains many classes, each with a variety of member variables, member constants, and methods. You don't learn about every class and every method in this chapter (that would simply be too much material to cover in a single chapter). Rather, you focus on the most important classes in the language package--the classes that are the most useful as you begin developing your own Java classes. Please note that although the multithreading and error-handling classes are part of the language package, they aren't covered in this chapter; Chapter 6, "Threads and Multithreading," and Chapter 7, "Exception Handling," are devoted to these classes. ## The Object Class The `Object` class is probably the most important of all Java classes, simply because it is the superclass of all Java classes. It is important to have a solid understanding of the `Object` class because all the classes you develop inherit the variables and methods of `Object`. The `Object` class implements the following important methods: `Object clone()` `boolean equals(Object` obj`)` `int hashCode()` `final Class getClass()` `String toString()` ### The clone() Method `Object clone()` The `Object clone()` method creates a clone of the object on which it is called. `clone()` creates and allocates memory for the new object being copied to. `clone()` actually creates a new object and then copies the contents of the calling object to the new object. An example of using the `clone()` method follows:
    Circle circle1 = new Circle(1.0, 3.5, 4.2);
    Circle circle2 = circle1.clone();
In this example, the `circle1` object is created, but the `circle2` object is only declared. `circle2` is not created by using the `new` operator; it is created when `circle1` calls the `clone()` method to create a clone of itself. ### The equals() Method `boolean equals(Object` obj) The `equals()` method compares two objects for equality. `equals()` is applicable only when both objects have been stored in a hash table. ### The hashCode() Method `int hashCode()` The `hashCode()` method returns the hashcode value for an object. Hashcodes are integers that uniquely represent objects in the Java system. ### The getClass() Method `final Class getClass()` The `getClass()` method returns the runtime class information for an object in the form of a `Class` object. The `Class` object keeps up with runtime class information such as the name of a class and the parent superclass. ### The toString() Method `String toString()` The `toString()` method returns a string representing the value of an object. Because the value of an object varies depending on the class type, it is assumed that each class will override the `toString()` method to display information specific to that class. The information returned by `toString()` can be very valuable for determining the internal state of an object when you are debugging your code. ## Data Type Wrapper Classes The data type wrapper classes provide object versions of the fundamental Java data types. Type wrapping is important because many Java classes and methods operate on classes rather than on fundamental types. Furthermore, by creating object versions of the simple data types, it is possible to add useful member functions for each data type. Following are the type wrapper classes supported by Java: `Boolean` `Byte` `Short` `Character` `Integer` `Long` `Float` `Double` `Void` Although each wrapper implements methods specific to each data type, a handful of methods are applicable to all the wrappers except the `Void` class. This is because the `Void` class serves merely as a placeholder for the primitive `void` type. The common methods implemented in the other wrapper classes follow: `ClassType(`type`)` `type` type`Value()` `int hashCode()` `String toString()` `boolean equals(Object` obj`)` `static boolean valueOf(String` s`)` NOTE: Actually, the `valueOf()` method isn't implemented in the `Character` class, but it is implemented in all the other wrapper classes. ### The ClassType() Method `ClassType(`type) The `ClassType()` method is actually the constructor for each class. The wrapper constructors take as their only parameter the `type` of data they are wrapping. This arrangement enables you to create a type wrapper from a fundamental type. For example, you can use the constructor for the `Character` class like this:
    Character c1 = new Character(`x');
### The typeValue() Method
    type typeValue()
The type`Value()` method is used to get the fundamental type back from a wrapper. type`Value()` returns a value of the same type as the fundamental type it wraps. Following is an example of how a fundamental type can be extracted from a wrapper object:
    char c2 = c1.charValue();
NOTE: Remember that fundamental types are not represented in Java by classes or objects. Data type wrapper classes provide a way of representing a fundamental type as an object, which is often useful. Wrapper classes are different from other Java classes in that their only purpose is to allow fundamental types to be represented as objects. You can easily distinguish wrapper classes from primitive types because the first letter of wrapper class names is always capitalized. ### The hashCode() Method `int hashCode()` The `hashCode()` method returns the hashcode for a type wrapper object. This `hashCode()` method is simply an overridden version of the `hashCode()` method contained in the `Object` class. ### The toString() Method `String toString()` The `toString()` method is used to get a string representation of the internal state of an object. `toString()` is typically overridden in each class so that it reflects unique state implementations. Following is an example of how you can output the state of a wrapper variable using `toString()`: `System.out.println(c1.toString());` ### The equals() Method `boolean equals(Object` obj) The `equals()` method is used to test for equality between two wrapper objects. This is the same `equals()` method that is implemented in `Object` and inherited by all other objects in Java. ### The valueOf() Method `static boolean valueOf(String` s) The `valueOf()` method is implemented in all the type wrappers except `Character`. `valueOf()`, which is `static`, is used to convert a string to a value of a particular wrapper type. `valueOf()` parses the `String` parameter s and returns its value. Now that you have an idea of what functionality all the wrapper classes share, it's time to take a look at some of the specifics of each class. ### The Boolean Class The `Boolean` class wraps the `boolean` fundamental data type. `Boolean` implements only one method in addition to the common wrapper methods already mentioned: `getBoolean()`. #### The getBoolean() Method `static boolean getBoolean(String name)` The `getBoolean()` method returns a type `boolean` that represents the boolean property value of the `String` parameter name. The name parameter refers to a property name that represents a boolean property value. Because `getBoolean()` is `static`, it is typically meant to be used without actually instantiating a `Boolean` object. NOTE: Java properties are system variables that define the characteristics of the Java runtime environment. For example, there is a property called `os.name` that specifies the name of the operating system in which the Java runtime is executing. In my case, `os.name` is set to `"Windows 95"`. #### Member Constants The `Boolean` class also includes three `final static` (`constant`) data members: `TRUE`, `FALSE`, and `TYPE`. `TRUE` and `FALSE` represent the two possible states that the `Boolean` class can represent. It is important to note the difference between `true` and `false` and `Boolean.TRUE` and `Boolean.FALSE`. The first pair applies to `boolean` fundamental types; the second pair applies to `Boolean` classes; they cannot be interchanged. The `TYPE` member constant specifies the runtime `Class` object representing the boolean value. ### The Byte and Short Classes The `Byte` class wraps the fundamental `byte` type and provides a variety of methods for working with byte numbers. Some of the more important methods implemented by `Byte` follow: `static int parseByte(String` s`, int` radix`)` `static int parseByte(String` s`)` `long shortValue()` `long longValue()` `long intValue()` `float floatValue()` `double doubleValue()` #### The parseByte() Methods
    static byte parseByte(String s, int radix)
    static byte parseByte(String s)
The `parseByte()` methods parse strings for a `byte` value and return the value as a byte. The version of `parseByte()` with the radix parameter enables you to specify the base of the byte; the other version of `parseByte()` assumes a base of 10. #### The shortValue(), longValue(), intValue(), floatValue(), and doubleValue() Methods
    short shortValue()
    long longValue()
    int intValue()
    float floatValue()
    double doubleValue()
The `shortValue()`, `longValue()`, `intValue()`, `floatValue()`, and `doubleValue()` methods return the value of a byte converted to the appropriate type. For example, the following code shows how to convert a byte to a double:
    Byte b = new Byte(43);
    Double d = b.doubleValue();
In this example, the value of the `Byte` variable `b` is converted to a `double` value and stored in the `Double` variable `d`. #### Member Constants The `Byte` class also includes three `final static` (`constant`) data members: `MIN_VALUE`, `MAX_VALUE`, and `TYPE`. `MIN_VALUE` and `MAX_VALUE` specify the smallest and largest numbers that can be represented by a `Byte` object. `TYPE` specifies the runtime `Class` object representing the byte value. The `Short` class is similar to the `Byte` class except that it wraps the fundamental type `short`. `Short` implements methods similar to those of the `Byte` class, with the exception that they act on `short`-type numbers rather than on `byte`-type numbers. ### The Character Class The `Character` class wraps the `char` fundamental type and provides some useful methods for manipulating characters. Some of the more important methods implemented by `Character` follow: `static boolean isLowerCase(char` ch`)` `static boolean isUpperCase(char` ch`)` `static boolean isDigit(char` ch`)` `static boolean isSpace(char` ch`)` `static char toLowerCase(char` ch`)` `static char toUpperCase(char` ch`)` `static int digit(char` ch`, int` radix`)` `static char forDigit(int` digit`, int` radix`)` All these methods are `static`, which means that they can be used without instantiating a `Character` object. #### The isLowerCase() and isUpperCase() Methods
    static boolean isLowerCase(char ch)
    static boolean isUpperCase(char ch)
The `isLowerCase()` and `isUpperCase()` methods return whether or not a character is an uppercase or lowercase character. An example of using the `isLowerCase()` method follows:
    Character c = new Character(`g');
    boolean isLower = Character.isLowerCase(c);
In this case, the `boolean` variable `isLower` is set to `true` because ``g'` is a lowercase character. #### The isDigit() Method `static boolean isDigit(char` ch) The `isDigit()` method simply returns whether or not a character is a digit (`0` to `9`). Following is an example of how to use the `isDigit()` method: `boolean isDigit = Character.isDigit(`7');` Here, the `boolean` variable `isDigit` is set to `true` because ``7'` is in fact a numeric digit. #### The isSpace() Method `static boolean isSpace(char` ch) The `isSpace()` method returns whether or not a character is whitespace. (Whitespace is defined as any combination of the space, tab, newline, carriage return, or linefeed characters.) Following is an example of how to use `isSpace()`: `boolean isSpace = Character.isSpace(`\t');` In this example, the `isSpace boolean` variable is set to `true` because the tab (``\t'`) character is considered whitespace. #### The toLowerCase() and toUpperCase() Methods
    static char toLowerCase(char ch)
    static char toUpperCase(char ch)
The `toLowerCase()` and `toUpperCase()` methods convert a character to a lowercase or uppercase character. If a character is already lowercase and `toLowerCase()` is called, the character is not changed. Similarly, `toUpperCase()` does nothing to uppercase characters. Following are a few examples of how to use these methods:
    char c1 = Character.toUpperCase(`g');
    char c2 = Character.toLowerCase(`M');
In the first example, `c1` is converted from ``g'` to ``G'` with the call to the `toUpperCase()` method. In the second example, `c2` is converted from ``M'` to ``m'` with the call to `toLowerCase()`. #### The digit() Method `static int digit(char ch, int radix)` The `digit()` method returns the numeric (integer) value of a character digit in base 10. The radix parameter specifies the base of the character digit for conversion. If the character is not a valid digit, `-1` is returned. Following are a few examples of using the `digit()` method:
    char c1 = `4';
    char c2 = `c';
    int four = Character.digit(c1, 10);
    int twelve = Character.digit(c2, 16);
In the first example, the character ``4'` is converted to the integer number `4` using the `digit()` method. In the second example, the hexadecimal number represented by the character ``c'` is returned as the base 10 integer number `12`. #### The forDigit() Method `static char forDigit(int digit, int radix)` The `forDigit()` method performs the reverse of the `digit()` method: It returns the character representation of an integer digit. Once again, radix specifies the base of the integer number. Following is an example of how to use `forDigit()`:
    int i = 9;
    char c = Character.forDigit(i, 10);
In this example, the integer number `9` is converted to the character ``9'` by the `forDigit()` method. #### Member Constants The `Character` class provides three `final static` data members for specifying the radix limits for conversions: `MIN_RADIX`, `MAX_RADIX`, and `TYPE`. The radix for a number is its base, such as binary, octal, or hexadecimal. These common radixes have values of `2`, `8`, and `16`, respectively. `MIN_RADIX` specifies the minimum radix (base 2) for performing numeric-to-character conversions and vice-versa. Likewise, `MAX_RADIX` specifies the maximum radix (base 36) for conversions. `TYPE` specifies the runtime `Class` object representing the character value. NOTE: The `Character` class also includes a variety of member constants representing different types of commonly used characters. Please refer to the Java 1.1 API documentation for more information on these member constants. ### The Integer and Long Classes The `Integer` and `Long` classes wrap the fundamental integer types `int` and `long` and provide a variety of methods for working with integer numbers. The methods implemented by `Integer` follow: `static int parseInt(String` s`, int` radix`)` `static int parseInt(String` s`)` `short shortValue()` `long longValue()` `float floatValue()` `double doubleValue()` `byte byteValue()` `static Integer getInteger(String` name`)` `static Integer getInteger(String` name`, int` val`)` `static Integer getInteger(String` name`, Integer` val`)` #### The parseInt() Methods
    static int parseInt(String s, int radix)
    static int parseInt(String s)
The `parseInt()` methods parse strings for an integer value and return the value as an `int`. The version of `parseInt()` with the radix parameter enables you to specify the base of the integer; the other version of `parseInt()` assumes a base of 10. #### The shortValue(), longValue(), floatValue(), doubleValue(), and byteValue() Methods
    short shortValue()
    long longValue()
    float floatValue()
    double doubleValue()
    byte byteValue()
The `shortValue()`, `longValue()`, `floatValue()`, `doubleValue(),` and`byteValue()` methods return the value of an integer converted to the appropriate type. For example, the following code shows how to convert an integer to a double:
    Integer i = new Integer(17);
    float f = i.floatValue();
In this example, the value of the `Integer` variable `i` is converted to a `float` value and is stored in the `float` variable `f`. The result is that the `Integer` value `17` is converted to the `float` value `17.0`. #### The getInteger() Methods
    static Integer getInteger(String name)
    static Integer getInteger(String name, int val)
    static Integer getInteger(String name, Integer val)
The `getInteger()` methods return an integer property value specified by the `String` property name parameter name. Notice that all three of the `getInteger()` methods are `static`, which means that you don't have to instantiate an `Integer` object to use these methods. The differences among these three methods is what happens when the integer property isn't found. The first version returns `0` if the property isn't found, the second version returns the `int` parameter `val`, and the last version returns the `Integer` object value `val`. #### Member Constants The `Integer` class also includes three `final static` (`constant`) data members: `MIN_VALUE`, `MAX_VALUE`, and `TYPE`. `MIN_VALUE` and `MAX_VALUE` specify the smallest and largest numbers that can be represented by an `Integer` object. `TYPE` specifies the runtime `Class` object representing the integer value. The `Long` class is similar to the `Integer` class except that it wraps the fundamental type `long`. The `Long` class implements methods similar to those of the `Integer` class, with the exception that they act on `long`-type numbers rather than on `int`-type numbers. ### The Float and Double Classes The `Float` and `Double` classes wrap the fundamental floating-point types `float` and `double`. These two classes provide a group of methods for working with floating-point numbers. The methods implemented by the `Float` class follow: `boolean isNaN()` `static boolean isNaN(float` v`)` `boolean isInfinite()` `static boolean isInfinite(float` v`)` `short shortValue()` `long longValue()` `int intValue()` `double doubleValue()` `byte byteValue()` `static int floatToIntBits(float` value`)` `static float intBitsToFloat(int` bits`)` #### The isNaN() Methods
    boolean isNaN()
    static boolean isNaN(float v)
The `isNaN()` method returns whether or not the `Float` value is the special not-a-number (`NaN`) value. The first version of `isNaN()` operates on the value of the calling `Float` object. The second version is `static` and takes the `float` to test as its parameter, v. #### The isInfinite() Methods
    boolean isInfinite()
    static boolean isInfinite(float v)
The `isInfinite()` method returns whether or not the `Float` value is infinite, which is represented by the special `NEGATIVE_INFINITY` and `POSITIVE_INFINITY` `final static` member constants. Like the `isNaN()` method, `isInfinite()` comes in two versions: a class value version and a `static` version that takes a `float` as an argument. #### The shortValue(), longValue(), intValue(), doubleValue(), and byteValue() Methods
    short shortValue()
    long longValue()
    int intValue()
    double doubleValue()
    byte byteValue()
The `shortValue()`, `longValue()`, `intValue()`, `doubleValue()`, and `byteValue()` methods return the values of a floating-point number converted to the appropriate type. For example, the following code shows how to convert a `Float` object to a `long` type:
    Float f = new Float(5.237);
    long l = f.longValue();
In this example, the value of the `Float` variable `f` is converted to a `long` and stored in the `long` variable `l`. This action results in the floating-point value `5.237` being converted to the `long` value `5`. #### The floatToIntBits() and intBitsToFloat() Methods
    static int floatToIntBits(float value)
    static float intBitsToFloat(int bits)
The last two methods implemented by the `Float` class are `floatToIntBits()` and `intBitsToFloat()`. The `floatToIntBits()` and `intBitsToFloat()` methods convert floating-point values to their integer bit representations and back. #### Member Constants The `Float` class also has a group of `final static` (`constant`) data members: `MIN_VALUE`, `MAX_VALUE`, `NEGATIVE_INFINITY`, `POSITIVE_INFINITY`, `NaN`, and `TYPE`. `MIN_VALUE` and `MAX_VALUE` specify the smallest and largest numbers that can be represented by a `Float` object. `NEGATIVE_INFINITY` and `POSITIVE_INFINITY` represent negative and positive infinity, while `NaN` represents the special not-a-number condition. `TYPE` specifies the runtime `Class` object representing the floating-point value. The `Double` class is very similar to the `Float` class. The only difference is that `Double` wraps the fundamental type `double` instead of `float`. `Double` implements methods similar to those of the `Float` class, with the exception that the methods act on `double`-type numbers rather than on `float`-type numbers. ### The Void Class The `Void` class is a placeholder class wrapping the primitive `void` Java data type. The `Void` class has no constructors or methods and only one member constant: `TYPE`. The `TYPE` member constant specifies the runtime `Class` object representing the `void` type. ## The Math Class The `Math` class contains many invaluable mathematical functions along with a few useful constants. The `Math` class isn't intended to be instantiated; it is basically just a holding class for mathematical functions. Additionally, the `Math` class is declared as `final`--you can't derive from it. The most useful methods implemented by the `Math` class follow: `static double sin(double` a`)` `static double cos(double` a`)` `static double tan(double` a`)` `static double asin(double` a`)` `static double acos(double` a`)` `static double atan(double` a`)` `static double exp(double` a`)` `static double log(double` a`)` `static double sqrt(double` a`)` `static double pow(double` a`, double` b`)` `static double ceil(double` a`)` `static double floor(double` a`)` `static long round(double` a`)` `static double rint(double` a`)` `static double atan2(double` a`, double` b`)` `static synchronized double random()` `static int abs(int` a`)` `static long abs(long` a`)` `static float abs(float` a`)` `static double abs(double` a`)` `static int min(int` a`, int` b`)` `static long min(long` a`, long` b`)` `static float min(float` a`, float` b`)` `static double min(double` a`, double` b`)` `static int max(int` a`, int` b`)` `static long max(long` a`, long` b`)` `static float max(float` a`, float` b`)` `static double max(double` a`, double` b`)` NOTE: Be sure that you don't confuse the `Math` class with the `java.math` package. The `Math` class is included in the `java.lang` package and provides a wide range of mathematical functions; the `java.math` package is a package unto itself that provides two support classes (`BigDecimal` and `BigInteger`) for working with large numbers. ### Trigonometric Methods
    static double sin(double a)
    static double cos(double a)
    static double tan(double a)
    static double asin(double a)
    static double acos(double a)
    static double atan(double a)
The trigonometric methods `sin()`, `cos()`, `tan()`, `asin()`, `acos()`, and `atan()` perform the standard trigonometric functions on `double` values. All the angles used in the trigonometric functions are specified in radians. Following is an example of calculating the sine of an angle: `double dSine = Math.sin(Math.PI / 2);` Notice in the example that the `PI` constant member of the `Math` class was used in the call to the `sin()` method. You learn about the `PI` member constant of `Math` at the end of this section. ### The exp(), log(), sqrt(), and pow() Methods
    static double exp(double a)
    static double log(double a)
    static double sqrt(double a)
    static double pow(double a, double b)
The `exp()` method returns the exponential number `E` raised to the power of the `double` parameter a. Similarly, the `log()` method returns the natural logarithm (base `E`) of the number passed in the parameter a. The `sqrt()` method returns the square root of the parameter number a. The `pow()` method returns the result of raising a number to a power. `pow()` returns a raised to the power of b. Following are some examples of using these `Math` methods:
    double d1 = 12.3;
    double d2 = Math.exp(d1);
    double d3 = Math.log(d1);
    double d4 = Math.sqrt(d1);
    double d5 = Math.pow(d1, 3.0);
### The ceil(), floor(), round(), and rint() Methods
    static double ceil(double a)
    static double floor(double a)
    static int round(float a)
    static long round(double a)
    static double rint(double a)
The `ceil()` and `floor()` methods return the "ceiling" and "floor" for the passed parameter a. The ceiling is the smallest whole number greater than or equal to a; the floor is the largest whole number less than or equal to a. The `round()` methods round `float` and `double` numbers to the nearest integer value, which is returned as type `int` or `long`. Both `round()` methods work by adding `0.5` to the number and then returning the largest integer that is less than or equal to the number. The `rint()` method returns an integer value, similar to `round()`, that remains a type `double`. Following are some examples of using these methods:
    double d1 = 37.125;
    double d2 = Math.ceil(d1);
    double d3 = Math.floor(d1);
    int i = Math.round((float)d1);
    long l = Math.round(d1);
    double d4 = Math.rint(d1);
Notice in the first example that uses `round()` that the `double` value `d1` must be explicitly cast to a `float`. This is necessary because this version of `round()` takes a `float` and returns an `int`. ### The atan2() Method `static double atan2(double` a, double b) The `atan2()` method converts rectangular coordinates to polar coordinates. The `double` parameters a and b represent the rectangular x and y coordinates to be converted to polar coordinates, which are returned together as a single `double` value. ### The random() Method `static synchronized double random()` The `random()` method generates a pseudo-random number between `0.0` and `1.0`. `random()` is useful for generating random floating-point numbers. To generate random numbers of different types, you should use the `Random` class, which is located in the utilities package, `java.util`. The utilities package, including the `Random` class, is covered in the next chapter. ### The abs() Methods
    static int abs(int a)
    static long abs(long a)
    static float abs(float a)
    static double abs(double a)
The `abs()` methods return the absolute values of numbers of varying types. There are versions of `abs()` for the following types: `int`, `long`, `float`, and `double`. Following is an example of using the `abs()` method to find the absolute value of an integer number:
    int i = -5, j;
    j = Math.abs(i);
### The min() and max() Methods
    static int min(int a, int b)
    static long min(long a, long b)
    static float min(float a, float b)
    static double min(double a, double b)
    static int max(int a, int b)
    static long max(long a, long b)
    static float max(float a, float b)
    static double max(double a, double b)
The `min()` and `max()` methods return the minimum and maximum numbers given a pair of numbers to compare. Like the `abs()` methods, the `min()` and `max()` methods come in different versions for handling the types `int`, `long`, `float`, and `double`. Following are some examples of using the `min()` and `max()` methods:
    double d1 = 14.2, d2 = 18.5;
    double d3 = Math.min(d1, d2);
    double d4 = Math.max(d1, 11.2);
Beyond the rich set of methods provided by the `Math` class, there are also a couple of important member constants: `E` and `PI`. The `E` member represents the exponential number (`2.7182...`) used in exponential calculations. The `PI` member represents the value of [pi] (`3.1415...`). ## The String Classes Text strings in Java are represented with classes rather than with character arrays (as they are in C and C++). The two classes that model strings in Java are `String` and `StringBuffer`. The reason for having two string classes is that the `String` class represents constant (immutable) strings and the `StringBuffer` class represents variable (mutable) strings. ### The String Class The `String` class is used to represent constant strings. The `String` class has less overhead than `StringBuffer`, which means that you should use it if you know that a string is constant. The constructors for the `String` class follow: `String()` `String(String` value`)` `String(char` value`[])` `String(char` value`[], int` offset`, int` count`)` `String(byte` ascii`[], int` offset`, int` count`, String` enc`)` `String(byte` ascii`[], String` enc`)` `String(StringBuffer` buffer`)` It should be readily apparent from the number of constructors for `String` that there are many ways to create `String` objects. The first constructor simply creates a new string that is empty. All the other constructors create strings that are initialized in different ways from various types of text data. Following are examples of using some of the `String()` constructors to create `String` objects:
    String s1 = new String();
    String s2 = new String("Hello");
    char cArray[] = {`H', `o', `w', `d', `y'};
    String s3 = new String(cArray);
    String s4 = new String(cArray, 1, 3);
In the first example, an empty `String` object (`s1`) is created. In the second example, a `String` object (`s2`) is created from a literal `String` value, `"Hello"`. The third example shows a `String` object (`s3`) being created from an array of characters. The fourth example shows a `String` object (`s4`) being created from a subarray of characters. The subarray is specified by passing `1` as the `offset` parameter and `3` as the `count` parameter. This means that the subarray of characters is to consist of the three consecutive characters starting one character into the array. The resulting subarray in this case consists of the characters ``o'`, ``w'`, and ``d'`. Once you have some `String` objects created, you are ready to work with them using some of the powerful methods implemented in the `String` class. Some of the most useful methods provided by the `String` class follow: `int length()` `char charAt(int` index`)` `boolean startsWith(String` prefix`)` `boolean startsWith(String` prefix`, int` toffset`)` `boolean endsWith(String` suffix`)` `int indexOf(int` ch`)` `int indexOf(int` ch`, int` fromIndex`)` `int indexOf(String` str`)` `int indexOf(String` str`, int` fromIndex`)` `int lastIndexOf(int` ch`)` `int lastIndexOf(int` ch`, int` fromIndex`)` `int lastIndexOf(String` str`)` `int lastIndexOf(String` str`, int` fromIndex`)` `String substring(int` beginIndex`)` `String substring(int` beginIndex`, int` endIndex`)` `boolean equals(Object` anObject`)` `boolean equalsIgnoreCase(String` anotherString`)` `int compareTo(String` anotherString`)` `String concat(String` str`)` `String replace(char` oldChar`, char` newChar`)` `String trim()` `String toLowerCase()` `String toUpperCase()` `static String valueOf(Object` obj`)` `static String valueOf(char` data`[])` `static String valueOf(char` data`[], int` offset`, int` count`)` `static String valueOf(boolean` b`)` `static String valueOf(char` c`)` `static String valueOf(int` i`)` `static String valueOf(long` l`)` `static String valueOf(float` f`)` `static String valueOf(double` d`)` #### The length(), charAt(), startsWith(), and endsWith() Methods
    int length()
    char charAt(int index)
    boolean startsWith(String prefix)
    boolean startsWith(String prefix, int toffset)
    boolean endsWith(String suffix)
The `length()` method simply returns the length of a string, which is the number of Unicode characters in the string. The `charAt()` method returns the character at a specific index of a string specified by the `int` parameter index. The `startsWith()` and `endsWith()` methods determine whether or not a string starts or ends with a prefix or suffix string, as specified by the prefix and suffix parameters. The second version of `startsWith()` enables you to specify an offset to begin looking for the string prefix. Following are some examples of using these methods:
    String s1 = new String("This is a test string!");
    int len = s1.length();
    char c = s1.charAt(8);
    boolean b1 = s1.startsWith("This");
    boolean b2 = s1.startsWith("test", 10);
    boolean b3 = s1.endsWith("string.");
In this series of examples, a `String` object is first created with the value `"This is a test string!"`. The length of the string is calculated using the `length()` method and stored in the integer variable `len`. The length returned is `22`, which specifies how many characters are contained in the string. The character at offset `8` into the string is then obtained using the `charAt()` method. As is true with C and C++, Java offsets start at `0`, not `1`. If you count eight characters into the string, you can see that `charAt()` returns the ``a'` character. The next two examples use the `startsWith()` method to determine whether specific strings are located in the `String` object. The first `startsWith()` example looks for the string `"This"` at the beginning of the `String` object. This example returns `true` because the string is in fact located at the beginning of the `String` object. The second `startsWith()` example looks for the string `"test"` beginning at offset `10` into the `String` object. This call also returns `true` because the string `"test"` is located 10 characters into the `String` object. The last example uses the `endsWith()` method to check for the occurrence of the string `"string."` at the end of the `String` object. This call returns `false` because the `String` object actually ends with `"string!"`. #### The indexOf() and lastIndexOf() Methods
    int indexOf(int ch)
    int indexOf(int ch, int fromIndex)
    int indexOf(String str)
    int indexOf(String str, int fromIndex)
    int lastIndexOf(int ch)
    int lastIndexOf(int ch, int fromIndex)
    int lastIndexOf(String str)
    int lastIndexOf(String str, int fromIndex)
The `indexOf()` method returns the location of the first occurrence of a character or string within a `String` object. The first two versions of `indexOf()` determine the index of a single character within a string; the second two versions determine the index of a string of characters within a string. Each pair of `indexOf()` methods contains a version for finding a character or string based on the beginning of the `String` object, as well a version that enables you to specify an offset into the string to begin searching for the first occurrence. If the character or string is not found, `indexOf()` returns `-1`. The `lastIndexOf()` methods work very much like `indexOf()`, with the exception that `lastIndexOf()` searches backwards through the string. Following are some examples of using these methods:
    String s1 = new String("Saskatchewan");
    int i1 = s1.indexOf(`t');
    int i2 = s1.indexOf("chew");
    int i3 = s1.lastIndexOf(`a');
In this series of examples, a `String` object is created with the value `"Saskatchewan"`. The `indexOf()` method is then called on this string with the character value ``t'`. This call to `indexOf()` returns `5` because the first occurrence of ``t'` is five characters into the string. The second call to `indexOf()` specifies the string literal `"chew"`. This call returns `6` because the substring `"chew"` is located six characters into the `String` object. Finally, the `lastIndexOf()` method is called with a character parameter of ``a'`. The call to `lastIndexOf()` returns `10`, indicating the position of the third ``a'` in the string. (Remember that `lastIndexOf()` searches backwards through the string to find the first occurrence of a character.) #### The substring() Methods
    String substring(int beginIndex)
    String substring(int beginIndex, int endIndex)
The `substring()` methods return a substring of the calling `String` object. The first version of `substring()` returns the substring beginning at the index specified by beginIndex, through the end of the calling `String` object. The second version of `substring()` returns a substring beginning at the index specified by beginIndex and ending at the index specified by endIndex. Following is an example using some of the `substring()` methods:
    String s1 = new String("sasquatch");
    String s2 = s1.substring(3);
    String s3 = s1.substring(2, 7);
In this example, a `String` object is created with the value `"sasquatch"`. A substring of this string is then retrieved using the `substring()` method and passing `3` as the beginIndex parameter. This results in the substring `"quatch"`, which begins at the string index of `3` and continues through the rest of the string. The second version of `substring()` is then used with starting and ending indices of `2` and `7`, yielding the substring `"squat"`. #### The equals(), equalsIgnoreCase(), and compareTo() Methods
    boolean equals(Object anObject)
    boolean equalsIgnoreCase(String anotherString)
    int compareTo(String anotherString)
There are two methods for determining equality between `String` objects: `equals()` and `equalsIgnoreCase()`. The `equals()` method returns a boolean value based on the equality of two strings. `equalsIgnoreCase()` performs a similar function except that it compares the strings with case insensitivity. Similarly, the `compareTo()` method compares two strings and returns an integer value that specifies whether the calling `String` object is less than, greater than, or equal to the anotherString parameter. The integer value returned by `compareTo()` specifies the numeric difference between the two strings. It is a positive value if the calling `String` object is greater; it is negative if the passed `String` object is greater. If the two strings are equal, the return value is `0`. Wait a minute--if strings are just text, how can you get a numeric difference between two strings or establish which one is greater than or less than the other? When strings are compared using the `compareTo()` method, each character is compared to the character at the same position in the other string until they don't match. When two characters are found that don't match, `compareTo()` converts them to integers and finds the difference. This difference is what is returned by `compareTo()`. Check out the following example to get a better idea of how this works:
    String s1 = new String("abcfj");
    String s2 = new String("abcdz");
    System.out.println(s1.compareTo(s2));
Each pair of characters is compared until two are encountered that don't match. In this example, the ``f'` and ``d'` characters are the first two that don't match. Because the `compareTo()` method is called on the `s1` `String` object, the integer value of ``d'` (`100`) is subtracted from the integer value of ``f'` (`102`) to determine the difference between the strings. Notice that all characters following the two nonmatching characters are ignored in the comparison. #### The concat() Method `String concat(String` str) The `concat()` method is used to concatenate two `String` objects. The string specified in the `str` parameter is concatenated on to the end of the calling `String` object. Following are a few examples of string concatenation:
    String s1 = new String("I saw sasquatch ");
    String s2 = new String(s1 + "in Saskatchewan.");
    String s3 = s1.concat("in Saskatchewan.");
In these concatenation examples, a `String` object is first created with the value `"I saw sasquatch"`. The first concatenation example shows how two strings can be concatenated using the addition operator (`+`). The second example shows how two strings can be concatenated using the `concat()` method. In both examples, the resulting string is the sentence `"I saw sasquatch in Saskatchewan."`. #### The replace() Method `String replace(char` oldChar, char newChar) The `replace()` method is used to replace characters in a string. All occurrences of oldChar are replaced with newChar. Using the strings from the previous concatenation examples, you can replace all the `s` characters with `m` characters like this: `String s4 = s3.replace(`s', `m');` This results in the string `"I maw mamquatch in Samkatchewan."`. Notice that the uppercase `S` character wasn't replaced. #### The trim(), toLowerCase(), and toUpperCase() Methods
    String trim()
    String toLowerCase()
    String toUpperCase()
The `trim()` method trims leading and trailing whitespace from a `String` object. The `toLowerCase()` and `toUpperCase()` methods are used to convert all the characters in a `String` object to lowercase and uppercase characters. Following are some examples of these methods using the strings from the previous two examples:
    String s5 = new String("\t Yeti\n");
    String s6 = s5.trim();
    String s7 = s3.toLowerCase();
    String s8 = s4.toUpperCase();
In this example, the `trim()` method is used to strip off the leading and trailing whitespace, resulting in the string `"Yeti"`. The call to `toLowerCase()` results in the string `"i saw sasquatch in saskatchewan."`. The only characters modified were the `I` and `S` characters, which were the only uppercase characters in the string. The call to `toUpperCase()` results in the string `"I MAW MAMQUATCH IN SAMKATCHEWAN."`. All the lowercase characters were converted to uppercase, as you might have guessed! #### The valueOf() Methods
    static String valueOf(Object obj)
    static String valueOf(char data[])
    static String valueOf(char data[], int offset, int count)
    static String valueOf(boolean b)
    static String valueOf(char c)
    static String valueOf(int i)
    static String valueOf(long l)
    static String valueOf(float f)
    static String valueOf(double d)
Finally, the `valueOf()` methods all return `String` objects that represent the particular type taken as a parameter. For example, the `valueOf()` method that takes an `int` returns the string `"123"` when passed the integer number `123`. ### The StringBuffer Class The `StringBuffer` class is used to represent variable, or nonconstant, strings. The `StringBuffer` class is useful when you know that a string will change in value or in length. The constructors for the `StringBuffer` class follow: `StringBuffer()` `StringBuffer(int` length`)` `StringBuffer(String` str`)` The first constructor simply creates a new string buffer that is empty. The second constructor creates a string buffer that is length characters long, initialized with spaces. The third constructor creates a string buffer from a `String` object. This last constructor is useful when you have to modify a constant `String` object. Following are examples of using the `StringBuffer` constructors to create `StringBuffer` objects:
    String s1 = new String("This is a string!");
    String sb1 = new StringBuffer();
    String sb2 = new StringBuffer(25);
    String sb3 = new StringBuffer(s1);
Some of the most useful methods implemented by `StringBuffer` follow: `int length()` `int capacity()` `synchronized void setLength(int` newLength`)` `synchronized char charAt(int` index`)` `synchronized void setCharAt(int` index`, char` ch`)` `synchronized StringBuffer append(Object` obj`)` `synchronized StringBuffer append(String` str`)` `synchronized StringBuffer append(char` c`)` `synchronized StringBuffer append(char` str`[])` `synchronized StringBuffer append(char` str`[], int` offset`, int` len`)` `StringBuffer append(boolean` b`)` `StringBuffer append(int` I`)` `StringBuffer append(long` l`)` `StringBuffer append(float` f`)` `StringBuffer append(double` d`)` `synchronized StringBuffer insert(int` offset`, Object` obj`)` `synchronized StringBuffer insert(int` offset`, String` str`)` `synchronized StringBuffer insert(int` offset`, char` c`)` `synchronized StringBuffer insert(int` offset`, char` str`[])` `StringBuffer insert(int` offset`, boolean` b`)` `StringBuffer insert(int` offset`, int` I`)` `StringBuffer insert(int` offset`, long` l`)` `StringBuffer insert(int` offset`, float` f`)` `StringBuffer insert(int` offset`, double` d`)` `String toString()` #### The length(), capacity(), and setLength() Methods
    int length()
    int capacity()
    synchronized void setLength(int newLength)
The `length()` method is used to get the length of, or number of characters in, the string buffer. The `capacity()` method is similar to `length()` except that it returns how many characters a string buffer has allocated in memory, which is sometimes greater than the length. Characters are allocated for a string buffer as they are needed. Frequently, more memory is allocated for a string buffer than is actually being used. In these cases, the `capacity()` method returns the amount of memory allocated for the string buffer. You can explicitly change the length of a string buffer using the `setLength()` method. An example of using `setLength()` is to truncate a string by specifying a shorter length. The following example shows the effects of using these methods:
    StringBuffer s1 = new StringBuffer(14);
    System.out.println("capacity = " + s1.capacity());
    System.out.println("length = " + s1.length());
    s1.append("Bigfoot");
    System.out.println(s1);
    System.out.println("capacity = " + s1.capacity());
    System.out.println("length = " + s1.length());
    s1.setLength(3);
    System.out.println(s1);
    System.out.println("capacity = " + s1.capacity());
    System.out.println("length = " + s1.length());
The resulting output of this example follows:
    capacity = 14
    length = 0
    Bigfoot
    capacity = 14
    length = 7
    Big
    capacity = 14
    length = 3
In this example, the newly created string buffer shows a capacity of `14` (based on the value passed in the constructor) and a length of `0`. After appending the string `"Bigfoot"` to the buffer, the capacity remains the same but the length grows to `7`, which is the length of the string. Calling `setLength()` with a parameter of `3` truncates the length down to `3`, but leaves the capacity unaffected at `14`. #### The charAt() and setCharAt() Methods `synchronized char charAt(int` index) `synchronized void setCharAt(int` index, char ch) The `charAt()` method returns the character at the location in the string buffer specified by the index parameter. You can change characters at specific locations in a string buffer using the `setCharAt()` method. The `setCharAt()` method replaces the character at index with the ch character parameter. The following example shows the use of these two methods:
    StringBuffer s1 = new StringBuffer("I saw a Yeti in Yellowstone.");
    char c1 = s1.charAt(9);
    System.out.println(c1);
    s1.setCharAt(4, `r');
    System.out.println(s1);
In this example, the call to `charAt()` results in the character `e`, which is located nine characters into the string. The call to `setCharAt()` results in the following output, based on the `w` in `saw` being replaced by `r`: `I sar a Yeti in Yellowstone.` #### The append() and insert() Methods
    synchronized StringBuffer append(Object obj)
    synchronized StringBuffer append(String str)
    synchronized StringBuffer append(char c)
    synchronized StringBuffer append(char str[])
    synchronized StringBuffer append(char str[], int offset, int len)
    StringBuffer append(boolean b)
    StringBuffer append(int I)
    StringBuffer append(long l)
    StringBuffer append(float f)
    StringBuffer append(double d)
    synchronized StringBuffer insert(int offset, Object obj)
    synchronized StringBuffer insert(int offset, String str)
    synchronized StringBuffer insert(int offset, char c)
    synchronized StringBuffer insert(int offset, char str[])
    StringBuffer insert(int offset, boolean b)
    StringBuffer insert(int offset, int I)
    StringBuffer insert(int offset, long l)
    StringBuffer insert(int offset, float f)
    StringBuffer insert(int offset, double d)
The `StringBuffer` class implements a variety of overloaded `append()` and `insert()` methods. The `append()` methods allow you to append various types of data on to the end of a `String` object. Each `append()` method returns the `String` object on which it was called. The `insert()` methods enable you to insert various data types at a specific offset in a string buffer. `insert()` works in a manner similar to `append()`, with the exception of where the data is placed. Following are some examples of using `append()` and `insert()`:
    StringBuffer sb1 = new StringBuffer("2 + 2 = ");
    StringBuffer sb2 = new StringBuffer("The tires make contact ");
    sb1.append(2 + 2);
    sb2.append("with the road.");
    sb2.insert(10, "are the things on the car that ");
In this set of examples, two string buffers are created using the constructor for `StringBuffer` that takes a string literal. The first `StringBuffer` object initially contains the string `"2 + 2 = "`. The `append()` method is used to append the result of the integer calculation `2 + 2`. In this case, the integer result `4` is converted by the `append()` method to the string `"4"` before it is appended to the end of the `StringBuffer` object. The value of the resulting `StringBuffer` object is `"2 + 2 = 4"`. The second string buffer object begins life with the value `"The tires make contact "`. The string `"with the road."` is then appended to the end of the string buffer using the `append()` method. Then the `insert()` method is used to insert the string `"are the things on the car that "`. Notice that this string is inserted at index `10` within the `StringBuffer` object. The string that results after these two methods are called follows: `The tires are the things on the car that make contact with the road.` #### The toString() Method `String toString()` The last method of interest in `StringBuffer` is the `toString()` method. `toString()` returns the `String` object representation of the calling `StringBuffer` object. `toString()` is useful when you have a `StringBuffer` object but need a `String` object. ## The System and Runtime Classes The `System` and `Runtime` classes provide access to the system and runtime environment resources. The `System` class is defined as `final` and is composed entirely of `static` variables and methods, which means that you never actually instantiate an object of it. The `Runtime` class provides direct access to the runtime environment and is useful for executing system commands and determining things like the amount of available memory. ### The System Class The `System` class contains the following useful methods: `static long currentTimeMillis()` `static void arraycopy(Object` src`, int` src_position`, Object` dst`, int` dst_position`, int` length`)` `static Properties getProperties()` `static String getProperty(String` key`)` `static String getProperty(String` key`, String` def`)` `static void setProperties(Properties` props`)` `static void gc()` `static void loadLibrary(String` libname`)` #### The currentTimeMillis() Method `static long currentTimeMillis()` The `currentTimeMillis()` method returns the current system time in milliseconds. The time is specified in GMT (Greenwich Mean Time) and reflects the number of milliseconds that have elapsed since midnight on January 1, 1970. This is a standard frame of reference for computer time representation. #### The arraycopy() Method `static void arraycopy(Object` src, int src_position, Object dst, int dst_position, int length) The `arraycopy()` method copies data from one array to another. `arraycopy()` copies length elements from the src array beginning at position src_position to the dst array starting at dst_position. #### The getProperties(), getProperty(), and setProperties() Methods
    static Properties getProperties()
    static String getProperty(String key)
    static String getProperty(String key, String def)
    static void setProperties(Properties props)
The `getProperties()` method gets the current system properties and returns them using a `Properties` object. There are also two `getProperty()` methods in the `System` class that allow you to get individual system properties. The first version of `getProperty()` returns the system property matching the key parameter passed into the method. The second version of `getProperty()` does the same as the first except that it returns the default def parameter if the property isn't found. The `setProperties()` method takes a `Properties` object and sets the system properties with it. #### The gc() Method `static void gc()` The `gc()` method stands for garbage collection and does exactly that. `gc()` forces the Java runtime system to perform a memory garbage collection. You can call `gc()` if you think the system is running low on memory because a garbage collection event usually frees up memory. #### The loadLibrary() Method `static void loadLibrary(String` libname) The Java system supports executable code in dynamic link libraries. A dynamic link library is a library of Java classes that can be accessed at run time. The `loadLibrary()` method is used to load a dynamic link library. The name of the library to load is specified in the libname parameter. #### Member Variables The `System` class contains three member variables that are very useful for interacting with the system: `in`, `out`, and `err`. The `in` member is an `InputStream` object that acts as the standard input stream. The `out` and `err` members are `PrintStream` objects that act as the standard output and error streams. ### The Runtime Class The `Runtime` class is another very powerful class for accessing Java system-related resources. Following are a few of the more useful methods in the `Runtime` class: `static Runtime getRuntime()` `long freeMemory()` `long totalMemory()` `void gc()` `synchronized void loadLibrary(String` libname`)` #### The getRuntime(), freeMemory(), and totalMemory() Methods `static Runtime getRuntime() long freeMemory() long totalMemory()` The `static` method `getRuntime()` returns a `Runtime` object representing the runtime system environment. The `freeMemory()` method returns the amount of free system memory in bytes. Because `freeMemory()` returns only an estimate of the available memory, it is not completely accurate. If you want to know the total amount of memory accessible by the Java system, you can use the `totalMemory()` method. The `totalMemory()` method returns the number of bytes of total memory; the `freeMemory()` method returns the number of bytes of available memory. Listing 10.1 contains the source code for the `Memory` program, which displays the available free memory and total memory. #### Listing 10.1. The Memory class.
    class Memory {
      public static void main (String args[]) {
        Runtime runtime = Runtime.getRuntime();
        long freeMem = runtime.freeMemory() / 1024;
        long totalMem = runtime.totalMemory() / 1024;
        System.out.println("Free memory : " + freeMem + "KB");
        System.out.println("Total memory : " + totalMem + "KB");
      }
    }
An example of the output of running the `Memory` program follows:
    Free Memory : 3068KB
    Total Memory : 3071KB
The `Memory` class uses the `getRuntime()`, `freeMemory()`, and `totalMemory()` methods of the `Runtime` class. Note that you can convert the amount of memory returned by each method from bytes to kilobytes by dividing by `1024`. #### The gc() and loadLibrary() Methods
    void gc()
    synchronized void loadLibrary(String libname)
The other two methods of importance in the `Runtime` class (`gc()` and `loadLibrary()`) work exactly the same as the versions that belong to the `System` class. ## The Class Classes Java provides two classes in the language package for dealing with classes: `Class` and `ClassLoader`. The `Class` class allows you access to the runtime information for a class. The `ClassLoader` class provides support for dynamically loading classes at run time. ### The Class Class Some of the more useful methods implemented by the `Class` class follow: `static Class forName(String` className`)` `String getName()` `Class getSuperclass()` `ClassLoader getClassLoader()` `boolean isInterface()` `String toString()` #### The forName() Method `static Class forName(String` className) The `forName()` method is a `static` method used to get the runtime class descriptor object for a class. The `String` parameter className specifies the name of the class about which you want information. `forName()` returns a `Class` object containing runtime information for the specified class. Notice that `forName()` is `static` and is the method you typically use to get an instance of the `Class` class for determining class information. Following is an example of how to use the `forName()` method to get information about the `StringBuffer` class: `Class info = Class.forName("java.lang.StringBuffer");` #### The getName() Method `String getName()` The `getName()` method retrieves the string name of the class represented by a `Class` object. Following is an example of using the `getName()` method: `String s = info.getName();` #### The getSuperclass(), getClassLoader(), and isInterface() Methods
    Class getSuperclass()
    ClassLoader getClassLoader()
    boolean isInterface()
The `getSuperclass()` method returns a `Class` object containing information about the superclass of an object. The `getClassLoader()` method returns the `ClassLoader` object for a class or `null` if no class loader exists. The `isInterface()` method returns a boolean indicating whether or not a class is an interface. #### The toString() Method `String toString()` Finally, the `toString()` method returns the name of a class or interface. `toString()` automatically prepends the string `"class"` or `"interface"` to the name based on whether the `Class` object represents a class or an interface. ### The ClassLoader Class The `ClassLoader` class provides the framework that enables you to dynamically load classes into the runtime environment. Following are the methods implemented by `ClassLoader`: `abstract Class loadClass(String` name`, boolean` resolve`)` `final Class defineClass(byte` data`[], int` offset`, int` length`)` `final void resolveClass(Class` c`)` `final Class findSystemClass(String` name`)` #### The loadClass() and defineClass() Methods
    abstract Class loadClass(String name, boolean resolve)
    final Class defineClass(byte data[], int offset, int length)
The `loadClass()` method is an `abstract` method that must be defined in a subclass of `ClassLoader`. `loadClass()` resolves a class name passed in the `String` parameter name into a `Class` runtime object. `loadClass()` returns the resulting `Class` on success or `null` if not successful. The `defineClass()` method converts an array of `byte` data into a `Class` object. The class is defined by the data parameter beginning at offset and continuing for length bytes. #### The resolveClass() Method `final void resolveClass(Class` c) A class defined with `defineClass()` must be resolved before it can be used. You can resolve a class by using the `resolveClass()` method, which takes a `Class` object as its only parameter. #### The findSystemClass() Method `final Class findSystemClass(String` name) Finally, the `findSystemClass()` method is used to find and load a system class. A system class is a class that uses the built-in (primordial) class loader, defined as `null`. ## Summary In this chapter, you learned a great deal about the classes and interfaces that make up the Java language package. The language package lays out the core classes, interfaces, and errors of the Java class libraries. Although some of the classes implemented in the language package are fairly low level, a solid understanding of these classes is necessary to move on to other areas of the Java class libraries. This chapter explained how fundamental data types can become objects using the data type wrappers. You then learned about the many mathematical functions contained in the `Math` class. And don't forget about the string classes, which provide a powerful set of routines for working with strings of text. You finished up with a tour of how to access the system and runtime resources of Java, along with the lower-level runtime and dynamic class support. The following chapter provides the next stop on this guided tour of the Java class libraries: the Java utilities package.
| ©Copyright, Macmillan Computer Publishing. All rights reserved.