The java.lang Package


The java.lang Package

The core Java classes fall into three broad categories. There are classes that support specific tasks, such as database access or graphical user interface (GUI) creation. These classes are organized into packages. For example, database support is in the java.sql package, while GUI infrastructure is in the java.awt package and its many subpackages. Another category is classes that are generally useful, no matter what kind of program you are writing. Most of these appear in the java.util package. The third category is classes that are essential to the operation of any program. These are to be found in the java.lang package. Let's begin with a look at a few of them.

The classes and interfaces in java.lang are so important that they are imported in all source code automatically. It is as if the compiler inserted the following line into any source:

import java.lang.*;

We will not be looking at all the classes in java.lang. Again, the purpose of this book is not to tell you everything there is to know about every class in the package. Instead, we will just look at a few of the most important classes. Since you know how to read API pages, you know how to find out about the others.

The java.lang.String Class

We will start with String. You have been aware of this class ever since Chapter 2, when you first looked at applications and saw the following:

public static void main(String[] args) { . . . }

Now you know that this is a method declaration, and no doubt you've guessed that the method takes a single argument whose type is an array of something called String.

The String class contains an ordered sequence of characters, representing a piece of text. The text that an instance contains is specified as a constructor argument. The class is immutable. This means that after an instance is constructed, its contents cannot be changed. So if an instance of String initially contains the text "Click here to select a color", it will contain that text throughout its lifetime.

This class is unique, in that there are two ways to create an instance. One way, of course, is to call a constructor. The second way, which is unique to the String class, is to use a literal string. A literal string is text enclosed in double-quotes, like this:

"I am a literal string."

When the compiler encounters a literal string, it generates code that creates an instance of String to represent the text in quotes. (Actually, the situation is a bit more complicated than that, but we don't need to go into detail here.) We have often used code with the following format:

System.out.println("value is " + x);

Now you know that the text between the quotes is a literal string. Later in this chapter, you will see what is really going on when the literal string is added to x. For now, you know that whatever else might be happening in the line of code, execution involves the creation of an instance of String that represents the text in quotes.

The shortest literal string is

""

This string has zero characters, but it is still an object that exists, and you can call any methods of the String class on it. It is called the empty string.

The easiest way to create a String instance that contains a particular run of text is like this:

String s; s = "To be, or not to be";

Or simply:

String s = "To be, or not to be"; 

There are 11 different versions of the String constructor. Here we will only look at one of them. (Later in this chapter you will learn how to look for information about the rest, so you will be able to choose the best one for any situation.) The simplest constructor is

public String(String s)

This constructor takes a single argument, which is a reference to another string. The new object is an exact replica of the argument. Even though this is the simplest form of the String constructor, it isn't often used because you have the option of using a literal string instead. For example, the following two lines are (almost) equivalent:

String s = new String("abcde"); String s = "abcde";

The second version is obviously easier to type.

The String class has a large number of methods. Here we will present a few of the more interesting ones. We start with toUpperCase() and toLowerCase(). The toUpperCase() method converts all lowercase characters in a string to uppercase. The toLowerCase () method converts all uppercase characters in a string to lowercase. Here is an example:

String s = "Mm"; String upper = s.toUpperCase(); String lower = s.toLowerCase(); System.out.println(upper); System.out.println(lower);

The output of this code is

MM Mm

These methods, and indeed all String methods that seem to modify a string, do not change the original string. That would be impossible, because strings are immutable. After they are constructed, they cannot be changed. Instead, toUpperCase() and toLowerCase() create and return a new string object. To prove this, you can modify the code example:

String s = "Mm"; String upper = s.toUpperCase(); String lower = s.toLowerCase(); System.out.println(upper); System.out.println(lower); System.out.println(s);

The output of this code is

MM mm Mm

Notice the last line, which prints out the unscathed original string.

The situation can get confusing when a single reference is reassigned, as in the following example:

String s = new String("UPPER : lower"); System.out.println("BEFORE: " + s); s = s.toUpperCase(); System.out.println("AFTER: " + s);

Here the single reference s refers first to the original string, and a little later to the new uppercase string. It looks like there is only a single string object involved, especially when you look at the output:

BEFORE: UPPER : lower AFTER: UPPER : LOWER

But there are actually two objects, although there is only one reference. When the reference is reassigned ( s = s.toUpperCase() ), the original string object might get garbage- collected. This would happen if there were no other references to the original object.

This might seem overly complicated when all you wanted to do was convert a string to upper- or lowercase, but it is always important to bear in mind the difference between references and objects, and to know exactly what references are pointing to what objects at every point in your code.

The StringLab animated illustration demonstrates strings in moving pictures. To run the animation, type java strings.StringLab. You see a window with two code statements, as shown in Figure 12.5.

click to expand
Figure 12.5: StringLab

The first statement creates a new instance of String. You can type anything you like to provide the text. The second statement calls a method, toUpperCase() or toLowerCase(),on the string. Use the controls at the top of the window to choose the method that will be called. You can also use the controls to choose between using two references or reassigning a single reference. (Notice how the code in the main window changes when you change this option.) As usual, click Run to see the animation, or click Run Lightspeed to skip the animation and see the final result. Be sure to watch the full animation with Reassign Old Reference selected so you can see the original string being garbage-collected.

Figure 12.6 shows the result of converting to uppercase and using two references. Figure 12.7 shows the result of converting to lowercase and reassigning the reference.

click to expand
Figure 12.6: StringLab: uppercase, 2 references

click to expand
Figure 12.7: StringLab: lowercase, 1 reference

Now that you understand strings and methods, we can move quickly through a list of other String methods:

trim() Removes blank spaces from the start and end (but not the middle) of the executing string object.

substring(int n) Returns a portion of the executing string object. The substring consists of the run of characters beginning at position n (where 0 is the first character) and ending at the end of the executing string object.

concat(String s) Appends s to the executing string object.

The return types are all String. These descriptions are deliberately brief. Detailed explanations are available to you in the API pages.

Here are some String methods that return information about the executing string object. The return types vary, so they are included in the list:

boolean equals(String s) Returns true if s and the executing string object contain identical text.

boolean equalsIgnoreCase(String s) Returns true if s and the executing string object contain identical text, ignoring uppercase and lowercase distinctions.

char charAt(int n) Returns the nth character in the executing string object.

int length() Returns the length of the executing string object.

boolean startsWith(String s) Returns true if the executing string object begins with string s.

Here is a method whose argument is a string. The method prints out every character of the argument on its own line:

    void printChars(String s)     {         int length = s.length();         for (int i=0; i<length; i++)         {             char c = s.charAt(i);             System.out.println("Char #" + i + " is " + c);         }     }

Note the use of the length() and charAt() methods. Here is the output when the method is called with argument Alligator:

Char #0 is A Char #1 is l Char #2 is l Char #3 is i Char #4 is g Char #5 is a Char #6 is t Char #7 is o Char #8 is r

The only tricky method presented here is equals(). It is easy to understand what it does, provided you don't get misled by the name. The equals()method does not check if the argument and the executing string object are the same object. Instead, it checks whether the two objects both represent identical sequences of characters. To check if the argument and the executing string are the same object, use the == operator, as demonstrated in the following example:

String s1 = new String("aa"); String s2 = new String("aa"); String s3 = s2; if (s1.equals(s2))   System.out.println("s1.equals(s2): YES"); if (s1 == s2)   System.out.println("s1 == s2: YES"); if (s2 == s3)   System.out.println("s2 == s3: YES");

The output is

s1.equals(s2): YES s2 == s3: YES

Figure 12.8 shows the references and objects of this example.


Figure 12.8: String references and objects

We say that the == operator checks for reference equality, which means it checks if two references point to the same object. The equals() method checks for object equality, which means it checks if two objects contain equal data. This distinction is very important in object-oriented programming.

Command-Line Arguments

Every Java application has a main method that begins like this:

public static void main(String[] args) . . .

Of course, you can call the method argument anything you like, but args is the conventional name. The array contains the application's command-line arguments. These are everything the user has typed into the command line that invoked the application, except for the following:

  • java

  • The application class name

  • Any arguments for the JVM

So if you have an application class called database.Backup, and you run it by typing java database.Backup network local greebo 1234, the args array will look like Figure 12.9.


Figure 12.9: Command-line arguments

Note that the last component in the array is a string. It is not a number, even though it looks like one because it consists entirely of digit characters. Later you will learn how to convert an all-digit string into an int.

One job of the main() method is to check the command-line arguments and take appropriate action. For example, a main() method might have the following code:

public static void main(String[] args) {   for (int i=0; i< args.length; i++)   {     if (args [i].equals("help"))     {       printHelpMessage();       break;     }   } }

We assume the existence of a printHelpMessage() method that prints out an explanatory message on how to use the program. The code scans the args array. If the array contains any occurrence of "help" (that is, if someone typed "help" anywhere on the command line), the explanatory message is printed.

Some command-line arguments are intended for the JVM and do not get passed into the application. To see a list of JVM arguments, type java -help. One such argument is -verbose. When you run a program with this argument, you get output from the JVM about such activities as class loading. If you invoke an application by typing java -verbose database .Backup network local greebo 1234, the -verbose argument will be consumed by the JVM and won't be passed on to the application. So the application's args array will still be as shown in Figure 12.9, but the output will include the verbose messages from the JVM.

The java.lang.Object Class

The Object class is the ultimate superclass of all other Java classes. It has about a dozen methods, many of which support advanced functionality that is beyond the scope of this book. But it does have two methods that everyone should know about: equals() and toString(). Since every other class extends Object (directly or indirectly), every other class inherits these methods. You are not likely to create instances of Object, but you are very likely to use the equals() and toString() methods that other classes inherit or override.

The first method we will look at is equals(). You already know about the implementation provided by the String class, and that it checks for object equality and not reference equality. This distinction is maintained throughout the core Java classes: Any implementation of equals() in any core class checks for object equality rather than reference equality. So thisRef.equals(thatRef) will return true if the two references point to objects that contain equal variables. (Of course, if the two references point to the same object, the call will also return true.)

For example, the java.awt.Point class represents a point in two-dimensional space. It has variables called x and y, which hold the horizontal and vertical location of the point. If p1 and p2 are both references to instances of this class, you can check for object equality by calling either

if (p1.equals(p2)) …

or

if (p2.equals(p1)) …

The equals() method of class Point returns true if p1.x equals p2.x and p1.y equals p2.y.

Not all core classes provide their own implementations of equals(). If you want to know if a class you are interested in provides an implementation, you should look at the class's API page. Beware of classes whose API pages do not document an equals() method. The class might inherit the method from Object, and that version is not very useful.

Now we will turn to the extremely useful toString() method. It is public, it returns a String, and it has no arguments, so its declaration looks like this:

public String toString() 

This method is intended to print out a useful message that includes information about the values of the executing object's variables. The version provided by the Object class isn't very informative. In fact, it's downright cryptic. But every one of the core Java classes overrides toString() with a version that provides useful information.

For example, there is a class called java.awt.Color that represents a color. The class has int variables called red, green, and blue, which contain the amounts of red, green, and blue light that make up the represented color. Their values can range from 0 through 255, and they are specified in the class's constructor.

Suppose you have a long intricate program with an instance of Color, referenced by variable foreground, that doesn't look right. (Colors are used extensively in visual programming, which we will look at in the last 3 chapters of this book.) It would be helpful if you knew exactly what the red, green, and blue components of the problematic color are. That information might lead you to the source of the trouble. Thanks to toString(), you can easily create a line of debug code that tells you what is going on inside your program. Always delete debug code after it has served your purpose. Otherwise it will accumulate, and your program will emit lots of information that is no longer helpful.

Here is a debug line that prints out the puzzling color: System.out.println("Weird color is " +                     foreground.toString());

The output looks something like this:

Weird color is java.awt.Color[r=100,g=255,b=0]

The output uses abbreviations instead of red, green, and blue, but it's clear what their values are. Now you can determine which of them are wrong and look at the code that calculates the corresponding value that is passed into the Color constructor.

There is an easier way to print the toString value of the color, or of any other object. This brings us to the topic of string concatenation. "Concatenation" is another of those five-syllable words. It just means joining strings consecutively, one after another (after another, after another...). You have already used concatenation extensively, whenever you did something like

System.out.println("size is " + size +                    "and weight is " + weight);

Now it's time to see what's really going on between those parentheses. Look at those plus signs. Obviously they mean something other than addition. In Java, plus signs have a double meaning:

  • When both items next to a plus sign are numeric, the plus sign means addition.

  • When one or both items next to a plus sign are references to strings, the plus sign means string concatenation.

In the second context, if one of the items next to the plus sign is a string, the other item can be anything! It can be a primitive, another string reference, or a reference to an object of any other class. The other item is converted to a string according to the rules shown in Table 12.1.

Table 12.1: String Concatenation Conversion Rules

Type

Conversion Rule

boolean

"true" or "false"

Primitive other than boolean

A reasonable string representation

String

The string

Object reference other than String

Call toString() on the reference

The last entry in the table means that the line

System.out.println("Weird color is " +                     foreground.toString());

is equivalent to

System.out.println("Weird color is " +                     foreground);

In other words, when you're doing concatenation, you never need to type .toString().

The ConcatLab animated illustration shows concatenation in action. Run the program by typing java concat.ConcatLab. You will see a window with three lines of code, as shown in Figure 12.10.

click to expand
Figure 12.10: ConcatLab

The first statement creates an instance of java.awt.Color. The constructor's arguments are the three primary color values (red/green/blue) that constitute the color. They must be in the range 0-255. You can type in any valid values. Later on, you will see the color they represent.

The second statement creates an instance of a class called Point3D, which is not part of the core Java classes. To see the (very simple) source for Point3D, click on the Edit Point3D button. You will see the display shown in Figure 12.11.

click to expand
Figure 12.11: ConcatLab's Point3D class

The class represents a point in 3-D space, with x, y, and z coordinates. You will see a version of toString() that returns a reasonable string representation. You can edit this code. Type any text you want into the text fields. When you're finished, click on OK.

The third statement on the main window says

String s = "c is " + c + " and p is " + p;   

Click on the Run button to run the animation, which shows how the four parts of the concatenated string are made. Figure 12.12 shows the result of running the animation, after some custom configuration.

click to expand
Figure 12.12: ConcatLab's Point3D class

The java.lang.Integer Class, and other Wrappers

The java.lang package has eight very simple classes called wrappers. A wrapper is a class whose data is a single primitive value. In other words, the primitive is "wrapped up" inside an object. The wrapper classes have names that are very similar to the corresponding primitive names. In some cases, the names are identical except for the first letter, which is always uppercase for class names and lowercase for primitive names. Table 12.2 shows the wrapper class names.

Table 12.2: Wrapper Class Names

Primitive

Wrapper

boolean

Boolean

char

Character

byte

Byte

short

Short

int

Integer

long

Long

float

Float

double

Double

The wrapper classes are immutable. This means that, just as with strings, the data contained in an instance doesn't change after the instance is created. The contained data is passed into the constructor, as shown below:

Boolean boo = new Boolean(true); Character cha = new Character('L'); byte b = 5; Byte bye = new Byte(b); short s = 10; Short sho = new Short(s); int i = 9999; Integer inty = new Integer(i); long n = 2222222; Long lonny = new Long(n); float f = 3.14159f; Float flo = new Float(f); double d = 1.2e200; Double dubby = new Double(d); 

It might not be clear why these classes would ever be useful. You'll find out why when you learn about the java.util class a little later on. But for now, be aware that the wrapper classes all have static methods that are useful for translating strings into primitives. For example, class Integer has a parseInt(String s) method that translates a string to an int. If the string does not represent a number, the method throws NumberFormatException.

The following code is an application that translates its first classes to an int, multiplies that value by 39, and then prints out the result:

public class X39 {   public static void main(String[] args)   {     if (args.length == 0)     {       System.out.println("Please supply a number.");     }     else     {                   try       {         int n = Integer.parseInt(args[0]);         int times39 = n * 39;         System.out.println(args[0] + " * 39 = " +                            times39);       }       catch (NumberFormatException x)       {         System.out.println("That's not a number!");       }     }   } }

Note that this code doesn't create an instance of Integer. Instead, it calls a static method of Integer (in the first line of the try block) to convert the string in args[0] to an int. Code like this is frequently seen near the beginning of main() methods. Generally, an application that has numeric command-line arguments can't get very far until it converts the argument strings to numeric primitives.

The java.lang.System Class

The java.lang.System class contains a hodgepodge of methods, most of which involve advanced functionality related to the JVM. This brief section will only cover one of the class's methods. First, let's take a moment to look at two of its static variables: out and in.

You have already used System.out extensively. Whenever you used

System.out.println(…);

You were making a call to the println() method of the System.out object.

The println() method is heavily overloaded. All of the versions of the method take a single argument. One version, which you have been using throughout this book, takes a string argument. The string is printed out, followed by a newline character. The newline character is not displayed. Instead, it moves the cursor position to the beginning of the next line.

Other versions of println() take args that are bytes, shorts, booleans, and so on. These versions convert their arguments to strings and then print them out, followed by a newline character.

Perhaps the most commonly used method of java.lang.System is exit(). This method causes the JVM to terminate, thus ending the current application immediately. The method takes an int argument called the exit code. Typically, 0 is used to indicate a normal termination, while a non-zero value indicates that termination was caused by an error condition.

Some operating systems are able to run sequences of programs, where the exit code of one program is used to control the operation of the next program. This is highly system-dependent and not relevant to an introductory Java book, but you need to know what exit status codes are because you need to pass an argument into every System.exit() call. You won't go wrong if you use 0 to mean normal termination and a small non-zero value to mean abnormal termination.

The following code is a rewrite of the previous example, using System.exit() to terminate execution.

public class X39RevB {   public static void main(String[] args)   {     if (args.length == 0)     {       System.out.println("Please supply a number.");       System.exit(1); // Non-zero exit code     }     else     {       try       {         int n = Integer.parseInt(args[0]);         int times39 = n * 39;         System.out.println(args[0] + " * 39 = " +                            times39);         System.exit(0);       }       catch (NumberFormatException x)       {         System.out.println("That's not a number!");         System.exit(2);       }     }   } }

The System.exit(0) call at the end of the try block isn't actually necessary. When main() finishes, the JVM shuts down anyway, with an exit code of 0.

The java.lang.Math Class

The java.lang.Math class is the least object-oriented of all the core Java classes. All of its methods are static, so you never need to create an instance. In fact, you aren't allowed to create an instance (see Exercise 3 for details).

The class has dozens of methods. Instead of listing them all, here's a short sampler. Consult the API page for the complete list.

int min(int a, int b) Returns the lesser of a and b

int max(int a, int b) Returns the greater of a and b

double sin(double angle) Computes the sine of an angle

double cos(double angle) Computes the cosine of an angle

double tan(double angle) Computes the tangent of an angle

double pow(double a, double b) Returns a raised to the power of b

double random() Returns a random number that is >=0 and <1

And so on. All trigonometry methods use radians, not degrees, for expressing angles. All methods that do intense calculation have return types of double.

The random() method can be used to generate a random double in any range. For example, to generate a random double that is >=0 and <30, just use 30 * Math.random(). To generate a random double that is >=10 and <40, just use 10 + (30*Math.random()).

The following code generates 100 random numbers that are >=0 and <50. Then it computes the area of a circle whose radius is the random number. The code keeps track of, and prints out, the largest area:

public class RandomAreas {   public static void main(String[] args)   {     double maxArea = 0;     for (int i=0; i<100; i++)     {       double radius = 50 * Math.random();       double area = 3.24159 * radius * radius;         if (area > maxArea)           maxArea = area;     }     System.out.println("Biggest area = " + maxArea);   } }

The lang class defines two public final static double variables, PI and E. They contain very precise values for these mathematical constants, accurate to 20 digits to the right of the decimal point. So you never need to memorize, look up, or type in either of these values. That's a good thing, because you might accidentally type in a wrong value that could throw off all your subsequent calculations. In fact, that's what happened in this example. In the line that begins double area =, the 2 should be a 1. A better line would be

double area = Math.PI * radius * radius;

You can make the code a little shorter by replacing these lines:

if (area > maxArea)   maxArea = area;

With this single line:

maxArea = Math.max(area, maxArea);




Ground-Up Java
Ground-Up Java
ISBN: 0782141900
EAN: 2147483647
Year: 2005
Pages: 157
Authors: Philip Heller

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net