CHAPTER
 
17
Exploring java.lang
This chapter discusses those classes and interfaces defined by java.lang. As you know, java.lang is automatically imported into all programs. It contains classes and interfaces that are fundamental to virtually all of Java programming. It is Java’s most widely used package.
java.lang includes the following classes:
image
java.lang defines the following interfaces:
image
Several of the classes contained in java.lang contain deprecated methods, most dating back to Java 1.0. These deprecated methods are still provided by Java to support an ever-shrinking pool of legacy code and are not recommended for new code. Because of this, the deprecated methods are not discussed here.
Primitive Type Wrappers
As mentioned in Part I of this book, Java uses primitive types, such as int and char, for performance reasons. These data types are not part of the object hierarchy. They are passed by value to methods and cannot be directly passed by reference. Also, there is no way for two methods to refer to the same instance of an int. At times, you will need to create an object representation for one of these primitive types. For example, there are collection classes discussed in Chapter 18 that deal only with objects; to store a primitive type in one of these classes, you need to wrap the primitive type in a class. To address this need, Java provides classes that correspond to each of the primitive types. In essence, these classes encapsulate, or wrap, the primitive types within a class. Thus, they are commonly referred to as type wrappers. The type wrappers were introduced in Chapter 12. They are examined in detail here.
Number
The abstract class Number defines a superclass that is implemented by the classes that wrap the numeric types byte, short, int, long, float, and double. Number has abstract methods that return the value of the object in each of the different number formats. For example, doubleValue( ) returns the value as a double, floatValue( ) returns the value as a float, and so on. These methods are shown here:
byte byteValue( )
double doubleValue( )
float floatValue( )
int intValue( )
long longValue( )
short shortValue( )
The values returned by these methods might be rounded, truncated, or result in a “garbage” value due to the effects of a narrowing conversion.
Number has concrete subclasses that hold explicit values of each primitive numeric type: Double, Float, Byte, Short, Integer, and Long.
Double and Float
Double and Float are wrappers for floating-point values of type double and float, respectively. The constructors for Float are shown here:
Float(double num)
Float(float num)
Float(String str) throws NumberFormatException
As you can see, Float objects can be constructed with values of type float or double. They can also be constructed from the string representation of a floating-point number.
The constructors for Double are shown here:
Double(double num)
Double(String str) throws NumberFormatException
Double objects can be constructed with a double value or a string containing a floatingpoint value.
The methods defined by Float include those shown in Table 17-1. The methods defined by Double include those shown in Table 17-2. Both Float and Double define the following constants:
BYTES
The width of a float or double in bytes (Added by JDK 8.)
MAX_EXPONENT
Maximum exponent
MAX_VALUE
Maximum positive value
MIN_EXPONENT
Minimum exponent
MIN_NORMAL
Minimum positive normal value
MIN_VALUE
Minimum positive value
NaN
Not a number
POSITIVE_INFINITY
Positive infinity
NEGATIVE_INFINITY
Negative infinity
SIZE
The bit width of the wrapped value
TYPE
The Class object for float or double
image
image
Table 17-1   The Methods Defined by Float
image
image
image
Table 17-2   The Methods Defined by Double
The following example creates two Double objects—one by using a double value and the other by passing a string that can be parsed as a double:
image
As you can see from the following output, both constructors created identical Double instances, as shown by the equals( ) method returning true:
image
Understanding isInfinite( ) and isNaN( )
Float and Double provide the methods isInfinite( ) and isNaN( ), which help when manipulating two special double and float values. These methods test for two unique values defined by the IEEE floating-point specification: infinity and NaN (not a number). isInfinite( ) returns true if the value being tested is infinitely large or small in magnitude. isNaN( ) returns true if the value being tested is not a number.
The following example creates two Double objects; one is infinite, and the other is not a number:
image
This program generates the following output:
image
Byte, Short, Integer, and Long
The Byte, Short, Integer, and Long classes are wrappers for byte, short, int, and long integer types, respectively. Their constructors are shown here:
Byte(byte num)
Byte(String str) throws NumberFormatException
Short(short num)
Short(String str) throws NumberFormatException
Integer(int num)
Integer(String str) throws NumberFormatException
Long(long num)
Long(String str) throws NumberFormatException
As you can see, these objects can be constructed from numeric values or from strings that contain valid whole number values.
The methods defined by these classes are shown in Tables 17-3 through 17-6. As you can see, they define methods for parsing integers from strings and converting strings back into integers. Variants of these methods allow you to specify the radix, or numeric base, for conversion. Common radixes are 2 for binary, 8 for octal, 10 for decimal, and 16 for hexadecimal.
The following constants are defined:
BYTES
The width of the integer type in bytes (Added by JDK 8.)
MIN_VALUE
Minimum value
MAX_VALUE
Maximum value
SIZE
The bit width of the wrapped value
TYPE
The Class object for byte, short, int, or long
image
Table 17-3   The Methods Defined by Byte
image
Table 17-4   The Methods Defined by Short
image
image
Table 17-5   The Methods Defined by Integer
image
image
Table 17-6   The Methods Defined by Long
Converting Numbers to and from Strings
One of the most common programming chores is converting the string representation of a number into its internal, binary format. Fortunately, Java provides an easy way to accomplish this. The Byte, Short, Integer, and Long classes provide the parseByte( ), parseShort( ), parseInt( ), and parseLong( ) methods, respectively. These methods return the byte, short, int, or long equivalent of the numeric string with which they are called. (Similar methods also exist for the Float and Double classes.)
The following program demonstrates parseInt( ). It sums a list of integers entered by the user. It reads the integers using readLine( ) and uses parseInt( ) to convert these strings into their int equivalents.
image
To convert a whole number into a decimal string, use the versions of toString( ) defined in the Byte, Short, Integer, or Long classes. The Integer and Long classes also provide the methods toBinaryString( ), toHexString( ), and toOctalString( ), which convert a value into a binary, hexadecimal, or octal string, respectively.
The following program demonstrates binary, hexadecimal, and octal conversion:
image
The output of this program is shown here:
image
Character
Character is a simple wrapper around a char. The constructor for Character is
Character(char ch)
Here, ch specifies the character that will be wrapped by the Character object being created.
To obtain the char value contained in a Character object, call charValue( ), shown here:
char charValue( )
It returns the character.
The Character class defines several constants, including the following:
BYTES
The width of a char in bytes (Added by JDK 8.)
MAX_RADIX
The largest radix
MIN_RADIX
The smallest radix
MAX_VALUE
The largest character value
MIN_VALUE
The smallest character value
TYPE
The Class object for char
Character includes several static methods that categorize characters and alter their case. A sampling is shown in Table 17-7. The following example demonstrates several of these methods:
image
The output from this program is shown here:
image
Character defines two methods, forDigit( ) and digit( ), that enable you to convert between integer values and the digits they represent. They are shown here:
static char forDigit(int num, int radix)
static int digit(char digit, int radix)
forDigit( ) returns the digit character associated with the value of num. The radix of the conversion is specified by radix. digit( ) returns the integer value associated with the specified character (which is presumably a digit) according to the specified radix. (There is a second form of digit( ) that takes a code point. See the following section for a discussion of code points.)
Another method defined by Character is compareTo( ), which has the following form:
int compareTo(Character c)
It returns zero if the invoking object and c have the same value. It returns a negative value if the invoking object has a lower value. Otherwise, it returns a positive value.
image
Table 17-7   Various Character Methods
Character includes a method called getDirectionality( ) which can be used to determine the direction of a character. Several constants are defined that describe directionality. Most programs will not need to use character directionality.
Character also overrides the equals( ) and hashCode( ) methods.
Two other character-related classes are Character.Subset, used to describe a subset of Unicode, and Character.UnicodeBlock, which contains Unicode character blocks.
Additions to Character for Unicode Code Point Support
Relatively recently, major additions were made to Character. Beginning with JDK 5, the Character class has included support for 32-bit Unicode characters. In the past, all Unicode characters could be held by 16 bits, which is the size of a char (and the size of the value encapsulated within a Character), because those values ranged from 0 to FFFF. However, the Unicode character set has been expanded, and more than 16 bits are required. Characters can now range from 0 to 10FFFF.
Here are three important terms. A code point is a character in the range 0 to 10FFFF. Characters that have values greater than FFFF are called supplemental characters. The basic multilingual plane (BMP) are those characters between 0 and FFFF.
The expansion of the Unicode character set caused a fundamental problem for Java. Because a supplemental character has a value greater than a char can hold, some means of handling the supplemental characters was needed. Java addressed this problem in two ways. First, Java uses two chars to represent a supplemental character. The first char is called the high surrogate, and the second is called the low surrogate. New methods, such as codePointAt( ), were provided to translate between code points and supplemental characters.
Secondly, Java overloaded several preexisting methods in the Character class. The overloaded forms use int rather than char data. Because an int is large enough to hold any character as a single value, it can be used to store any character. For example, all of the methods in Table 17-7 have overloaded forms that operate on int. Here is a sampling:
static boolean isDigit(int cp)
static boolean isLetter(int cp)
static int toLowerCase(int cp)
In addition to the methods overloaded to accept code points, Character adds methods that provide additional support for code points. A sampling is shown in Table 17-8.
Boolean
Boolean is a very thin wrapper around boolean values, which is useful mostly when you want to pass a boolean variable by reference. It contains the constants TRUE and FALSE, which define true and false Boolean objects. Boolean also defines the TYPE field, which is the Class object for boolean. Boolean defines these constructors:
Boolean(boolean boolValue)
Boolean(String boolString)
image
Table 17-8   A Sampling of Methods That Provide Support for 32-Bit Unicode Code Points
In the first version, boolValue must be either true or false. In the second version, if boolString contains the string "true" (in uppercase or lowercase), then the new Boolean object will be true. Otherwise, it will be false.
Boolean defines the methods shown in Table 17-9.
image
Table 17-9   The Methods Defined by Boolean
Void
The Void class has one field, TYPE, which holds a reference to the Class object for type void. You do not create instances of this class.
Process
The abstract Process class encapsulates a process—that is, an executing program. It is used primarily as a superclass for the type of objects created by exec( ) in the Runtime class, or by start( ) in the ProcessBuilder class. Process contains the methods shown in Table 17-10.
image
Table 17-10   The Methods Defined by Process
Runtime
The Runtime class encapsulates the run-time environment. You cannot instantiate a Runtime object. However, you can get a reference to the current Runtime object by calling the static method Runtime.getRuntime( ). Once you obtain a reference to the current Runtime object, you can call several methods that control the state and behavior of the Java Virtual Machine. Applets and other untrusted code typically cannot call any of the Runtime methods without raising a SecurityException. Several commonly used methods defined by Runtime are shown in Table 17-11.
image
image
Table 17-11   A Sampling of Methods Defined by Runtime
Let’s look at two of the most common uses of the Runtime class: memory management and executing additional processes.
Memory Management
Although Java provides automatic garbage collection, sometimes you will want to know how large the object heap is and how much of it is left. You can use this information, for example, to check your code for efficiency or to approximate how many more objects of a certain type can be instantiated. To obtain these values, use the totalMemory( ) and freeMemory( ) methods.
As mentioned in Part I, Java’s garbage collector runs periodically to recycle unused objects. However, sometimes you will want to collect discarded objects prior to the collector’s next appointed rounds. You can run the garbage collector on demand by calling the gc( ) method. A good thing to try is to call gc( ) and then call freeMemory( ) to get a baseline memory usage. Next, execute your code and call freeMemory( ) again to see how much memory it is allocating. The following program illustrates this idea:
image
Sample output from this program is shown here (of course, your actual results may vary):
image
Executing Other Programs
In safe environments, you can use Java to execute other heavyweight processes (that is, programs) on your multitasking operating system. Several forms of the exec( ) method allow you to name the program you want to run as well as its input parameters. The exec( ) method returns a Process object, which can then be used to control how your Java program interacts with this new running process. Because Java can run on a variety of platforms and under a variety of operating systems, exec( ) is inherently environment-dependent.
The following example uses exec( ) to launch notepad, Windows’ simple text editor. Obviously, this example must be run under the Windows operating system.
image
There are several alternative forms of exec( ), but the one shown in the example is the most common. The Process object returned by exec( ) can be manipulated by Process’ methods after the new program starts running. You can kill the subprocess with the destroy( ) method. The waitFor( ) method causes your program to wait until the subprocess finishes. The exitValue( ) method returns the value returned by the subprocess when it is finished. This is typically 0 if no problems occur. Here is the preceding exec( ) example modified to wait for the running process to exit:
image
While a subprocess is running, you can write to and read from its standard input and output. The getOutputStream( ) and getInputStream( ) methods return the handles to standard in and out of the subprocess. (I/O is examined in detail in Chapter 20.)
ProcessBuilder
ProcessBuilder provides another way to start and manage processes (that is, programs). As explained earlier, all processes are represented by the Process class, and a process can be started by Runtime.exec( ). ProcessBuilder offers more control over the processes. For example, you can set the current working directory.
ProcessBuilder defines these constructors:
ProcessBuilder(List<String> args)
ProccessBuilder(String … args)
Here, args is a list of arguments that specify the name of the program to be executed along with any required command-line arguments. In the first constructor, the arguments are passed in a List. In the second, they are specified through a varargs parameter. Table 17-12 describes the methods defined by ProcessBuilder.
In Table 17-12, notice the methods that use the ProcessBuilder.Redirect class. This abstract class encapsulates an I/O source or target linked to a subprocess. Among other things, these methods enable you to redirect the source or target of I/O operations. For example, you can redirect to a file by calling to( ), redirect from a file by calling from( ), and append to a file by calling appendTo( ). A File object linked to the file can be obtained by calling file( ). These methods are shown here:
static ProcessBuilder.Redirect to(File f)
static ProcessBuilder.Redirect from(File f)
static ProcessBuilder.Redirect appendTo(File f)
File file( )
Another method supported by ProcessBuilder.Redirect is type( ), which returns a value of the enumeration type ProcessBuilder.Redirect.Type. This enumeration describes the type of the redirection. It defines these values: APPEND, INHERIT, PIPE, READ, or WRITE. ProcessBuilder.Redirect also defines the constants INHERIT and PIPE.
image
image
Table 17-12   The Methods Defined by ProcessBuilder
To create a process using ProcessBuilder, simply create an instance of ProcessBuilder, specifying the name of the program and any needed arguments. To begin execution of the program, call start( ) on that instance. Here is an example that executes the Windows text editor notepad. Notice that it specifies the name of the file to edit as an argument.
image
System
The System class holds a collection of static methods and variables. The standard input, output, and error output of the Java run time are stored in the in, out, and err variables. The methods defined by System are shown in Table 17-13. Many of the methods throw a SecurityException if the operation is not permitted by the security manager.
Let’s look at some common uses of System.
image
image
Table 17-13   The Methods Defined by System
Using currentTimeMillis( ) to Time Program Execution
One use of the System class that you might find particularly interesting is to use the currentTimeMillis( ) method to time how long various parts of your program take to execute. The currentTimeMillis( ) method returns the current time in terms of milliseconds since midnight, January 1, 1970. To time a section of your program, store this value just before beginning the section in question. Immediately upon completion, call currentTimeMillis( ) again. The elapsed time will be the ending time minus the starting time. The following program demonstrates this:
image
Here is a sample run (remember that your results probably will differ):
image
If your system has a timer that offers nanosecond precision, then you could rewrite the preceding program to use nanoTime( ) rather than currentTimeMillis( ). For example, here is the key portion of the program rewritten to use nanoTime( ):
image
Using arraycopy( )
The arraycopy( ) method can be used to copy quickly an array of any type from one place to another. This is much faster than the equivalent loop written out longhand in Java. Here is an example of two arrays being copied by the arraycopy( ) method. First, a is copied to b. Next, all of a’s elements are shifted down by one. Then, b is shifted up by one.
image
As you can see from the following output, you can copy using the same source and destination in either direction:
image
Environment Properties
The following properties are available in all cases:
image
You can obtain the values of various environment variables by calling the System.getProperty( ) method. For example, the following program displays the path to the current user directory:
image
Object
As mentioned in Part I, Object is a superclass of all other classes. Object defines the methods shown in Table 17-14, which are available to every object.
Using clone( ) and the Cloneable Interface
Most of the methods defined by Object are discussed elsewhere in this book. However, one deserves special attention: clone( ). The clone( ) method generates a duplicate copy of the object on which it is called. Only classes that implement the Cloneable interface can be cloned.
The Cloneable interface defines no members. It is used to indicate that a class allows a bitwise copy of an object (that is, a clone) to be made. If you try to call clone( ) on a class that does not implement Cloneable, a CloneNotSupportedException is thrown. When a clone is made, the constructor for the object being cloned is not called. As implemented by Object, a clone is simply an exact copy of the original.
Cloning is a potentially dangerous action, because it can cause unintended side effects. For example, if the object being cloned contains a reference variable called obRef, then when the clone is made, obRef in the clone will refer to the same object as does obRef in the original. If the clone makes a change to the contents of the object referred to by obRef, then it will be changed for the original object, too. Here is another example: If an object opens an I/O stream and is then cloned, two objects will be capable of operating on the same stream. Further, if one of these objects closes the stream, the other object might still attempt to write to it, causing an error. In some cases, you will need to override the clone( ) method defined by Object to handle these types of problems.
image
Table 17-14   The Methods Defined by Object
Because cloning can cause problems, clone( ) is declared as protected inside Object. This means that it must either be called from within a method defined by the class that implements Cloneable, or it must be explicitly overridden by that class so that it is public. Let’s look at an example of each approach.
The following program implements Cloneable and defines the method cloneTest( ), which calls clone( ) in Object:
image
Here, the method cloneTest( ) calls clone( ) in Object and returns the result. Notice that the object returned by clone( ) must be cast into its appropriate type (TestClone).
The following example overrides clone( ) so that it can be called from code outside of its class. To do this, its access specifier must be public, as shown here:
image
The side effects caused by cloning are sometimes difficult to see at first. It is easy to think that a class is safe for cloning when it actually is not. In general, you should not implement Cloneable for any class without good reason.
Class
Class encapsulates the run-time state of a class or interface. Objects of type Class are created automatically, when classes are loaded. You cannot explicitly declare a Class object. Generally, you obtain a Class object by calling the getClass( ) method defined by Object. Class is a generic type that is declared as shown here:
class Class<T>
Here, T is the type of the class or interface represented. A sampling of methods defined by Class is shown in Table 17-15.
image
image
Table 17-15   A Sampling of Methods Defined by Class
The methods defined by Class are often useful in situations where run-time type information about an object is required. As Table 17-15 shows, methods are provided that allow you to determine additional information about a particular class, such as its public constructors, fields, and methods. Among other things, this is important for the Java Beans functionality, which is discussed later in this book.
The following program demonstrates getClass( ) (inherited from Object) and getSuperclass( ) (from Class):
image
The output from this program is shown here:
image
ClassLoader
The abstract class ClassLoader defines how classes are loaded. Your application can create subclasses that extend ClassLoader, implementing its methods. Doing so allows you to load classes in some way other than the way they are normally loaded by the Java run-time system. However, this is not something that you will normally need to do.
Math
The Math class contains all the floating-point functions that are used for geometry and trigonometry, as well as several general-purpose methods. Math defines two double constants: E (approximately 2.72) and PI (approximately 3.14).
Trigonometric Functions
The following methods accept a double parameter for an angle in radians and return the result of their respective trigonometric function:
Method
Description
static double sin(double arg)
Returns the sine of the angle specified by arg in radians.
static double cos(double arg)
Returns the cosine of the angle specified by arg in radians.
static double tan(double arg)
Returns the tangent of the angle specified by arg in radians.
The next methods take as a parameter the result of a trigonometric function and return, in radians, the angle that would produce that result. They are the inverse of their non-arc companions.
Method
Description
static double asin(double arg)
Returns the angle whose sine is specified by arg.
static double acos(double arg)
Returns the angle whose cosine is specified by arg.
static double atan(double arg)
Returns the angle whose tangent is specified by arg.
static double atan2(double x, double y)
Returns the angle whose tangent is x/y.
The next methods compute the hyperbolic sine, cosine, and tangent of an angle:
Method
Description
static double sinh(double arg)
Returns the hyperbolic sine of the angle specified by arg.
static double cosh(double arg)
Returns the hyperbolic cosine of the angle specified by arg.
static double tanh(double arg)
Returns the hyperbolic tangent of the angle specified by arg.
Exponential Functions
Math defines the following exponential methods:
Method
Description
static double cbrt(double arg)
Returns the cube root of arg.
static double exp(double arg)
Returns e to the arg.
static double expm1(double arg)
Returns e to the arg–1.
static double log(double arg)
Returns the natural logarithm of arg.
static double log10(double arg)
Returns the base 10 logarithm for arg.
static double log1p(double arg)
Returns the natural logarithm for arg + 1.
static double pow(double y, double x)
Returns y raised to the x; for example, pow(2.0, 3.0) returns 8.0.
static double scalb(double arg, int factor)
Returns arg × 2factor.
static float scalb(float arg, int factor)
Returns arg × 2factor.
static double sqrt(double arg)
Returns the square root of arg.
Rounding Functions
The Math class defines several methods that provide various types of rounding operations. They are shown in Table 17-16. Notice the two ulp( ) methods at the end of the table. In this context, ulp stands for units in the last place. It indicates the distance between a value and the next higher value. It can be used to help assess the accuracy of a result.
image
image
Table 17-16   The Rounding Methods Defined by Math
Miscellaneous Math Methods
In addition to the methods just shown, Math defines several other methods, which are shown in Table 17-17. Notice that several of the methods use the suffix Exact. These were added by JDK 8. They throw an ArithmeticException if overflow occurs. Thus, these methods give you an easy way to watch various operations for overflow.
image
Table 17-17   Other Methods Defined by Math
The following program demonstrates toRadians( ) and toDegrees( ):
image
The output is shown here:
image
StrictMath
The StrictMath class defines a complete set of mathematical methods that parallel those in Math. The difference is that the StrictMath version is guaranteed to generate precisely identical results across all Java implementations, whereas the methods in Math are given more latitude in order to improve performance.
Compiler
The Compiler class supports the creation of Java environments in which Java bytecode is compiled into executable code rather than interpreted. It is not for normal programming use.
Thread, ThreadGroup, and Runnable
The Runnable interface and the Thread and ThreadGroup classes support multithreaded programming. Each is examined next.
image
NOTE An overview of the techniques used to manage threads, implement the Runnable interface, and create multithreaded programs is presented in Chapter 11.
The Runnable Interface
The Runnable interface must be implemented by any class that will initiate a separate thread of execution. Runnable only defines one abstract method, called run( ), which is the entry point to the thread. It is defined like this:
void run( )
Threads that you create must implement this method.
Thread
Thread creates a new thread of execution. It implements Runnable and defines the following commonly used constructors:
Thread( )
Thread(Runnable threadOb)
Thread(Runnable threadOb, String threadName)
Thread(String threadName)
Thread(ThreadGroup groupOb, Runnable threadOb)
Thread(ThreadGroup groupOb, Runnable threadOb, String threadName)
Thread(ThreadGroup groupOb, String threadName)
threadOb is an instance of a class that implements the Runnable interface and defines where execution of the thread will begin. The name of the thread is specified by threadName. When a name is not specified, one is created by the Java Virtual Machine. groupOb specifies the thread group to which the new thread will belong. When no thread group is specified, the new thread belongs to the same group as the parent thread.
The following constants are defined by Thread:
MAX_PRIORITY
MIN_PRIORITY
NORM_PRIORITY
As expected, these constants specify the maximum, minimum, and default thread priorities.
The methods defined by Thread are shown in Table 17-18. In early versions of Java, Thread also included the methods stop( ), suspend( ), and resume( ). However, as explained in Chapter 11, these were deprecated because they were inherently unstable. Also deprecated are countStackFrames( ), because it calls suspend( ), and destroy( ), because it can cause deadlock.
image
image
image
Table 17-18   The Methods Defined by Thread
ThreadGroup
ThreadGroup creates a group of threads. It defines these two constructors:
ThreadGroup(String groupName)
ThreadGroup(ThreadGroup parentOb, String groupName)
For both forms, groupName specifies the name of the thread group. The first version creates a new group that has the current thread as its parent. In the second form, the parent is specified by parentOb. The non-deprecated methods defined by ThreadGroup are shown in Table 17-19.
image
image
Table 17-19   The Methods Defined by ThreadGroup
Thread groups offer a convenient way to manage groups of threads as a unit. This is particularly valuable in situations in which you want to suspend and resume a number of related threads. For example, imagine a program in which one set of threads is used for printing a document, another set is used to display the document on the screen, and another set saves the document to a disk file. If printing is aborted, you will want an easy way to stop all threads related to printing. Thread groups offer this convenience. The following program, which creates two thread groups of two threads each, illustrates this usage:
image
image
Sample output from this program is shown here (the precise output you see may differ):
image
image
Inside the program, notice that thread group A is suspended for four seconds. As the output confirms, this causes threads One and Two to pause, but threads Three and Four continue running. After the four seconds, threads One and Two are resumed. Notice how thread group A is suspended and resumed. First, the threads in group A are obtained by calling enumerate( ) on group A. Then, each thread is suspended by iterating through the resulting array. To resume the threads in A, the list is again traversed and each thread is resumed. One last point: This example uses the recommended approach to suspending and resuming threads. It does not rely upon the deprecated methods suspend( ) and resume( ).
ThreadLocal and InheritableThreadLocal
Java defines two additional thread-related classes in java.lang:
•  ThreadLocal    Used to create thread local variables. Each thread will have its own copy of a thread local variable.
•  InheritableThreadLocal    Creates thread local variables that may be inherited.
Package
Package encapsulates version data associated with a package. Package version information is becoming more important because of the proliferation of packages and because a Java program may need to know what version of a package is available. The methods defined by Package are shown in Table 17-20. The following program demonstrates Package, displaying the packages about which the program currently is aware:
image
image
image
Table 17-20   The Methods Defined by Package
RuntimePermission
RuntimePermission relates to Java’s security mechanism and is not examined further here.
Throwable
The Throwable class supports Java’s exception-handling system and is the class from which all exception classes are derived. It is discussed in Chapter 10.
SecurityManager
SecurityManager supports Java’s security system. A reference to the current security manager can be obtained by calling getSecurityManager( ) defined by the System class.
StackTraceElement
The StackTraceElement class describes a single stack frame, which is an individual element of a stack trace when an exception occurs. Each stack frame represents an execution point, which includes such things as the name of the class, the name of the method, the name of the file, and the source-code line number. An array of StackTraceElements is returned by the getStackTrace( ) method of the Throwable class.
StackTraceElement has one constructor:
StackTraceElement(String className, String methName, string fileName, int line)
Here, the name of the class is specified by className, the name of the method is specified in methName, the name of the file is specified by fileName, and the line number is passed in line. If there is no valid line number, use a negative value for line. Furthermore, a value of –2 for line indicates that this frame refers to a native method.
The methods supported by StackTraceElement are shown in Table 17-21. These methods give you programmatic access to a stack trace.
image
Table 17-21   The Methods Defined by StackTraceElement
Enum
As described in Chapter 12, an enumeration is a list of named constants. (Recall that an enumeration is created by using the keyword enum.) All enumerations automatically inherit Enum. Enum is a generic class that is declared as shown here:
class Enum<E extends Enum<E>>
Here, E stands for the enumeration type. Enum has no public constructors.
Enum defines several methods that are available for use by all enumerations, which are shown in Table 17-22.
image
Table 17-212   The Methods Defined by Enum
ClassValue
ClassValue can be used to associate a value with a type. It is a generic type defined like this:
Class ClassValue<T>
It is designed for highly specialized uses, not for normal programming.
The CharSequence Interface
The CharSequence interface defines methods that grant read-only access to a sequence of characters. These methods are shown in Table 17-23. This interface is implemented by String, StringBuffer, and StringBuilder, among others.
The Comparable Interface
Objects of classes that implement Comparable can be ordered. In other words, classes that implement Comparable contain objects that can be compared in some meaningful manner. Comparable is generic and is declared like this:
interface Comparable<T>
Here, T represents the type of objects being compared.
image
Table 17-23   The Methods Defined by CharSequence
The Comparable interface declares one method that is used to determine what Java calls the natural ordering of instances of a class. The signature of the method is shown here:
int compareTo(T obj)
This method compares the invoking object with obj. It returns 0 if the values are equal. A negative value is returned if the invoking object has a lower value. Otherwise, a positive value is returned.
This interface is implemented by several of the classes already reviewed in this book. Specifically, the Byte, Character, Double, Float, Long, Short, String, and Integer classes define a compareTo( ) method. So does Enum.
The Appendable Interface
Objects of a class that implements Appendable can have a character or character sequences appended to it. Appendable defines these three methods:
Appendable append(char ch) throws IOException
Appendable append(CharSequence chars) throws IOException
Appendable append(CharSequence chars, int begin, int end) throws IOException
In the first form, the character ch is appended to the invoking object. In the second form, the character sequence chars is appended to the invoking object. The third form allows you to indicate a portion (the characters running from begin through end–1) of the sequence specified by chars. In all cases, a reference to the invoking object is returned.
The Iterable Interface
Iterable must be implemented by any class whose objects will be used by the for-each version of the for loop. In other words, in order for an object to be used within a for-each style for loop, its class must implement Iterable. Iterable is a generic interface that has this declaration:
interface Iterable<T>
Here, T is the type of the object being iterated. It defines one abstract method, iterator( ), which is shown here:
Iterator<T> iterator( )
It returns an iterator to the elements contained in the invoking object.
Beginning with JDK 8, Iterable also defines two default methods. The first is called forEach( ):
default void forEach(Consumer<? super T> action)
For each element being iterated, forEach( ) executes the code specified by action. (Consumer is a functional interface added by JDK 8 and defined in java.util.function. See Chapter 19.)
The second default method is spliterator( ), shown next:
default Spliterator<T> spliterator( )
It returns a Spliterator to the sequence being iterated. (See Chapters 18 and 29 for details on spliterators.)
image
NOTE Iterators are described in detail in Chapter 18.
The Readable Interface
The Readable interface indicates that an object can be used as a source for characters. It defines one method called read( ), which is shown here:
int read(CharBuffer buf) throws IOException
This method reads characters into buf. It returns the number of characters read, or –1 if an EOF is encountered.
The AutoCloseable Interface
AutoCloseable provides support for the try-with-resources statement, which implements what is sometimes referred to as automatic resource management (ARM). The try-with-resources statement automates the process of releasing a resource (such as a stream) when it is no longer needed. (See Chapter 13 for details.) Only objects of classes that implement AutoCloseable can be used with try-with-resources. The AutoCloseable interface defines only the close( ) method, which is shown here:
void close( ) throws Exception
This method closes the invoking object, releasing any resources that it may hold. It is automatically called at the end of a try-with-resources statement, thus eliminating the need to explicitly invoke close( ). AutoCloseable is implemented by several classes, including all of the I/O classes that open a stream that can be closed.
The Thread.UncaughtExceptionHandler Interface
The static Thread.UncaughtExceptionHandler interface is implemented by classes that want to handle uncaught exceptions. It is implemented by ThreadGroup. It declares only one method, which is shown here:
void uncaughtException(Thread thrd, Throwable exc)
Here, thrd is a reference to the thread that generated the exception and exc is a reference to the exception.
The java.lang Subpackages
Java defines several subpackages of java.lang:
•  java.lang.annotation
•  java.lang.instrument
•  java.lang.invoke
•  java.lang.management
•  java.lang.ref
•  java.lang.reflect
Each is briefly described here.
java.lang.annotation
Java’s annotation facility is supported by java.lang.annotation. It defines the Annotation interface, the ElementType and RetentionPolicy enumerations, and several predefined annotations. Annotations are described in Chapter 12.
java.lang.instrument
java.lang.instrument defines features that can be used to add instrumentation to various aspects of program execution. It defines the Instrumentation and ClassFileTransformer interfaces, and the ClassDefinition class.
java.lang.invoke
java.lang.invoke supports dynamic languages. It includes classes such as CallSite, MethodHandle, and MethodType.
java.lang.management
The java.lang.management package provides management support for the JVM and the execution environment. Using the features in java.lang.management, you can observe and manage various aspects of program execution.
java.lang.ref
You learned earlier that the garbage collection facilities in Java automatically determine when no references exist to an object. The object is then assumed to be no longer needed and its memory is reclaimed. The classes in the java.lang.ref package provide more flexible control over the garbage collection process.
java.lang.reflect
Reflection is the ability of a program to analyze code at run time. The java.lang.reflect package provides the ability to obtain information about the fields, constructors, methods, and modifiers of a class. Among other reasons, you need this information to build software tools that enable you to work with Java Beans components. The tools use reflection to determine dynamically the characteristics of a component. Reflection was introduced in Chapter 12 and is also examined in Chapter 30.
java.lang.reflect defines several classes, including Method, Field, and Constructor. It also defines several interfaces, including AnnotatedElement, Member, and Type. In addition, the java.lang.reflect package includes the Array class that enables you to create and access arrays dynamically.
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.191.168.8