Exception handling usage in Java and its architecture and usage recommendations _java

Source: Internet
Author: User
Tags exception handling finally block getmessage int size stack trace throwable concurrentmodificationexception

Java exceptions are a consistent mechanism provided by Java for identifying and responding to errors.
The Java exception mechanism separates the exception handling code and normal business code in the program, guarantees the program code to be more graceful, and enhances the program robustness. In the case of effective use of exceptions, the exception can clearly answer what, where, why these 3 questions: The exception type answered "What" was thrown, the exception stack trace answered "where" thrown, the exception information answered "Why" will be thrown.
The Java exception mechanism uses several keywords: try, catch, finally, throw, throws.

Key Words Description
Try For listening. The code that will be listening (the code that may throw an exception) is placed within a try statement block, and the exception is thrown when an exception occurs within a try statement block.
Catch Used to catch exceptions. Catch is used to catch exceptions that occur in a try statement block.
Finally Finally statement blocks are always executed. It is primarily used to reclaim material resources (such as database connections, network connections, and disk files) that are opened in a try block. Only a finally block, after execution completes, returns or throw statements in a try or catch block, and if finally a statement with a return or throw method is used, the execution is not skipped and stopped directly.
Throw Used to throw an exception.
Throws Used in a method signature to declare an exception that the method might throw.

Here are a few examples of these keywords to understand briefly.
Example one: Understanding the basic usage of try and catch

public class Demo1 {public

 static void Main (string[] args) {
  try {
   int i = 10/0;
    System.out.println ("i=" +i); 
  } catch (ArithmeticException e) {
    System.out.println ("Caught Exception"); 
   System.out.println ("E.getmessage ():" + e.getmessage ()); 
   System.out.println ("e.tostring ():" + e.tostring ()); 
   System.out.println ("E.printstacktrace ():");
   E.printstacktrace ();}}


Run Result:

Caught Exception
e.getmessage ():/by Zero
e.tostring (): java.lang.ArithmeticException:/by Zero
E.printstacktrace ():
java.lang.ArithmeticException:/by zero at
 Demo1.main (demo1.java:6)

Result: An operation with a divisor of 0 in the try statement block, which throws a Java.lang.ArithmeticException exception. The exception is caught by a catch.
Observation results we found that there was no implementation of SYSTEM.OUT.PRINTLN ("i=" +i). This means that the remainder of the try statement block is no longer executed after an exception is made to the try statement block.
Example Two: Understanding the basic usage of finally
on the basis of "example one," we add a finally statement.

public class Demo2 {public

 static void Main (string[] args) {
  try {
   int i = 10/0;
    System.out.println ("i=" +i); 
  } catch (ArithmeticException e) {
    System.out.println ("Caught Exception"); 
   System.out.println ("E.getmessage ():" + e.getmessage ()); 
   System.out.println ("e.tostring ():" + e.tostring ()); 
   System.out.println ("E.printstacktrace ():");
   E.printstacktrace (); 
  } finally {
   System.out.println ("Run Finally");}}


Run Result:

Caught Exception
e.getmessage ():/by Zero
e.tostring (): java.lang.ArithmeticException:/by Zero
E.printstacktrace ():
java.lang.ArithmeticException:/by zero at
 Demo2.main (demo2.java:6)
Run finally

Result: Finally, a finally statement block is executed.
example Three: Understanding the basic usage of throws and throw
throws is used to declare an exception thrown, and throw is used to throw an exception.

Class MyException extends Exception {public
 myexception () {} public
 myexception (String msg) {
  Super (msg );
 }
}

public class Demo3 {public

 static void Main (string[] args) {
  try {
   test ();
  } catch (MyException e) { C20/>system.out.println ("Catch my Exception");
   E.printstacktrace ();
  }
 public static void Test () throws myexception{
  try {
   int i = 10/0;
    System.out.println ("i=" +i); 
  } catch (ArithmeticException e) {
   throw new MyException ("This is MyException");}}


Run Result:

Catch my Exception
myexception:this are myexception at
 demo3.test (demo3.java:24) at
 Demo3.main (Demo3.java : 13)

The results show that MyException is a subclass of exception inherited from the class. The arithmeticexception exception (divisor 0) is generated in the TRY statement block of test (), and the exception is caught in the catch, then the MyException exception is thrown. The main () method captures the myexception thrown in test ().


Java Exception framework
Java exception schema diagram:

1. Throwable
Throwable is a superclass of all errors or exceptions in the Java language.
Throwable contains two subclasses: Error and Exception. They are typically used to indicate that an exception has occurred.
Throwable contains a snapshot of the thread execution stack when its thread was created, and it provides interfaces such as Printstacktrace () for obtaining information such as stack trace data.

2. Exception
exception and its subclasses are a form of throwable that indicates the conditions that a reasonable application wants to capture.

3. RuntimeException
RuntimeException are superclass of exceptions that may be thrown during the normal operation of a Java virtual machine.
The compiler does not check for runtimeexception exceptions. For example, a ArithmeticException exception is thrown when the divisor is zero. RuntimeException is a arithmeticexception of the Super class. When the code has zero divisor, if both "did not throw through the throws declaration ArithmeticException exception", also "did not pass the Try...catch ..." Handle the exception, or it can be compiled. This is what we call "The compiler does not check for runtimeexception exceptions"!
If the code produces a RuntimeException exception, it needs to be avoided by modifying the code. For example, if a divisor is zero, you need to avoid it by code!

4. Error
As with exception, error is also a throwable subclass. It is used to indicate a serious problem that reasonable applications should not attempt to capture, most of which are exceptional conditions.
As with RuntimeException, the compiler does not check for error.
Java divides the throwable structure into three types: checked exceptions (Checked Exception), run-time exceptions (runtimeexception), and Errors (error).

(1) Run-time exception
definition: RuntimeException and its subclasses are called Run-time exceptions.
Feature: The Java compiler does not check it. That is, when such an exception can occur in a program, it is "not caught with a throws declaration", or "it is not captured with a try-catch statement", or it is compiled. For example, the arithmeticexception exception that occurs when the divisor is zero, the indexoutofboundsexception exception that occurs when the array crosses bounds, The fail-fail mechanism produces concurrentmodificationexception exceptions, all of which belong to Run-time exceptions.
Although the Java compiler does not check for Run-time exceptions, we can also throw them through throws, or we can capture them through Try-catch.
If a Run-time exception is generated, it needs to be avoided by modifying the code. For example, if a divisor is zero, you need to avoid it by code!

(2) Checked exceptions
Definition: The exception class itself, as well as subclasses of exception except "Run-time exceptions", belong to the checked exception.
Feature: the Java compiler checks it. This type of exception is either thrown through a throws declaration or captured by Try-catch, otherwise it cannot be compiled. For example, Clonenotsupportedexception belongs to a checked exception. When an object is cloned through the clone () interface, and the corresponding class of the object does not implement the Cloneable interface, a Clonenotsupportedexception exception is thrown.
Checked exceptions are usually recoverable.

(3) Error
Definition: The error class and its subclasses.
Features: As with run-time exceptions, the compiler does not check for errors.
An error occurs when resources are insufficient, constraints fail, or other programs cannot continue to run. The program itself cannot fix these errors. For example, Virtualmachineerror is an error.
According to the Java Convention, we are not supposed to be implementing any new error subclasses!
For the 3 structures above, which one is it when we throw an exception or an error? The advice given in effective Java is to use a checked exception for a condition that can be recovered, and a Run-time exception for a program error.

Several suggestions on exception handling

Rule 1th: Use exceptions only for abnormal conditions
Recommendation: Exceptions should be used only for abnormal conditions that should never be used for normal flow of control.
This is illustrated by comparing the following two codes.
Code 1

try {
 int i=0;
 while (true) {
  arr[i]=0;
  i++
 }
} catch (Indexoutofboundsexception e) {
}
code 2 for
(int i=0; i<arr.length; i++) {
 arr[i]=0;
}

The

Two code works by traversing the ARR array and setting the value of each element in the array to 0. Code 1 is terminated by an exception, which seems very difficult to understand, and code 2 is terminated by an array boundary. There are three main reasons why we should avoid using code 1:
The exception mechanism was designed to be used in abnormal situations, so the JVM implementations rarely attempt to optimize their performance. Therefore, the overhead of creating, throwing, and catching exceptions is expensive. The
putting code in Try-catch returns to prevent some specific optimizations that the JVM implementation might otherwise have performed. The standard pattern of
traversal of arrays does not result in redundant checks, and some modern JVM implementations optimize them.
In fact, an exception based pattern is much slower than standard mode. The test code is as follows:

public class Advice1 {private static int[] arr = new int[]{1,2,3,4,5};

 private static int SIZE = 10000;
  public static void Main (string[] args) {Long S1 = System.currenttimemillis ();
  for (int i=0; i<size; i++) Endbyrange (arr);
  Long e1 = System.currenttimemillis ();

  System.out.println ("Endbyrange Time:" + (E1-S1) + "MS");
  Long s2 = System.currenttimemillis ();
  for (int i=0; i<size; i++) endbyexception (arr);
  Long e2 = System.currenttimemillis ();
 System.out.println ("Endbyexception Time:" + (E2-S2) + "MS");
   }//Traversal arr array: private static void Endbyexception (Int[] arr via exception) {try {int i=0;
    while (true) {arr[i]=0;
    i++;
   System.out.println ("endbyrange:arr[" +i+ "]=" +arr[i)); } catch (Indexoutofboundsexception e) {}}//Traverse arr array: private static void Endbyrange (int[] arr) by boundary
   R (int i=0; i<arr.length; i++) {arr[i]=0;
  System.out.println ("endbyexception:arr[" +i+ "]=" +arr[i));

 }
 }
}

Run Result:

Endbyrange time:8ms
endbyexception time:16ms

The results show that the rate of traversal through the exception is much slower than the normal way of traversing the array!

2nd: Use a checked exception for a recoverable condition, use a Run-time exception for program errors

Abnormal Description
Run-time exceptions The RuntimeException class and its subclasses are called Run-time exceptions.
The exception that was checked The exception class itself, as well as subclasses of exception except "Run-time exceptions", belong to the checked exception

The difference is that the Java compiler checks for "checked exceptions" and does not check for "run-time exceptions."
That is, for the exception being checked, it is either thrown through a throws declaration or captured by Try-catch, otherwise it cannot be compiled. In the case of a run-time exception, if it is "not thrown through the throws declaration", it is "not captured with the Try-catch statement", or it compiles. Of course, although the Java compiler does not check for Run-time exceptions, we can also describe the exception through throws, or capture it through Try-catch.
Rithmeticexception (for example, a divisor of 0), indexoutofboundsexception (for example, array bounds), etc. belong to run-time exceptions. For this exception, we should avoid it by modifying the code. For exceptions that are checked, you can get the program back to run by processing. For example, suppose that a user does not store enough of the front, so he fails to make a call on a pay phone, and then throws a checked exception.

Rule 3rd: Avoid unnecessary use of the checked exceptions
"Checked exceptions" is a good feature of the Java language. Unlike the return code, "checked exceptions" force programmers to deal with exceptional conditions, greatly improving the reliability of the program.
However, excessive use of checked exceptions makes the API very inconvenient to use. If a method throws one or more checked exceptions, the code that calls the method must handle the exceptions in one or more catch statement blocks, or it must throw the exceptions through the throws declaration. Whether by catch-handling or by throws declarations, the programmer adds a burden that cannot be ignored.
Applied to "checked exceptions" must meet two conditions: first, even if the API is used correctly, it does not prevent exception conditions from occurring. Second, once an exception is generated, programmers using the API can take useful actions to process the program.

4th: Try to use standard exceptions
code reuse is worth advocating, and this is a common rule, and exceptions are no exception. There are several benefits to reusing existing exceptions:
First, it makes your API easier to learn and use, because it's consistent with the idioms that programmers used to know.
Second, for programs that use these APIs, they are much more readable because they are not flooded with exceptions that are unfamiliar to programmers.
Third, the fewer the exception classes, the smaller the memory footprint, and the less time it takes to reprint these classes.
Several of the Java standard Exceptions are exceptions that are frequently used. The following table:

Abnormal Use occasion
IllegalArgumentException The value of the parameter is not appropriate
IllegalStateException The state of the parameter is not appropriate
NullPointerException Parameter value is NULL when NULL is prohibited
Indexoutofboundsexception Subscript out of Bounds
Concurrentmodificationexception Object detects concurrent modifications when concurrent modifications are prohibited
Unsupportedoperationexception Methods that the object does not support client requests

Although they are the most frequently reused exceptions to date in the Java Platform Library, other exceptions can be reused under permissive conditions. For example, if you want to implement an arithmetic object such as a complex number or a matrix, then reusing ArithmeticException and numberformatexception will be very appropriate. If an exception satisfies your needs, do not hesitate to use it, but you must make sure that the condition that throws the exception is the same as the condition described in the document for the exception. This reuse must be based on semantics, not on the basis of names!
Finally, it's important to be clear that choosing which exception to reuse has no rules to follow. For example, consider the case of a card object, assuming that there is a method for the licensing operation, and that its argument (handsize) is the number of cards that are issued with a single hand. Suppose the value passed by the caller in this argument is greater than the number of remaining sheets for the entire deck. This situation can be interpreted either as illegalargumentexception (the value of handsize is too large) or as illegalstateexception (too few cards are available relative to the customer's request).

5th: The thrown exception should be appropriate for the corresponding abstract
This situation can be confusing if the exception thrown by a method has no obvious association with the task it performs. This often occurs when a method passes an exception that is thrown by a low-level abstraction. When this happens, it is not only confusing, but also "polluting" the high-level API.
To avoid this problem, high-level implementations should capture low-level exceptions while throwing an exception that can be described in high-level abstractions. This practice is referred to as "anomalous translation (Exception translation)".
For example, the Get () method Abstractsequentiallist in the Java Collection framework is as follows (based on jdk1.7.0_40):

Public E get (int index) {
 try {return
  listiterator (index). Next ();
 \ catch (nosuchelementexception exc) {
   throw new Indexoutofboundsexception ("Index:" +index);
 }

Listiterator (Index) returns the Listiterator object, and calling the next () method of the object may throw a Nosuchelementexception exception. In the Get () method, throwing a nosuchelementexception exception can be confusing. So, get () captures the nosuchelementexception and throws a Indexoutofboundsexception exception. That is, the equivalent of translating nosuchelementexception into a indexoutofboundsexception exception.

6th: Each method throws the exception must have the document
to declare an exception that is checked separately, and to use the @throws tag of Javadoc, accurately record the conditions under which each exception is thrown.
If many of the methods in a class throw the same exception for the same reason, it is acceptable to document the exception in the documentation comments for that class, rather than to document each method separately.

7th: Include failure in the detail message--capture message
in short, when we customize an exception or throw an exception, we should include information about the failure.
When a program fails due to an exception that has not been caught, the system automatically prints out the stack trajectory of the exception. A string representation that contains the exception in the stack trajectory. Typically, it contains the class name of the exception class, along with the detail message immediately following it.

8th: Efforts to keep the failure of atomic
when an object throws an exception, we always expect the object to remain in a well-defined, usable state. This is especially important for checked exceptions, because the caller usually expects to recover from the checked exception.
In general, a failed method call should keep the object in the state before it was called. Methods with this property are referred to as having "failed atomicity (failure atomic)". It can be understood that failure also remains atomic. There are several ways in which objects remain "failed atomicity":
(1) Design a Non-volatile object.
(2) The most common way to obtain "failed atomicity" for methods that perform operations on a Mutable object is to check the validity of the parameters before performing the operation. as follows (pop method in Stack.java):

Public Object pop () {
 if (size==0)
  throw new Emptystackexception ();
 Object result = Elements[--size];
 Elements[size] = null;
 return result;
}

(3) Similar to the previous method, you can adjust the order of the calculation process so that any part of the calculation that may fail occurs before the object state is modified.
(4) Write a recovery code to explain the failures that occurred during the operation and to roll the object back to the state before the operation started.
(5) Perform an operation on a temporary copy of the object, and then copy the results from the temporary copy to the original object when the operation is completed.
While "keeping the object's failure atomicity" is the desired goal, it is not always possible to do so. For example, if multiple threads attempt to access an object concurrently without an appropriate synchronization mechanism, the object may be left in an inconsistent state.
It is not always expected, even in situations where "failure atomicity" can be achieved. For some operations, it can significantly increase overhead or complexity.
The general rule is that, as part of the method specification, any exception should not change the state before the object invokes the method, and if the rule is violated, the API document should clearly indicate what state the object will be in.

Rule 9th: Do not ignore exceptions
when the designer of an API declares that a method throws an exception, they are trying to explain something. So, please don't ignore it! The code to ignore the exception is as follows:

try {
 ...
} catch (Someexception e) {
}

An empty catch block makes an exception less than it should, and the exception is to force you to deal with an abnormal condition. Ignoring an exception is like ignoring a fire signal-if the fire alarm is closed, no one will see the fire signal when the real fire occurs. Therefore, at least the catch block should contain a description to explain why it is appropriate to ignore this exception.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.