Briefly java's exception handling of Try Catch Finally

  • 2020-05-07 19:43:36
  • OfStack

The English word for exception is exception, which literally means "exception, exception," or abnormal situation. In fact, exceptions are essentially errors in the program, including program logic errors and system errors.

1 introduction

java exception handling is familiar to everyone. In general, there are the following two points:

1. Throws an exception :throw exception


class SimpleException{
  public void a() throws Exception{
    throw new Exception();
  };
}

2. Catch exceptions:


public class MyException {
  public static void main(String[] args){
    MyException e = new MyException();
    SimpleException se = new SimpleException();
    try {
      se.a();
    } catch (Exception e1) {
      e1.printStackTrace();
    }
  }
}

class SimpleException{
  public void a() throws Exception{
    throw new Exception();
  };
 } 

On this basis, this paper will discuss some details in more depth.

2 custom exception class

The java language provides us with many exception classes, but sometimes we have to customize them for the convenience of writing code:

class SimpleException extends Exception {};
Once created we can capture it using try catch:


public class MyException {
  public static void main(String[] args){
    MyException e = new MyException();
    try {
      e.a();
    } catch (SimpleException e1) {
      e1.printStackTrace();
    }
  }
  
  public void a() throws SimpleException{
    throw new SimpleException();
  }
}

class SimpleException extends Exception {};

We defined a method a() in MyException to throw an SimpleException exception, then we called the method in main() and caught the exception using try catch:


SimpleException
  at MyException.a(MyException.java:15)
  at MyException.main(MyException.java:8)
  at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
  at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
  at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
  at java.lang.reflect.Method.invoke(Method.java:606)
  at com.intellij.rt.execution.application.AppMain.main(AppMain.java:144)

Process finished with exit code 0


After the compilation of the results, mainly look at the first three lines. Here are some highlights:
1. Exception type specification :(exception specification)
When we need to throw an exception in one method, we will use throw followed by an instance of an exception class, where the program will throw the corresponding exception to the client program (the program that calls this code) and exit (equivalent to return). It is also important to note that we must specify the type of exception when we define the method, for example, the following code will throw an SimpleException exception

public void a() throws SimpleException

2. Throw multiple exceptions:


  public void a() throws SimpleException,AException,BException{
    throw new SimpleException();
    
  }

Separate the different exception classes by commas. In this case, we do not have to throw each instance of the exception class (), but the client code must catch to each exception class:


public class MyException {
  public static void main(String[] args){
    MyException e = new MyException();
    try {
      e.a();
    } catch (SimpleException e1) {
      e1.printStackTrace();
    } catch (BException e1) {
      e1.printStackTrace();
    } catch (AException e1) {
      e1.printStackTrace();
    }
  }

  public void a() throws SimpleException,AException,BException{
    throw new SimpleException();
    
  }
}

class SimpleException extends Exception {};
class AException extends Exception{}
class BException extends Exception{}


3 stack trace

Whether we throw an exception or catch an exception to handle, our goal is to write a more robust program, which relies heavily on the exception information provided by the java exception mechanism, whose carrier is stack trace.
In the previous code, we directly used printStackTrace() to print out the exception information, in fact, we can also use getStackTrace() method to get the collection of StackTraceElement type, if you have IDEA, you can first search out StackTraceElement class, you can find that it implements the interface Serializable, and then look at its class description:


/**
 * An element in a stack trace, as returned by {@link
 * Throwable#getStackTrace()}. Each element represents a single stack frame.
 * All stack frames except for the one at the top of the stack represent
 * a method invocation. The frame at the top of the stack represents the
 * execution point at which the stack trace was generated. Typically,
 * this is the point at which the throwable corresponding to the stack trace
 * was created.
 *
 * @since 1.4
 * @author Josh Bloch
 */

To be clear, each instance of this class is an element of stack trace, representing 1 stack frame, stack trace being returned by the getStackTrace() method. After that, I tried to translate it several times, but I felt it was not good. I had to go directly to the code to make it clear:


public class MyException {
  public static void main(String[] args){
    MyException e = new MyException();
    e.a();

  public void a(){
    try {
      throw new Exception();
    } catch (Exception e) {
      StackTraceElement[] ste = e.getStackTrace();
      System.out.println(ste.length);

    }
  }
}

We define the method a and make it catch it while throwing Exception exception. Then we get an StackTraceElement array by getStackTrace() method and print out the length of the array:

7

Process finished with exit code 0
We changed the code by 1 to not catch exceptions in a, we redefined a method b, let it call a at the same time to catch exceptions:


public class MyException {
  public static void main(String[] args){
    MyException e = new MyException();
    e.b();
  }

  public void b(){
    try {
      a();
    } catch (Exception e) {
      StackTraceElement[] ste = e.getStackTrace();
      System.out.println(ste.length);
    }
  }

  public void a() throws Exception{
    throw new Exception();
  }
}

The results are as follows:

8

Process finished with exit code 0
Don't worry, let's look at something more interesting:


public class MyException {
  public static void main(String[] args){
    MyException exception = new MyException();
    try {
      exception.c();
    } catch (Exception e) {
      StackTraceElement[] ste = e.getStackTrace();
      System.out.println(ste.length);
      System.out.println("---------------------------------------------------------------");
      for (StackTraceElement s : e.getStackTrace()){
        System.out.println(s.getClassName()+":method "+s.getMethodName()+" at line"+s.getLineNumber());
      }
      System.out.println("---------------------------------------------------------------");

    }

  }

 public void c() throws Exception{
    try {
      a();
    }catch (Exception e){
      throw e;
    }
  }

  public void a() throws Exception{
    throw new Exception();
  }
}

Here are the results:


public class MyException {
  public static void main(String[] args){
    MyException e = new MyException();
    SimpleException se = new SimpleException();
    try {
      se.a();
    } catch (Exception e1) {
      e1.printStackTrace();
    }
  }
}

class SimpleException{
  public void a() throws Exception{
    throw new Exception();
  };
 } 

0

That is to say, getStackTrace () returns a stack, it contains from the caller (main ()) to the original throw was abnormal (a ()) of 1, some basic information in the above code, we call a method in c method when catch exceptions and through throws it again thrown (rethrow), the method call c method can capture and handle exceptions, can also choose to continue to enticement of a higher level of the caller (near the bottom of the stack). While rethrow is very convenient, it has some problems. Let's look at the following code:


public class MyException {
  public static void main(String[] args){
    MyException e = new MyException();
    SimpleException se = new SimpleException();
    try {
      se.a();
    } catch (Exception e1) {
      e1.printStackTrace();
    }
  }
}

class SimpleException{
  public void a() throws Exception{
    throw new Exception();
  };
 } 

1

We rethrow e in c, and print e.printStackTrace () in main, and you can see that stack trace still belongs to a. If we want to change stack trace to c, we can say:


public class MyException {
  public static void main(String[] args){
    MyException e = new MyException();
    SimpleException se = new SimpleException();
    try {
      se.a();
    } catch (Exception e1) {
      e1.printStackTrace();
    }
  }
}

class SimpleException{
  public void a() throws Exception{
    throw new Exception();
  };
 } 

2

4 exception chain Exception chaining

Let's start with a scenario:


public class TestException {
  public static void main(String[] args){
    TestException testException = new TestException();
    try {
      testException.c();
    } catch (CException e) {
      e.printStackTrace();
    }
  }

  public void a() throws AException{
    AException aException = new AException("this is a exception");
    throw aException;
  }

  public void b() throws BException{
    try {
      a();
    } catch (AException e) {
      throw new BException("this is b exception");
    }
  }

  public void c() throws CException{
    try {
      b();
    } catch (BException e) {
      throw new CException("this is c exception");
    }
  }
}

class AException extends Exception{
  public AException(String msg){
    super(msg);
  }
}

class BException extends Exception{
  public BException(String msg){
    super(msg);
  }
}

class CException extends Exception{
  public CException(String msg){
    super(msg);
  }
}

Three exception classes AException, BException, CException are created, AException is thrown in a(), AException is caught in b() and BException is thrown, BException is caught in c() and CException is thrown, the result is printed as follows:


public class MyException {
  public static void main(String[] args){
    MyException e = new MyException();
    SimpleException se = new SimpleException();
    try {
      se.a();
    } catch (Exception e1) {
      e1.printStackTrace();
    }
  }
}

class SimpleException{
  public void a() throws Exception{
    throw new Exception();
  };
 } 

4

Ok, we only see the CException information, AException, BException exception information has been lost, then the exception chain function is out, look at the code:


public class MyException {
  public static void main(String[] args){
    MyException e = new MyException();
    SimpleException se = new SimpleException();
    try {
      se.a();
    } catch (Exception e1) {
      e1.printStackTrace();
    }
  }
}

class SimpleException{
  public void a() throws Exception{
    throw new Exception();
  };
 } 

5

We used initCause() method to concatenate the abnormal information, and the result is as follows:


public class MyException {
  public static void main(String[] args){
    MyException e = new MyException();
    SimpleException se = new SimpleException();
    try {
      se.a();
    } catch (Exception e1) {
      e1.printStackTrace();
    }
  }
}

class SimpleException{
  public void a() throws Exception{
    throw new Exception();
  };
 } 

6

5 afterword.

In fact, there is still a lot to discuss about java exception handling, but due to my limited experience, I can't understand it too deeply


public class MyException {
  public static void main(String[] args){
    MyException e = new MyException();
    SimpleException se = new SimpleException();
    try {
      se.a();
    } catch (Exception e1) {
      e1.printStackTrace();
    }
  }
}

class SimpleException{
  public void a() throws Exception{
    throw new Exception();
  };
 } 

7

But anyway we can thank java for providing us with the exception mechanism, which is like an elder, guiding us the way from time to time, and making us less bored when coding :)


Related articles: