Handling errors with exceptions
Exception: A problem that prevents the current method or scope from continuing to execute.
Monitoring area: A code area that may generate exceptions, namely the try area.
Exception handler: The place where exceptions are handled, that is, the catch area.
Two models of exception handling
Termination model: Once an exception is thrown, there is no way to return to the place where the exception occurred.
Recovery model: instead of throwing an exception when an exception is raised, patch the exception through a method or by putting a try in a loop.
Note: Restoring the model tends to enhance program coupling
custom exception
import java.util.logging.Logger;
public class MyException {
private static void f() throws CustomException{
System.out.println("f:");
throw new CustomException();
}
private static void g(String msg)throws CustomException{
System.out.println("g:");
throw new CustomException(msg);
}
private static void h(){
int x,y,z;
x=4;
y=0;
try {
z=x/y;
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String... args) {
try {
f();
} catch (CustomException e) {
e.printStackTrace(System.out);
}
try {
g("msg");
} catch (CustomException e) {
e.printStackTrace(System.out);
}
h();
}
}
class CustomException extends Exception{
private Logger logger=Logger.getLogger("CustomException");
public CustomException(){
}
public CustomException(String msg){
super(msg);
}
@Override
public String getMessage() {
//return super.getMessage();
return "This is my custom error info";
}
}
When commenting out return super.getMessage():
f:
thinkinjava.CustomException: This is my custom error info
at thinkinjava.MyException.f(MyException.java:7)
at thinkinjava.MyException.main(MyException.java:26)
g:
thinkinjava.CustomException: This is my custom error info
at thinkinjava.MyException.g(MyException.java:11)
at thinkinjava.MyException.main(MyException.java:32)
h:
java.lang.ArithmeticException: / by zero
at thinkinjava.MyException.h(MyException.java:19)
at thinkinjava.MyException.main(MyException.java:36)
When commented out return "This is my custom error info":
f:
thinkinjava.CustomException
at thinkinjava.MyException.f(MyException.java:7)
at thinkinjava.MyException.main(MyException.java:26)
g:
thinkinjava.CustomException: msg
at thinkinjava.MyException.g(MyException.java:11)
at thinkinjava.MyException.main(MyException.java:32)
h:
java.lang.ArithmeticException: / by zero
at thinkinjava.MyException.h(MyException.java:19)
at thinkinjava.MyException.main(MyException.java:36)
getMessage is similar to toString method
exception and logging
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.logging.Logger;
public class LoggerException {
private static Logger logger=Logger.getLogger("LoggerException");
private static void logprint(Exception e){
StringWriter sw=new StringWriter();
PrintWriter pw=new PrintWriter(sw);
e.printStackTrace(pw);
logger.severe(pw.toString());
}
public static void main(String...args){
try {
throw new NullPointerException();
} catch (NullPointerException e) {
logprint(e);
}
}
}
May 01, 2018 9:31:36 PM thinkinjava.LoggerException logprint
critical: java.io.PrintWriter@330bedb4
throw: throw an error to the upper layer for processing
public class Thrower {
static void demoproc() {
try {
throw new NullPointerException("demo");
} catch(NullPointerException e) {
System.out.println("Caught inside demoproc.");
throw e;
}
}
public static void main(String args[]) {
try {
demoproc();
} catch(NullPointerException e) {
System.out.println("Recaught: " + e);
}
}
}
Caught inside demoproc.
Recaught: java.lang.NullPointerException: demo
stack trace
public class StackTracer {
private static void a(){
try{
throw new Exception();
}catch (Exception e){
for(StackTraceElement stackTraceElement:e.getStackTrace())
System.out.println(stackTraceElement.getMethodName());
}
}
private static void b(){
a();
}
private static void c(){
b();
}
public static void main(String...args){
a();
System.out.println("-------------");
b();
System.out.println("-------------");
c();
}
}
output:
a
main
-------------
a
b
main
-------------
a
b
c
main
Call from the bottom of the stack, similar to recursion
If the current exception is rethrown, printStackTrace() still displays the call stack information of the original exception throw point
private static void d() throws Exception{
throw new Exception("throw new Exception from d");
}
private static void e() throws Exception{
try{
d();
}catch (Exception e){
System.out.println("e try catch");
e.printStackTrace(System.out);
throw e;
}
}
private static void f() throws Exception{
try{
d();
}catch (Exception e){
System.out.println("f try catch");
e.printStackTrace(System.out);
throw (Exception) e.fillInStackTrace();
}
}
public static void main(String...args){
try {
e();
}catch (Exception e){
System.out.println("main try catch from e");
e.printStackTrace(System.out);
}
try {
f();
}catch (Exception e){
System.out.println("main try catch from f");
e.printStackTrace(System.out);
}
}
e try catch
java.lang.Exception: throw new Exception from d
at thinkinjava.StackTracer.d(StackTracer.java:19)
at thinkinjava.StackTracer.e(StackTracer.java:24)
at thinkinjava.StackTracer.main(StackTracer.java:44)
main try catch from e
java.lang.Exception: throw new Exception from d
at thinkinjava.StackTracer.d(StackTracer.java:19)
at thinkinjava.StackTracer.e(StackTracer.java:24)
at thinkinjava.StackTracer.main(StackTracer.java:44)
f try catch
java.lang.Exception: throw new Exception from d
at thinkinjava.StackTracer.d(StackTracer.java:19)
at thinkinjava.StackTracer.f(StackTracer.java:34)
at thinkinjava.StackTracer.main(StackTracer.java:51)
*main try catch from f
java.lang.Exception: throw new Exception from d
at thinkinjava.StackTracer.f(StackTracer.java:38)
at thinkinjava.StackTracer.main(StackTracer.java:51)
Such as the last output result, it no longer outputs the original throw point d
If two different custom exceptions are thrown, they cannot be associated, that is, the stack trace printed at the second throw point will not have any information about the first time. This is if we also want to print the first time. For the stack trace of the throw point, you need to use the exception chain:
public class ExceptionLink {
class MyException2 extends Exception{
public MyException2(Throwable throwable){
super(throwable);
}
public MyException2(){
super();
}
}
class MyException1 extends Exception{
public MyException1(){
super();
}
}
private void a() throws MyException1{
throw new MyException1();
}
private void b() throws MyException2{
try {
a();
}catch (MyException1 exception1){
System.out.println("b try catch");
exception1.printStackTrace(System.out);
throw new MyException2();
//throw new MyException2(exception1);
}
}
public static void main(String...args){
ExceptionLink exceptionLink=new ExceptionLink();
try {
exceptionLink.b();
} catch (MyException2 myException2) {
System.out.println("main try catch");
myException2.printStackTrace(System.out);
}
}
}
output:
b try catch
thinkinjava.ExceptionLink$MyException1
at thinkinjava.ExceptionLink.a(ExceptionLink.java:18)
at thinkinjava.ExceptionLink.b(ExceptionLink.java:22)
at thinkinjava.ExceptionLink.main(ExceptionLink.java:32)
main try catch
thinkinjava.ExceptionLink$MyException2
at thinkinjava.ExceptionLink.b(ExceptionLink.java:26)
at thinkinjava.ExceptionLink.main(ExceptionLink.java:32)
As above, the second throw point does not throw the information thrown by the first throw point, because these are two different exception classes.
If uncomment the commented line, it will output:
b try catch
thinkinjava.ExceptionLink$MyException1
at thinkinjava.ExceptionLink.a(ExceptionLink.java:18)
at thinkinjava.ExceptionLink.b(ExceptionLink.java:22)
at thinkinjava.ExceptionLink.main(ExceptionLink.java:32)
main try catch
thinkinjava.ExceptionLink$MyException2: thinkinjava.ExceptionLink$MyException1
at thinkinjava.ExceptionLink.b(ExceptionLink.java:26)
at thinkinjava.ExceptionLink.main(ExceptionLink.java:32)
Caused by: thinkinjava.ExceptionLink$MyException1
at thinkinjava.ExceptionLink.a(ExceptionLink.java:18)
at thinkinjava.ExceptionLink.b(ExceptionLink.java:22)
... 1 more
This is the exception chain
The finally statement is used in the return statement
try{
return;
}finally{
System.out.println("before return")
}
It will print "before return" before returning
Abnormal loss
There are two situations that cause abnormal loss:
try{
throw new Exception1();
}finally{
throw new Exception2();
}
try{
throw new MyException();
}finally{
return;
}