Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống
1
/ 91 trang
THÔNG TIN TÀI LIỆU
Thông tin cơ bản
Định dạng
Số trang
91
Dung lượng
1,11 MB
Nội dung
We can define our own exceptions by deriving a new class from Exception or one of its descendants. The class we choose as the parent depends on what situation or condition the new exception represents. The program in Listing 8.5 instantiates an exception object and throws it. The exception is created from the OutOfRangeException class, which is shown in Listing 8.6. Note that this exception is not part of the Java standard class library. It was created to represent the situation in which a value is outside a particular valid range. After reading in an input value, the main method evaluates it to see whether it is in the valid range. If not, the throw statement is executed. A throw statement is used to begin exception propagation. Because the main method does not catch and handle the exception, the program will terminate if the exception is thrown, printing the message associated with the exception. We create the OutOfRangeException class by extending the Exception class. Often, a new exception is nothing more than what you see in this example: an extension of some existing exception class that stores a particular message describing the situation it represents. The important point is that the class is ulti- mately a descendant of the Exception class and the Throwable class, which gives it the ability to be thrown using a throw statement. 8.0 exceptions 457 listing 8.4 continued // // Performs a calculation to produce an exception. It is not // caught and handled at this level. // public void level3 () { int numerator = 10, denominator = 0; System.out.println("Level 3 beginning."); int result = numerator / denominator; System.out.println("Level 3 ending."); } } A new exception is defined by deriving a new class from the Exception class or one of its descendants. key concept 458 CHAPTER 8 exceptions and i/o streams The type of situation handled by this program, in which a value is out of range, does not need to be represented as an exception. We’ve previously handled such situations using conditionals or loops. Whether you handle a situation using an exception or whether you take care of it in the normal flow of your program is an important design decision. figure 8.1 Part of the Error and Exception class hierarchy Exception Object Throwable Error AWTError VirtualMachineError ThreadDeath LinkageError NullPointerException IndexOutOfBoundsException ArithmeticException ClassNotFoundException NoSuchMethodException IllegalAccessException RunTimeException 8.0 exceptions 459 listing 8.5 //******************************************************************** // CreatingExceptions.java Author: Lewis/Loftus // // Demonstrates the ability to define an exception via inheritance. //******************************************************************** import cs1.Keyboard; public class CreatingExceptions { // // Creates an exception object and possibly throws it. // public static void main (String[] args) throws OutOfRangeException { final int MIN = 25, MAX = 40; OutOfRangeException problem = new OutOfRangeException ("Input value is out of range."); System.out.print ("Enter an integer value between " + MIN + " and " + MAX + ", inclusive: "); int value = Keyboard.readInt(); // Determines if the exception should be thrown if (value < MIN || value > MAX) throw problem; System.out.println ("End of main method."); // may never reach } } Enter an integer value between 25 and 40, inclusive: 69 Exception in thread "main" OutOfRangeException: Input value is out of range. at CreatingExceptions.main(CreatingExceptions.java:20) output checked and unchecked exceptions There is one other issue concerning exceptions that we should explore. Some exceptions are checked, whereas others are unchecked. A checked exception must either be caught by a method or it must be listed in the throws clause of any method that may throw or propagate it. A throws clause is appended to the header of a method definition to formally acknowl- edge that the method will throw or propagate a particular exception if it occurs. An unchecked exception generally should not be caught and requires no throws clause. The only unchecked exceptions in Java are objects of type RuntimeException or any of its descendants. All other exceptions are considered checked exceptions. The main method of the CreatingExceptions program has a throws clause, indicating that it may throw an OutOfRangeException. This throws clause is required because the OutOfRangeException was derived from the Exception class, making it a checked exception. Errors are similar to RuntimeException and its descendants in that they should not be caught and do not require a throws clause. 460 CHAPTER 8 exceptions and i/o streams listing 8.6 //******************************************************************** // OutOfRangeException.java Author: Lewis/Loftus // // Represents an exceptional condition in which a value is out of // some particular range. //******************************************************************** public class OutOfRangeException extends Exception { // // Sets up the exception object with a particular message. // OutOfRangeException (String message) { super (message); } } The throws clause on a method header must be included for checked excep- tions that are not caught and handled in the method. key concept 8.1 input/output streams 461 8.1 input/output streams A stream is an ordered sequence of bytes. The term stream comes from the analogy that as we read and write information, the data flows from a source to a destination (or sink) as water flows down a stream. The source of the information is like a spring filling the stream, and the des- tination is like a cave into which the stream flows. In a program, we treat a stream as either an input stream, from which we read information, or as an output stream, to which we write information. That is, a program serves either as the spring filling the stream or as the cave receiving the stream. A program can deal with multiple input and output streams at one time. A particular store of data, such as a file, can serve either as an input stream or as an output stream to a program, but it cannot be both at the same time. The java.io package of the Java standard class library provides many classes that let us define streams with particular characteristics. Some of the classes deal with files, others with memory, and others with strings. Some classes assume that the data they handle consists of characters, whereas others assume the data con- sists of raw bytes of binary information. Some classes provide the means to manipulate the data in the stream in some way, such as buffering the information or numbering it. By combining classes in appropriate ways, we can create objects that represent a stream of information that has the exact characteristics we want for a particular situation. The sheer number of classes in the java.io package prohibits us from discuss- ing them all in detail. Instead, our goal is to provide an overview of the classes involved, and then explore a few specific situations that are particularly useful. In addition to dividing the classes in the java.io package into input and out- put streams, they can be subdivided in two other primary ways. First, we can divide the classes by the type of information on which they operate. There are basically two categories of classes in this regard: those that operate on character data and those that operate on byte data. We can also divide the classes in the java.io package by the role they play. Again we have two categories: those that represent a particular type of source or sink for information, such as a file or net- work connection, and those that provide the means to alter or manage the basic data in the stream. Most of the classes in the java.io package fall into one of the subdivisions created by these categories, as shown in Fig. 8.2. A stream is a sequential sequence of bytes, it can be used as a source of input or a destination for output. key concept 462 CHAPTER 8 exceptions and i/o streams character streams versus byte streams A character stream is designed to manage 16-bit Unicode characters. The stream is nothing more than a lengthy series of characters, though they can be read and written in chunks (such as one line at a time) if we set up the stream with the proper characteristics. A byte stream, on the other hand, man- ages 8-bit bytes of raw binary data. How the bytes are interpreted and used once read depends on the program that reads them. Although they can be used to read and write any data, byte streams are typically used to read and write binary data such as sounds and images. The classes that manage character streams and byte streams are cleanly divided in the I/O class inheritance hierarchy. The InputStream and OutputStream classes and all their descendants represent byte streams. The Reader and Writer classes and all their descendants represent character streams. Figure 8.3 shows this relationship. The two class hierarchies share some basic similarities. For example, the Reader and InputStream classes provide similar methods but for different types of data. For example, they both provide a basic read method. The read method of Reader reads one character or an array of characters; the read method of InputStream reads one byte or an array of bytes. Such paired classes are com- mon between the hierarchies but are not always consistent. data streams versus processing streams A data stream is a stream that represents a particular source or destination stream, such as a string in memory or a file on disk. A processing stream (sometimes called figure 8.2 Dividing the Java I/O classes into categories Data Streams Processing Streams Character Streams Byte Streams Output Streams Input Streams A character stream manages Unicode characters, whereas a byte stream manages 8-bit bytes. key concept 8.1 input/output streams 463 figure 8.3 The Java I/O class hierarchy ByteArrayInputStream FileInputStream InputStream Object OutputStream Reader Writer PipedInputStream ObjectInputStream FilterInputStream SequenceInputStream ByteArrayOutputStream FileOutputStream PipedOutputStream ObjectOutputStream FilterOutputStream BufferedOutputStream DataOutputStream CharArrayReader PipedReader StringReader BufferedReader FilterReader InputStreamReader LineNumberReader PushBackReader FileReader PrintStream BufferedInputStream DataInputStream PushbackInputStream CharArrayWriter PipedWriter StringWriter BufferedWriter FilterWriter OutputStreamWriter FileWriter PrintWriter 464 CHAPTER 8 exceptions and i/o streams a filtering stream) performs some sort of manipulation on the data in a stream, such as converting it from one format to another or buffering the input to deliver it in chunks. By combining data streams with pro- cessing streams we can create an input or output stream that behaves exactly as we wish. The classes that represent data streams and processing streams are the same classes that represent character streams and byte streams. It is just another way to categorize them. The data streams and processing streams cut across the class hierarchies, however. That is, all four of the primary class hierar- chies in the Java I/O classes can be further subdivided into those that represent data streams and those that represent processing streams. the IOException class Many operations performed by I/O classes can potentially throw an IOException. The IOException class is the parent of several exception classes that represent problems when trying to perform I/O. An IOException is a checked exception. As described earlier in this chapter that means that either the exception must be caught, or all methods that propa- gate it must list it in a throws clause of the method header. Because I/O often deals with external resources, many problems can arise in programs that attempt to perform I/O operations. For example, a file from which we want to read might not exist; when we attempt to open the file, an exception will be thrown because that file can’t be found. In general, we should try to design programs to be as robust as possible when dealing with potential problems. 8.2 standard I/O Three streams are often called the standard I/O streams. They are listed in Fig. 8.4. The System class contains three object reference variables (in, out, and err) that represent the three standard I/O streams. These references are declared as both public and static, which allows them to be accessed directly through the System class. We’ve been using the standard output stream, with calls to System.out.prinln for instance, in examples throughout this book. Finally we can explain the details underlying that method invocation. In Chapter Java I/O classes can be divided into data streams, which repre- sent a particular source or des- tination, or processing streams, which perform operations on data in an existing stream. key concept Three variables in the System class represent the standard I/O streams. key concept 8.2 standard I/O 465 5 we explored some of the details of the Keyboard class, which masks the use of the standard input stream. We can now explore those issues in more detail as well. The standard I/O streams, by default, represent particular I/O devices. System.in typically represents keyboard input, whereas System.out and System.err typically represent a particular window on the monitor screen. The System.out and System.err streams write output to the same window by default (usually the one in which the program was executed), though they could be set up to write to different places. The System.err stream is usually where error messages are sent. All three of these streams are created and open by default, and in one sense are ready for use by any Java program. Both the System.out and System.err ref- erence variables are declared to be of type PrintStream. The System.in refer- ence is declared to be a generic InputStream. PrintStream objects automatically have print and println methods defined for them. This makes the System.out object useful without any further manipu- lations. Note that PrintStream is technically a byte stream that converts objects and numbers into text for easy output. It is typically used for debugging and sim- ple examples. PrintStream does not handle advanced internationalization and error checking; the PrintWriter class is a better choice for this. The System.in reference is deliberately declared to be a generic InputStream reference so that it is not restricted in its use. This means, however, that it must usually be mapped into a stream with more useful characteristics. This is one of the reasons we created the Keyboard class. the Keyboard class revisited Recall that the Keyboard class was written by the authors of this text to make reading values from the standard input stream easier, especially when we were figure 8.4 Standard I/O streams System.in Standard input stream. Standard output stream. Standard error stream (output for error messages) System.out System.err Standard I/O Stream Description 466 CHAPTER 8 exceptions and i/o streams just getting started and had other issues to worry about. The Keyboard class provides methods such as readInt, readFloat, and readString to obtain a particular type of input value. In Chapter 5, we explored some of the details that the Keyboard class took care of for us. Now we can peel back the cover even more, revealing the underlying stan- dard Java features used to write the Keyboard class. The Keyboard class hides the following I/O operations: ◗ the declaration of the standard input stream in a useful form ◗ the handling of any IOException that may be thrown ◗ the parsing of an input line into separate tokens ◗ the conversion of an input value to its expected type ◗ the handling of conversion problems Because System.in is defined as a reference to a generic InputStream object, it has by default only the basic ability to read and write byte data. To modify it into a more useful form, the Keyboard class performs the following declaration: InputStreamReader isr = new InputStreamReader (System.in); BufferedReader stdin = new BufferedReader (isr); The first line creates an InputStreamReader object, which converts the original byte input stream into a character input stream. The second line transforms it into a BufferedReader, which allows us to use the readLine method to get an entire line of character input in one operation. In the Keyboard class, each invocation of readLine is performed inside a try block so that an IOException, if it is thrown, can be caught and handled. The readLine method returns a string that includes all characters included in the input line. If that input line contains multiple values, they must be separated into individual tokens. Recall that the StringTokenizer class performs just that kind of service. The Keyboard class constantly keeps track of the current input line and uses a StringTokenizer object to extract the next token when requested. On top of all of this, each token, as it is extracted from the input line, may be needed as a particular primitive type, such as an int. Therefore each method of the Keyboard class performs the proper conversion. For example, the readInt method of the Keyboard class takes the next token from the input line and calls the parseInt method of the Integer wrapper class to convert the string to an int. Similar processing can be seen in the file I/O examples in the next section. The Keyboard class, though not part of the Java standard class library, provides an abstraction for several I/O operations on the standard input stream. key concept [...]... retain the data written to them The data that is contained in the file test.dat after the TestData program is run might look like this: 85 90 93 15 82 79 52 71 70 98 74 57 41 66 22 16 67 65 24 84 86 61 91 79 18 81 64 41 68 81 98 47 28 40 69 10 85 82 64 41 23 61 27 10 59 89 88 26 24 76 key concept The TestData program uses nested for loops to compute a random value and print it to the file After all values... Clip: Cog: 14 at 3.35 = 46. 9 132 at 0.32 = 42.24 58 at 1.92 = 111. 36 28 at 4.17 = 1 16. 76 25 at 1.75 = 43.75 409 at 0.12 = 49.08 142 at 2.08 = 295. 36 The program uses the data it reads from the file to create several InventoryItem objects (see Listing 8.8) The data read from the file is passed to the InventoryItem constructor Certain parts of the processing in the CheckInventory program are performed within... the horizontal positioning of the label in its allotted space with the setting of the orientation between the text and the image The third parameter of the constructor determines the first, and the explicit method calls determine the second In this program, the layout manager of the program overrides the horizontal positioning of the labels anyway, centering them in each row of the panel Layout managers... purpose in this program as it does in the Keyboard class—to buffer input and provide the readLine method— even though the actual source of the information is quite different in each case This situation illustrates why the designers of the java. io package separated the responsibilities as they did The Java I/O classes can be combined in many different ways to provide exactly the kind of interaction and... all file streams explicitly when they are no longer needed 474 CHAPTER 8 exceptions and i/o streams 33 89 73 36 54 91 42 73 95 58 19 41 18 14 63 80 96 30 17 28 24 37 40 64 94 23 98 10 78 50 89 28 64 54 59 23 61 15 80 88 51 28 44 48 73 21 41 52 35 38 8.4 object serialization key concept When a program terminates, the data it used is destroyed unless an effort is made to store the data externally We’ve... //******************************************************************** // TestData .java Author: Lewis/Loftus // // Demonstrates the use of a character file output stream //******************************************************************** import java. util.Random; import java. io.*; public class TestData { // // Creates a file of test data that consists of ten lines each // containing ten integer values... Serializable interface, so we can store an entire list of objects in one operation So if we had stored the CountryInfo objects in an ArrayList (instead of a regular array) in the WriteCountryInfo program, we could have written the entire set of objects out in one operation Likewise, the ReadCountryInfo program could have then read the entire ArrayList of CountryInfo objects from the file in one operation... display 487 488 exceptions and i/o streams CHAPTER 8 listing 8. 16 //******************************************************************** // LabelPanel .java Author: Lewis/Loftus // // Represents the primary display for the LabelDemo program //******************************************************************** import java. awt.*; import javax.swing.*; public class LabelPanel extends JPanel { private... ("United States of America", "USA", "Washington, D.C.", 962 9091L, 278058900L); countries[1] = new CountryInfo ("Russia", "RUS", "Moscow", 17075200L, 145470200L); countries[2] = new CountryInfo ("Italy", "ITA", "Rome", 301230L, 5 767 9800L); countries[3] = new CountryInfo ("Sweden", "SWE", "Stockholm", 449 964 L, 8875100L); countries[4] = new CountryInfo ("Poland", "POL", "Warsaw", 31 268 5L, 3 863 3900L); int... 8.18 //******************************************************************** // DirectionPanel .java Author: Lewis/Loftus // // Represents the primary display panel for the Direction program //******************************************************************** import javax.swing.*; import java. awt.*; import java. awt.event.*; public class DirectionPanel extends JPanel { private final int WIDTH = 300, . TestData program is run might look like this: 85 90 93 15 82 79 52 71 70 98 74 57 41 66 22 16 67 65 24 84 86 61 91 79 18 81 64 41 68 81 98 47 28 40 69 10 85 82 64 41 23 61 27 10 59 89 88 26 24 76 Output. test.dat output 33 89 73 36 54 91 42 73 95 58 19 41 18 14 63 80 96 30 17 28 24 37 40 64 94 23 98 10 78 50 89 28 64 54 59 23 61 15 80 88 51 28 44 48 73 21 41 52 35 38 8.4 object serialization When a program terminates,. throws clause. 460 CHAPTER 8 exceptions and i/o streams listing 8 .6 //******************************************************************** // OutOfRangeException .java Author: Lewis/Loftus // //