corejava11 (7.2 catch the exception)

7.2 catch the exception

You now know how to throw an exception of. It's easy: you throw forget. Of course, some code must catch the exception. Catch exceptions require more planning. This is the next section of the discussion.

7.2.1 catch an exception

If no exception is caught anywhere, the program will terminate and print a message Console, given the type of exception and stack trace. The GUI program (applets and applications) to catch exceptions, the print stack trace message and returns the user interface processing cycle. (Debugging GUI program, the console is best to remain on the screen, rather than minimized.)

To catch the exception, set a try/catchblock. tryThe simplest form of a block as follows:

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

If tryany code block throws catchexception clause specifies the class, then

  1. Skip the tryrest of the code block.
  2. Program execution catchclause handler code.

If the tryblock is no code throws an exception, then the program will skip catchclause.

If any code method caused catchan exception clause other than the specified type, this method exits immediately. (I hope it's a caller has been provided for this type of catchclause.)

To demonstrate this at work, here are some very typical data read the code:

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

Please note that tryclause Most of the code is very simple: it reads and processes bytes, until the end of file is encountered. As can be seen from the Java API, the readmethod may throw a IOException. In this case, we skip the entire whilecycle, input catchclause, and generates stack trace. For a toy program, it seems to be a reasonable way to handle this exception. You have a choice?

In general, the best option is to do nothing, just pass the exception to the caller. If readan error method, so that readmethod callers worried about it! If we adopt this approach, then we have to announce the fact that the method may throw IOException.

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

Remember, the compiler strictly enforces throwsspecifier. If you call a method that throws a checked exception, you must deal with it or pass it.

Which one is better? As a general rule, you should capture those you know how to handle exceptions, and the spread of those you do not know how to handle exceptions.

When the spread of exceptions, you must add the throwsspecifier to alert the caller may cause an exception.

View Java API documentation to see what method which exceptions thrown. And then decide whether to process them or add them to throwsthe list. The latter option there is nothing embarrassing. Preferably the exception of the ability to be directed to a handler, rather than to suppress it.

Remember, as we mentioned earlier, there is one exception to this rule. If the method of writing rewrite the superclass method (if not throw an exception JComponentin paintComponent), you must capture each selected exceptions in the code method. Not allowed to add more than the superclass method subclass method throwsspecifier.

C ++ Note

Catch exceptions in Java and C ++ are almost identical. Strictly speaking, analogy

catch (Exception e) // Java

Yes

catch (Exception& e) // C++

No analogy in C ++ catch (...) a. In Java need not do so, because all exceptions from a common superclass.

7.2.2 capture multiple exceptions

In one You can trycapture a plurality of blocks exception type, and each type processed in different ways. Use for each individual type catchclause, in the following example:

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 all other I/O problems
}

The exception object may contain information about the nature of the anomaly. To learn more about the object, try

e.getMessage()

Get a detailed error message (if any), or

e.getClass().getName()

Obtain the actual type of the exception object.

As for Java 7, the same you can catchcapture multiple types of exceptions clause. For example, the same operation is assumed that the missing files and unknown host. Then you can combine catchclause:

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

Not only belong to a subclass exception types need each other to capture this function only when.

note

When capturing a plurality of abnormality, the abnormality of the variable implicitly final. For example, in a clause of the body is not especify different values.

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

note

Capture multiple exceptions not only make the code look more simple and more efficient. Generating shared bytecode comprising catcha single block clause.

7.2.3 retransmission and abnormal link

You can catchthrow an exception clause. In general, when you want to change the type of exception, you can do so. If you build a subsystem other programmers to use, then use a represents an abnormal type of subsystem failure is significant. An example of this type of exception is ServletException. Execute servlet code may not want to know in detail what's wrong, but it certainly would like to know servlet problem.

The following is a method to catch the exception and re-throw the exception:

try
{
    access the database
}
catch (SQLException e)
{
    throw new ServletException("database error: " + e.getMessage());
}

Here, ServletExceptiona message configured with text abnormality.

However, the best original exception to "the cause" of a new exception:

try
{
    access the database
}
catch (SQLException original)
{
    var e = new ServletException("database error");
    e.initCause(original);
    throw e;
}

When catching exceptions, you can retrieve the original exception:

Throwable original = caughtException.getCause();

Strongly recommended the use of this packaging technology. It allows you to throw an exception in advanced subsystems without losing details of the original failure.

prompt

If the check occurs in the method does not allow throw checked exceptions in unusual, packaging technology is also useful. You can capture selected abnormal and abnormal is packaged runtime.

Sometimes you just want to record an exception, and re-execute it without making any changes:

try
{
    access the database
}
catch (Exception e)
{
    logger.log(level, message, e);
    throw e;
}

Before Java 7, there is problem with this approach. Suppose a process code

public void updateRecord() throws SQLException

Java compiler see catchin the block throwstatement, and then view etype, and complained that the method may throw any Exception, not just SQLException. Now the situation has improved. The compiler now tracking estems from trythe fact that the block. If the selected block is the only exceptions are SqlExceptionexamples, and catchdo not change the block e, then closing declared method throws SQLExceptionis effective.

7.2.4 fianllyclause

When the code throws an exception, it will stop code processing method and exit the remaining method. If the method had some local resources (This is the only way to know), and the resource must be removed, then this is a problem. One solution is to catch all exceptions, cleanup, and then re-throw an exception. But this solution is lengthy because you need two position in the normal code and exception code cleanup resource allocation. finallyClause can solve this problem.

note

Since the Java 7, there is a more elegant solution, that is seen in the following sections try-with-resourcesstatement. Because it is the conceptual basis, we discussed in detail finallythe mechanism. In practice, however, than you may finallyuse more frequently clause try-with-resourcestatement.

Whether or not catch the exception finallyclause of the code will be executed. In the following example, the input stream will close in all cases:

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

Let's look at the program will execute finallythree kinds clause possibilities.

  1. Code does not throw an exception. In this case, the program first executes tryall the code blocks. Then, it performs finallyclause code. After that, the execution will proceed to finallythe first statement after the clause. In other words, 2, 5 and 6 is performed by point.
  2. In our example, the code throws an catchabnormal clause captured, that is IOException. To this end, the program execution tryof all code blocks until it raises an exception so far. We will skip trythe rest of the code block. Then, the program performs the matching catchcodes clause, and then execute finallythe code clause.
    If the catchclause does not throw an exception, then the program will execute finallythe first line after clause. In this scenario, the execution by point 1,3,4,5 and 6.
    If the catchclause throws an exception, the exception will be thrown back to the caller of this method, and performed only by points 1, 3 and 5.
  3. Code led to a not at all catchan exception clause capture. Here, the program execution tryof all code blocks, until the exception is thrown up. We will skip trythe rest of the code block. Then, execute finallythe code clause, abnormal and returned to the caller of the method. Performed only by the points 1 and 5.

You can use the finallyclause without using the catchclause. For example, consider the following trystatement:

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

Regardless of trywhether an exception is encountered block, finallyclause in.close()statement will be executed. Of course, if an exception is encountered, it will be re-initiated, and must be in another catchcapture clause.

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

Internal tryblock only one responsibility: to ensure that the input stream has been closed. External tryblock only one responsibility: to ensure that reports an error. This solution is not only a clearer and more practical: report finallyclause error.

Be careful

finallyClause contains returnmay produce unexpected results statement. Assuming returnstatement exits the tryintermediate block. Before the method returns, the execution finallyblock. If the finallyblock also contains a returnstatement, it will return the original mask value. Consider this example:

public static int parseInt(String s)
{
    try
    {
        return Integer.parseInt(s);
    }
    finally
    {
        return 0; // ERROR
    }
}

In the call parseInt("42"), the trybody 42 returns the integer block appears. However, the finallyclause is executed before the method actually returns, and lead method returns 0, ignore the original return value.

What's worse is. Consider calling parseInt("zero"). Integer.parseIntIt sparked a method NumberFormatException. Then execution finallyclause, returnthe statement will swallow an exception!

finallyThe main clause used to clean up resources. Do not finallychange the control flow return(clause into the throw, break, , continue) statement.

7.2.5 try-with-resourceStatement

For Java 7, the code for the model has a useful shortcuts.

open a resource
try
{
    work with the resource
}
finally
{
    close the resource
}

If the resource is an implementation AutoClosableclass interface. That interface has a single method

void close() throws Exception

note

Another Closeableinterface. It is a AutoCloseablesub-interface, there is also a closemethod. However, this method statement for the initiation IOException.

In its simplest variant, try-with-resourcesin the form of statements

try (Resource res = . . .)
{
    work with res
}

When the trytime block exits, will automatically call res.close(). Here is a typical example of a file read all the words:

try (var in = new Scanner(
    new FileInputStream("/usr/share/dict/words"), StandardCharsets.UTF_8))
{
    while (in.hasNext())
           System.out.println(in.next());
}

When the block is normal or abnormal exit, call in.close()methods, like the use of finallyblock same.

You can specify multiple resources. E.g,

try (var in = new Scanner(
    new FileInputStream("/usr/share/dict/words"), StandardCharsets
    var out = new PrintWriter("out.txt", StandardCharsets.UTF_8))
{
    while (in.hasNext())
        out.println(in.next().toUpperCase());
}

No matter how this block of code to go in and out are closed. If manual programming, then two nested try / finally statement.

For Java 9, can tryprovide an effective final variable previously declared head:

public static void printAll(String[] lines, PrintWriter out)
{
    try (out) { // effectively final variable
        for (String line : lines)
        out.println(line);
    } // out.close() called here
}

When the tryblock throws an exception, closewhen the method also throws an exception, a difficulty will arise. try-with-resourcesStatement handle this situation very elegant. Original exception is re-initiation closemethod throws any exceptions are considered "suppression." They will automatically capture and use the addSuppressedmethod to the original exception. If you are interested in them, please call the getSuppressedmethod from closegenerating a suppressed expression array method.

You do not want manual programming. Whenever you need to close the resource, use try-with-resourcesstatement.

note

try-with-resourcesStatement itself may have a catchclause even finallyclause. These are performed after the close of resources.

7.2.6 Analysis of stack trace elements

The stack trace is a list of program execution at a specific point of all pending method calls. You will almost certainly see a stack trace list, whenever the Java program ends, they will appear as an exception is not cleared.

By calling the Throwableclass printStackTracemethod, you can access a text description of the stack trace.

var t = new Throwable();
var out = new StringWriter();
t.printStackTrace(new PrintWriter(out));
String description = out.toString();

The method is more flexible StackWalkertype, it generates StackWalker.StackFrameinstances stream, each instance describes a stack frame. You can use this iterative call stack frame:

StackWalker walker = StackWalker.getInstance();
walker.forEach(frame -> analyze frame)

To handle an inert Stream <StackWalker.StackFrame>, call

walker.walk(stream -> process stream)

The second volume of the first stream processing section details.

StackWalker.StackFrameThe method of retrieval is performed with the class file name and line number of the line code and the object class and method names. toStringThe method of generating a formatted string contains all this information.

note

Before Java 9, Throwable.getStackTracea method of producing an StackTraceElement[]array, it StasWalk.StackFramehas a similar example of the information flow. However, the call is low efficiency, because it captures the entire stack, even if the calling party may only need a few frames, and is available only to the class name pending method (rather than class objects) access.

Print Listing 7.1 stack recursive factorial function is tracking. For example, if the calculation factorial(3), the print output is

factorial(3):
stackTrace.StackTraceTest.factorial(StackTraceTest.java:20)
stackTrace.StackTraceTest.main(StackTraceTest.java:36)
factorial(2):
stackTrace.StackTraceTest.factorial(StackTraceTest.java:20)
stackTrace.StackTraceTest.factorial(StackTraceTest.java:26)
stackTrace.StackTraceTest.main(StackTraceTest.java:36)
factorial(1):
stackTrace.StackTraceTest.factorial(StackTraceTest.java:20)
stackTrace.StackTraceTest.factorial(StackTraceTest.java:26)
stackTrace.StackTraceTest.factorial(StackTraceTest.java:26)
stackTrace.StackTraceTest.main(StackTraceTest.java:36)
return 1
return 2
return 6

清单7.1 stackTrace/StackTraceTest.java

package stackTrace;
 
import java.util.*;
 
/**
* A program that displays a trace feature of a recursive method call.
* @version 1.10 2017-12-14
* @author Cay Horstmann
*/
public class StackTraceTest
{
   /**
    * Computes the factorial of a number
    * @param n a non-negative integer
    * @return n! = 1 * 2 * . . . * n
    */
   public static int factorial(int n)
   {
      System.out.println("factorial(" + n + "):");
      var walker = StackWalker.getInstance();
      walker.forEach(System.out::println);  
      int r;
      if (n <= 1) r = 1;
      else r = n * factorial(n - 1);
      System.out.println("return " + r);
      return r;
   }
 
   public static void main(String[] args)
   {
      try (var in = new Scanner(System.in))
      {
         System.out.print("Enter n: ");
         int n = in.nextInt();
         factorial(n);
      }
   }
}

java.lang.Trhowable 1.0

  • Throwable(Throwable cause) 1.4
  • Throwable(String message, Throwable cause)1.4
    with the given reason Throwable.
  • Throwable initCause(Throwable cause)1.4
    reasons for setting this object, there are reasons for this object if an exception is thrown. Return this.
  • Throwable getCause()1.4
    gets set for this object exception object cause, if the cause is not set, it was null.
  • StackTraceElement[] getStackTrace()1.4
    get the call stack when constructing this object tracking.
  • void addSuppressed(Throwable t)7
    The "suppression" exception to this exception. This occurs in the try-with-resourcesstatement, which tis the closemethod was thrown.
  • Throwable[] getSuppressed()7
    get this exception "to suppress" all exceptions. Typically, these exceptions are generated by try-with-resourcesinitiation of the close method statement.

java.lang.Exception 1.0

  • Exception(Throwable cause) 1.4
  • Exception(String message, Throwable cause)
    With the given reason Exception.

java.lang.RuntimeException 1.0

  • RuntimeException(Throwable cause) 1.4
  • RuntimeException(String message, Throwable cause)1.4
    with the given reason RuntimeException.

java.lang.StackWalker 9

  • static StackWalker getInstance()
  • static StackWalker getInstance(StackWalker.Option option)
  • static StackWalker getInstance(Set<StackWalker.Option> options)
    Gets StackWalkerinstance. Options include StackWalker.Optionenumeration RETAIN_CLASS_REFERENCE, SHOW_HIDDEN_FRAMESand SHOW_REFLECT_FRAMES.
  • forEach(Consumer<? super StackWalker.StackFrame> action)
  • walk(Function<? super Stream<StackWalker.StackFrame>,? extends T> function)
    Given function is applied to the stack frame of the stream function and returns the result.

java.lang.StackWalker.StackFrame 9

  • String getFileName()
    Gets the name of the source file containing the execution point of this element, if the information is not available, it was null.
  • int getLineNumber()
    Acquisition source file containing this element execution point line number, if the information is not available, or -1.
  • String getClassName()
    The method of obtaining the fully qualified name which contains this element performs the point class.
  • String getDeclaringClass()
    The method of obtaining this element containing the execution point of the class object. If the stack walk is not a RETAIN_CLASS_REFERENCEoption structure, an exception is thrown.
  • String getMethodName()
    Get the name of containing the execution point of this element method. The name of the constructor is <init>. Static initializer name is <clinit>. Overloaded methods can not distinguish between the same name.
  • boolean isNativeMethod()
    If the execution point of this element is located within the native method returns true.
  • String toString()
    Returns a formatted string that contains the class and method names, the file name and line number (if available).

java.lang.StackTraceElement 1.4

  • String getFileName()
    Gets the name of the source file containing the execution point of this element, if the information is not available, it was null.

  • int getLineNumber()
    Acquisition source file containing this element execution point line number, if the information is not available, or -1.

  • String getClassName()
    Obtain the fully qualified class name contains this element performs point.

  • String getMethodName()
    Get the name of containing the execution point of this element method. The name of the constructor is <init>. Static initializer name is <clinit>. Overloaded methods can not distinguish between the same name.

  • boolean isNativeMethod()

    If the execution point of this element is located within the native method, it returns true.

  • String toString()
    Returns a formatted string that contains the class and method names, the file name and line number (if available).

Guess you like

Origin blog.csdn.net/nbda1121440/article/details/91496560