Java basics notes -7- exceptions, assertions and logging

Java basics notes -7- exceptions, assertions and logging

In an ideal world, the user input format data are always right, choose to open the file must also exist, and never appear bug. So far, the book presented to us are in such a code seems ideal realm. However, in the real world is full of bad data and code with the problem, we are now discussing Java programming language mechanisms to deal with these issues fertile time.

People feel uncomfortable when an error is encountered. If a user program during operation, due to an error in the program or some external environment caused by the loss of user data, the user may no longer have to use this program, in order to avoid the occurrence of such things, or at least you should do the following :

  • Notice error to the user;
  • Save all the results of the work;
  • It allows the user to exit the program with proper form.

For exceptions, for example, may result in erroneous input program crashes, Java uses a technique called error exception handling (exception handing) capture mechanisms to deal with. Java exception handling in C ++ or Delphi exception handling is very similar. Part 1 of this chapter first introduced Java exception.

During the test, the need for a lot of testing to verify the correctness of the program operation. However, these tests can be very time-consuming, do not keep them after the testing is complete. Therefore, these tests can be deleted, and when other tests need to paste them back, this is a very tedious thing. Part 2 of this chapter explains how to use assertions to selectively enable detection.

When a program error occurs, it is not always able to communicate with the user or terminal. At this point, you may wish to record the issues arising under, for later analysis. Part 3 of this chapter discusses standard Java logging framework.

1 processing error

Assume that an error occurred during a Java program to run. This error may be due to the file that contains the error message, or network connectivity problems caused, but also may be due to invalid array index, or the attempt to use a reference object has not been assigned caused. Users expect when an error occurs, the program can use some irrational behavior. If due to an error so that certain operation is not completed, the program should:

  • Return to a safe state, and allows users to perform some other commands; or
  • It allows users to save the results of all operations, and the proper way to terminate the program

To do this is not an easy thing. The reason for this is to detect (or throws) an error condition code is usually far removed from the code to allow data to a safe state, or be able to save the result of the user, and normally exit the program. Exception handling task is to transfer control from where the error occurred to the error processor capable of handling this situation. In order to be able to handle exceptions in your program, you must study program may appear errors and problems, as well as the types of issues that need attention.

  1. User input error

    In addition to the inevitable keyboard input errors, some users prefer their own ways, do not comply with the requirements of the program. For example, suppose a user requests a connection URL, and the syntax is not correct. In this program code must be checked, if not checked, it will alert the network layer.

  2. Device Error

    Hardware does not always make it what to do and what it will do. The printer may be turned off. Web pages may temporarily can not browse. In the process a task, hardware problems often arise. For example, the printer during printing may not be of paper.

  3. Physical limitations

    The disk is full, the available storage space has been used up.

  4. Code Error
    procedural methods may not execute properly. For example, the method may return the wrong answer, or mistakenly call other methods. Array index calculations are not legitimate, trying to find a record that does not exist in the hash table, or trying to find an empty pop operations to perform, these are code errors.

For a wrong method, the traditional approach is to return a special error code analysis by the calling method. For example, a method for reading information from a file, the return value is usually not a standard character, but a -1 indicating the end of the file. This approach for many abnormal conditions are possible. There is also a common condition indicates an error return value is a null reference.

Unfortunately, not all can return an error code in any case. There may not explicitly distinguish between valid data and invalid data. One way to integer can not simply return an error by returning -1, since -1 is likely to be a perfectly legitimate result. As discussed in Chapter 5, as described above, in Java, if a method is not capable of using the normal channels, complete its task, you can exit the method by another path. In this case, the method does not return any value, but throw (the throw) encapsulates a target error message. Note that this method will immediately exit does not return any value. In addition, the code calling this method will not be able to continue, instead, exception handling mechanism began to search an exception handler can handle this abnormal situation (exception handler). Abnormal has its own grammar and specific inheritance structure. First, tell us about the following syntax, and then given skills to effectively use such language features.

1.1 malfunction classification

In the Java programming language, the exception object is an instance of Throwable derived class. You can also see later, if the built-in exception classes in Java can not meet the demand, users can create their own exception classes.

7-1 is a simplified schematic diagram of a Java exception hierarchy.

        Throwable
Error               Expception
            IOException     RuntimeException

It should be noted that all exceptions are inherited from the Throwable, but the next layer immediately divided into two branches: Error and Exception

Error class hierarchy describes internal errors and resource depletion Java run-time system error. Applications should not throw this type of object. If such an internal error, in addition to notice to the user, and try to make the program terminate safely outside, he could do no more. This is rarely the case.

In the design of Java programs, we need to focus Exception hierarchy. This hierarchical structure and divided into two branches: a branch derived from RuntimeException; the other branches contain an exception. The rules are divided into two branches: the program error caused an abnormal belong RuntimeException; and the program itself is not the problem, but because, like I / O error caused by abnormalities such problems belong to other anomalies:

Derived from RuntimeException exceptions include the following situations:

  • Error type conversion.
  • Array access out of bounds
  • Null pointer access

Is not derived from RuntimeException exceptions include:

  • Trying to read the data in the back end of the file.
  • I try to open a file that does not exist.
  • Attempts to find a Class object according to the given string, and the string representation of this class does not exist

"If RuntimeException abnormal, then it must be your problem" is a fairly reasonable rules. It should be detected by the array index out of bounds to avoid ArraylndexOutOfBoundsException abnormal; by detecting whether or not it should be null to prevent the occurrence of a NullPointerException before using variables.

How to deal with file does not exist yet? Do not check if a file exists and then open it anyway? Ah, this file before it is possible to check whether there had been deleted in you. Therefore, "the existence of" depending on the environment, not just depends on your code.

Born in the Java language specification will send RuntimeException Error class or classes of all the exceptions referred to as non unchecked (unchecked) exceptions, all other abnormalities called by check (checked) exception. These are two very useful term, will be used later. The compiler will check whether an exception provided for all exception handler under investigation.

1.2 Statement checked exception

If you encounter a situation can not be processed, then the Java method can throw an exception. The reason is simple: a method not only need to tell the compiler what value will be returned, but also to tell the compiler is likely what went wrong. For example, a piece of code to read a file to know it is possible to read the file does not exist or is empty, therefore, attempt to deal with the code file information required to notify the compiler may throw an exception IOException class.

In the first part of its method should declare all the possible exceptions thrown. This may be thrown from the types of this method reflects the header checked exception. For example, the following statement is a class constructor FilelnputStream provided in the standard library (more information about the input and output volumes see Chapter 2 Ⅱ in.)

public FilelnputStream(String name) throws FileNotFoundException

This statement indicates that the constructor will produce a FilelnputStream String object based on the given parameters, but might also throw a FileNotFoundException exception. If this bad happens, the constructor does not initialize a new FileInputStream object, but throws a FileNotFoundException class object. If this method is really threw out an exception object, the system will start searching for an exception handler runs, in order to know how to deal with FileNotFoundException object.

When writing your own method, without having to throw all possible exceptions are declared. As for when required by the method throws an exception clause specifies what exceptions must be declared using the throws clause, need to keep in mind in the face of the following four cases should throw an exception:

  • 1) a call to check that throw exception by, e.g., FilelnputStream constructor.
  • 2) the program is running errors are found, and using the throw statement throws a checked exception (The next section describes in detail the throw statement).
  • 3) an error occurs procedure, e.g., a [-1] = 0 will throw an ArraylndexOutOffloundsException such non checked exception.
  • 4) Java virtual machine and runtime library internal error appears.

If one of the first two situations, you must tell the programmers call this method may throw an exception. why? Because any method throws an exception are likely to be a death trap. If the processor does not catch this exception, the currently executing thread will end.

For those Java methods may be used by others, should be based on exception specifications (exception specification), in the first part of this statement method will throw an exception.

class MyAnimation {
    ...
    public Image loadlmage(String s) throws IOException {
        ...
    }
}

If a method may throw more checked exception type, then you must list all the exception classes in the header method. Separated by a comma between each exception class. As shown in the following example:

class MyAnimation {
    ...
    public Image loadlmage(String s) throws FileNotFoundException,EOFException
    {
        ...
    }
}

However, Java does not need to declare an internal error, that is inherited from Error error. Any program code that has the potential to throw those exceptions, we have not any ability to control it.

Similarly, statements that are not and should not be checked exception inherit from RuntimeException

class MyAnimation {
   ...
   void drawlmage(int i) throws ArraylndexOutOfBoundsException // bad style
   {
       ...
   }
}

These runtime errors completely under our control. If the array index error of particular concern triggered, it should be more time spent on correcting errors in the program, rather than the instructions on the likelihood of these errors.

In summary, a method must declare all the possible throws the checked exception subject, rather than checked exception either can not control (Error), or should be avoided (RuntimeException). If the method does not declare all checked exception, the compiler may occur will issue an error message.

Of course, from the previous example we can know: in addition to declare the exception, can also capture exception. Than it would be abnormal not to be thrown into the method does not require throws specification. Later, we will discuss how to decide an exception is caught, or was thrown by other processors for processing.

Warning: If you override a superclass in a subclass, subclass abnormalities more common method declared in the statement can not be checked exception than the superclass method (that is, the subclass method can throw more specific abnormal, or not throw any exceptions) in particular should be noted that, if the superclass method does not throw any checked exception, a subclass can not throw any checked exception. For example, if the coverage JComponent.paintComponent method, the superclass this method does not throw any exceptions, so the custom paintComponent can not throw any checked exception.

If an exception in a method declaration class will throw an exception, and this exception is an instance of a particular class, then this method it is possible to throw an exception of this class, or any class of a subclass . For example, FilelnputStream constructor statement will have a IOExcetion may throw an exception, but did not know specifically what kind of IOException anomaly. It may be an IOException, it may be a subclass of the abnormality, e.g., a FileNotFoundException

1.3 How to throw an exception

Assume some very bad things happened in the program code. A method called readData is reading a header file with the following information:

Content-length: 1024

However, after reading 733-character file over. We think this is an abnormal situation, hoping to throw an exception.

You must first decide what type of exception should be thrown. The IOException the abnormality is attributed to a good choice. After carefully reading the Java API documentation will find: EOFException description of the exception is "in the input process, encountered a signal of unexpected EOF". This is what we want to throw. The following is a statement throws this exception:

throw new EOFException();

or

EOFException e = new EOFException();
throw e;
String readData(Scanner in) throws EOFException
{
    ...
    while(...) 
    {
        if (!in.hasNext()) // EOF encountered
        {
            if (n < len)
                throw new EOFException();
        }
        ...
    }
    return s;
}

EOFException class there is a structure containing a string parameter. This constructor can be more detailed description of the abnormal situation.

String gripe = "Content-length: " + len + ", Received: " + n;
throw new EOFException(gripe);

Have previously seen, for an existing exception class, it is very easy to throw, in this case:

  • 1) find an appropriate exception class.
  • 2) create an object of this class.
  • 3) objects thrown.

Once the method throws an exception, this method can not be returned to the caller. In other words, you do not have to worry about default or error code returned.

1.4 Creating exception class

In the program, you may experience any of the standard exception classes are not able to adequately describe the problem clearly. In this case, create your own exception class is a logical thing. We need to do is define a class derived from Exception or derived from class Exception subclasses. For example, the definition of a class derived from IOException. Traditionally, the class definition should contain two constructors, a default constructor; the other is configured with a detailed description of an information (super class Throwable toString method will print out the details, which in debugging very useful).

class FileFormatException extends IOException
{
    public FileFormatException() {}
    public FileFormatException(String gripe) {
        super(gripe);
    }
} 

Now, you can throw your own exception types defined in the.

String readData(BufferedReader in) throws FileFormatException {
    while (...) {
        if (ch == -1 ) // EOF encountered
        {
            if (n < len) 
                throw new FileFornatException();
        }
        ...
    }
    return s;
}
Throwable();   //构造一个新的Throwabie对象,这个对象没有详细的描述信息。
Throwable(String message);  //构造一个新的throwabie对象,这个对象带有特定的详细描述信息。习惯上,所有派生的异常类都支持一个默认的构造器和一个带有详细描述信息的构造器。 
String getMessage();  //获得Throwabie对象的详细描述信息

2 catch the exception

So far, already know how to throw an exception. This process is very easy. Just do not throw it stepped reason. Of course, some code must catch the exception. Catch exceptions requires careful planning. This is the content of the following sections to be introduced.

2.1 catch the exception

If an exception occurs not capture anywhere, that program will terminate execution and print out abnormal messages on the console, including content type and stack exception. For a graphical interface program (applet and application), after catching exceptions, it will print out the information heap Zhan, but the program will return to the processing cycle of the user interface (GUI when debugging program, the best guarantee of the console window visible and it is not minimized).

To catch an exception, you must set the try / catch block. The simplest try blocks as follows:

try
{
    code
    more code
    more code
}
catch (ExceptionType e)
{
    handlerfor this type
}

If any code in the try block throws an exception class described in the catch clause, then

  • 1) the program will skip the rest of the code in try block.
  • 2) The program execution processor code catch clause.

If the code in try block without throwing an exception, the program will skip the catch clause.

If any code method throws an exception type that is not declared in the catch clause, then this method will immediately quit (hope the caller for this type of abnormal designed catch clause).

To demonstrate exception capture process, is given below a typical program codes read data:

public void read(String filename)
{
    try
    {
        InputStream in = new FileInputStream(filename);
        int b;
        while ((b = in.read()3 != -1 )
        {
            process input
        }
    }
    catch (IOException exception)
    {
        exception.printStackTrace();
    }
} 

Note that, try statements Most of the code is very easy to understand: the byte read and process until the end of file encountered so far. As seen in the Java API as, read method may throw an IOException. In this case, the entire out of the while loop, into the catch clause, and generate a stack trace. For a general procedure, the thus-treated substantially justified exception. There are other options?

In general, the best option is to do nothing but pass the exception to the caller. If the read method an error, let the caller read method to worry about! With this approach, you must declare this method may throw an IOException.

public void read(String filename) throws IOException
{
    inputStream in = new FileinputStream(filename);
    int b;
    while ((b = in.readO) != -1 )
    {
        process input
    }
} 

Remember, the compiler strictly enforced throws specifier. If the method throws a checked exception is invoked, it is necessary to process it, or continue to pass.

Which method is better? Generally, you should capture those who know how to handle exceptions, and those exceptions do not know how to handle the transfer to proceed.

If you want to pass an exception, it must be a throws specifier in the header to add methods to inform the caller of the method might throw an exception.

Carefully read the Java API documentation, in order to know what each method may throw an exception, and then decide whether to deal with their own or added to the throws list. In the latter case, do not hesitate. Directly to the exception processor capable of processing and better handling than its press.

Also keep in mind, there is one exception to this rule. I've already mentioned: If you write a superclass of coverage, but this method has not throw an exception (such as paintComponent JComponent in), then this method must capture every method code appears in checked exception. Exception class superclass method exceeds the range set forth in the allowed subclass throws specifier.

2.2 capture multiple exceptions

In a try block may capture a plurality of types of abnormality, and different types of exception is processed differently. Each exception type can use a separate catch clauses of the following ways:

try {
    code that might throw exceptions
}
catch (FileNotFoundException e) {
    emergency action for missing files
}
catch (UnknownHostException e) {
    emergency action for unknown hosts
}
catch (IOException e) {
    emergency action for allother I/Oproblems
}

The exception object may contain information related to the exception itself. To get more information on objects, you can try to use

e.getHessage()

Get detailed error information (if any), or use

e.getClass().getName()

Get the actual type of the exception object.

In Java SE 7, the same can be captured in a plurality of catch clause exception types. For example, assume that the operation corresponding to the missing files and unknown host exception is the same, can be combined catch clause:

try {
    code that might throw exceptions
}
catch (FileNotFoundException|UnknownHostException e) {
    emergency action for missing filesand unknown hosts
}
catch (IOException e) {
    emergency action for all other I/O problems
} 

When there is no relationship between the type of exception subclasses of each other to capture this feature only when needed.

Note: When capturing multiple exceptions, the implicit exception variable as final variables. For example, it can not be assigned to a different e values ​​in the following clauses body:

catch (FileNotFoundException|UnknownHostException e) {...}

Note: The capture multiple exceptions will not only make your code looks much simpler, but also more efficient. Generating bytecode common block contains only a corresponding catch clause.

2.3 once again thrown the exception chain

2.4 finally clause

When code throws an exception, the remaining processing method is terminated code, and withdraw this method. If the method to get some local resources, and this is the only method he knows, and if these resources must be recovered before exiting the method, it will generate resource recovery issues. One solution is to capture and re-throw all exceptions. However, this solution is relatively boring, because it is necessary to clear the resources allocated in two places. In a normal code; other abnormal code.

Java has a better solution, which is finally clause. The following describes how to properly turn off Java in a file. If you use a database program written in Java, you need to use the same techniques to close the connection to the database. Chapter 4 Ⅱ in volume can be seen in more detail. When an exception occurs, all databases properly close the connection is very important.

Regardless of whether an exception is captured, finally clause of the code is executed. In the following example, the program closes the file in all cases.

InputStream in = new FileInputStream(...); 
try {
    //1
    code that might throwexceptions
    //2
}
catch (IOException e) {
    // 3
    show error message 
    // 4 
}
finally {
    // 5
    in.close();
}
//6

In the above code, there are the following three cases will finally clause:

  • 1) code does not throw an exception. In this case, the program first executes all code in the try block, and then finally clause code. Subsequently, proceed to the first statement after the try block. In other words, the implementation of 1,2,5,6 at the label.

  • 2) thrown in to capture a catch clause. In the above example is an IOException. In this case, the program will execute all the code in the try block, until the abnormality occurs. At this time, skip the rest of the code in the try block, turn to the implementation of the code catch clause matches the exception of the last code in the finally clause. If no catch clause throws an exception, the program will execute the first statement after the try block. Here, the implementation of labeling statements at 1,3,4,5,6. If the catch clause throws an exception, the exception will be thrown back to the caller of this method. Here, the implementation of labeling statements at 1,3,5.
  • 3) code throws an exception, but the exception is not caught by the catch clause. In this case, the program will execute all the statements in the try block, an exception is thrown until far. At this time, skip the rest of the code in the try block, and the finally clauses statement and exception thrown to the caller of this method. Here, the implementation of labeling statements at 1,5.

try statement can only finally clause, but did not catch clause. For example, try following this statement:

InputStream in = ...;
try {
    code that might throw exceptions
}
finally {
    in.close();
} 

Regardless of whether an exception is encountered in the try block, finally clause in.close () statement will be executed. Of course, if it encounters an exception that will be re-thrown and it must be caught by another catch clause.

In fact, we believe in the need to close the resource, use the finally clause in this way is a good choice.

The following detailed explanation will be given tips.

Tip: Here, it is strongly recommended that the solution to engage in co-try / catch and try / finally block. This can improve the clarity of the code. E.g:

InputStrean in = ...;
try {
  try {
      code that might throw exceptions
  }
  finally {
      in.close();
  }
}
catch (IOException e) {
  show error message
}

Inner try block only one duty is to ensure that close the input stream. Outer try block and only one responsibility is to ensure that the error report appears. This design approach not only clear, but also has a function that will report errors appear in the finally clause.

Warning: When the finally clause contains a return statement, there will be an unexpected result, "assume use return statement exits from the try block before the method returns, the contents of the finally clause will be executed if the finally clause. there is also a return statement, the return value will overwrite the original look of the return value of a complex example:

public static int f(int n) {
  try {
      int r = n * n;
      return r;
  }
  finally {
      if (n = 2)
          return 0;
  }
} 

If the call f (2), then the try statement block calculation result is r = 4, and execute a return statement, however, before the method returns true, but also finally clause. finally clause that will return 0 return value return value of the original cover 4.

Sometimes, finally clause will bring trouble. For example, a method to clean up resources might also throw an exception. Suppose you want to ensure the closed flow stream encounters an exception handling code.

InputStreai in = ...;
try {
    code that might throw exceptions
}
finally {
    in.close();
}

Now, suppose the code in the try block throws some non IOException exceptions, these exceptions only this method of callers to be able to be dealt with. Execute the finally block, and call the close method. The clos method itself might also throw an IOException. When this happens, the original exception is lost in favor thrown close approach.

This will be a problem, because the first exception is likely to be more interesting. If you want to do the proper treatment, re-throw the original exception, the code will become extremely cumbersome. As follows:

InputStream in = ...;
Exception ex = null;
try {
    try {
        code that might throw exceptions
    } catch (Exception e) {
        ex=e;
        throw e;
    }
}
finally {
    try {
        in.close();
    } catch (Exception e) {
        if (ex = null)
            throw e;
    }
}

Fortunately, the next section, you will learn to close the resource 7 Java SE process much easier.

Guess you like

Origin www.cnblogs.com/whatsabc/p/11489462.html