java中的异常体系
java.lang.Throwable 是java的顶层类,它的子类error和exception都是继承它的,Exception的代码很简单基本上都是调用了super的代码。error同理。
public class Error extends Throwable {
static final long serialVersionUID = 4980196508277280342L;
/**
* Constructs a new error with {@code null} as its detail message.
* The cause is not initialized, and may subsequently be initialized by a
* call to {@link #initCause}.
*/
public Error() {
super();
}
/**
* Constructs a new error with the specified detail message. The
* cause is not initialized, and may subsequently be initialized by
* a call to {@link #initCause}.
*
* @param message the detail message. The detail message is saved for
* later retrieval by the {@link #getMessage()} method.
*/
public Error(String message) {
super(message);
}
/**
* Constructs a new error with the specified detail message and
* cause. <p>Note that the detail message associated with
* {@code cause} is <i>not</i> automatically incorporated in
* this error's detail message.
*
* @param message the detail message (which is saved for later retrieval
* by the {@link #getMessage()} method).
* @param cause the cause (which is saved for later retrieval by the
* {@link #getCause()} method). (A {@code null} value is
* permitted, and indicates that the cause is nonexistent or
* unknown.)
* @since 1.4
*/
public Error(String message, Throwable cause) {
super(message, cause);
}
/**
* Constructs a new error with the specified cause and a detail
* message of {@code (cause==null ? null : cause.toString())} (which
* typically contains the class and detail message of {@code cause}).
* This constructor is useful for errors that are little more than
* wrappers for other throwables.
*
* @param cause the cause (which is saved for later retrieval by the
* {@link #getCause()} method). (A {@code null} value is
* permitted, and indicates that the cause is nonexistent or
* unknown.)
* @since 1.4
*/
public Error(Throwable cause) {
super(cause);
}
/**
* Constructs a new error with the specified detail message,
* cause, suppression enabled or disabled, and writable stack
* trace enabled or disabled.
*
* @param message the detail message.
* @param cause the cause. (A {@code null} value is permitted,
* and indicates that the cause is nonexistent or unknown.)
* @param enableSuppression whether or not suppression is enabled
* or disabled
* @param writableStackTrace whether or not the stack trace should
* be writable
*
* @since 1.7
*/
protected Error(String message, Throwable cause,
boolean enableSuppression,
boolean writableStackTrace) {
super(message, cause, enableSuppression, writableStackTrace);
}
}
public class Exception extends Throwable {
static final long serialVersionUID = -3387516993124229948L;
public Exception() {
super();
}
public Exception(String message) {
super(message);
}
public Exception(String message, Throwable cause) {
super(message, cause);
}
/**
* Constructs a new exception with the specified cause and a detail
* message of <tt>(cause==null ? null : cause.toString())</tt> (which
* typically contains the class and detail message of <tt>cause</tt>).
* This constructor is useful for exceptions that are little more than
* wrappers for other throwables (for example, {@link
* java.security.PrivilegedActionException}).
*
* @param cause the cause (which is saved for later retrieval by the
* {@link #getCause()} method). (A <tt>null</tt> value is
* permitted, and indicates that the cause is nonexistent or
* unknown.)
* @since 1.4
*/
public Exception(Throwable cause) {
super(cause);
}
/**
* Constructs a new exception with the specified detail message,
* cause, suppression enabled or disabled, and writable stack
* trace enabled or disabled.
*
* @param message the detail message.
* @param cause the cause. (A {@code null} value is permitted,
* and indicates that the cause is nonexistent or unknown.)
* @param enableSuppression whether or not suppression is enabled
* or disabled
* @param writableStackTrace whether or not the stack trace should
* be writable
* @since 1.7
*/
protected Exception(String message, Throwable cause,
boolean enableSuppression,
boolean writableStackTrace) {
super(message, cause, enableSuppression, writableStackTrace);
}
}
error
error是程序运行,一般有oom stackoverflow等 ,属于程序异常,不属于bug,属于程序异常,需要手动处理,一般是资源受限,死锁等问题造成的。
StackOverflowError和OOM
- OOM异常需要到JVM那块 暂时先不写了
exception
包含为受检异常和运行异常 (编译时异常和运行时异常),前者在编译前就要检查是否有可能产生编译时异常;后者是在编译后运行时才会判断的异常。
受检异常:idea会提醒你可能得异常,你需要处理才能正常编译,可以throws或者try catch。常见的有IOException:
SQLException
ClassNotFoundException
InterruptedException
ParseException
NoSuchMethodException
FileNotFoundException
运行时异常:可以正常编译运行,我们需要注意这种异常。这种异常是属于代码的bug。常见的有NullPointerException,ArrayIndexOutOfBoundsException,
IllegalArgumentException,
IllegalStateException,
ClassCastException
我们也可以自定义异常,例如
public class MyNullpointException extends NullPointerException{
public MyNullpointException(String s) {
super(s);
}
}
在spring中我们可以定义全局异常
@ControllerAdvice
public class GlobalExceptionHandler {
// 捕获自定义异常 MyNullpointException
@ExceptionHandler(MyNullpointException.class)
public ResponseEntity<String> handleCustomException(MyNullpointException ex) {
// 可以根据需要进行异常处理逻辑
String errorMessage = "Custom Exception occurred: " + ex.getMessage();
System.out.println(errorMessage);
return new ResponseEntity<>(errorMessage, HttpStatus.INTERNAL_SERVER_ERROR);
}
// 捕获其他未处理的异常
@ExceptionHandler(Exception.class)
public ResponseEntity<String> handleOtherExceptions(Exception ex) {
// 可以根据需要进行异常处理逻辑
String errorMessage = "An error occurred: " + ex.getMessage()+ex.getStackTrace().toString()+ex.getCause().toString();
System.out.println(errorMessage);
return new ResponseEntity<>(errorMessage, HttpStatus.INTERNAL_SERVER_ERROR);
}
}
可以参考这个 git地址:
https://gitee.com/sunweibo5/demo/tree/master/src/main/java/com/example/demo/service/exceptions
对于异常的处理
主要包含 throws throw try catch finally这几个关键字。
我们可以主动抛异常
throw new NullPointerException();
主动抛出的异常 有两种处理方式 一种是try catch,去处理这个异常; 一种是thows 把这个异常抛出去给上层 让上层去处理。
常见的几种try catch finally的关系 下面代码分析一下
public static int test(){
System.out.println("try 中return");
int i= 1;
try{
System.out.println("try");
i++;
System.out.println("i:"+i);
return i;
}catch (Exception e){
System.out.println("catch");
return i++;
}finally{
System.out.println("finally");
i++;
System.out.println("i:"+i);
}
}
public static int test2(){
System.out.println("try 和 finally中同时return");
int i= 1;
try{
System.out.println("try");
i++;
System.out.println("i:"+i);
return i;
}catch (Exception e){
System.out.println("catch");
return 2;
}finally{
System.out.println("finally");
i++;
System.out.println("i:"+i);
return i;
}
//小心这里,可能会出现不可达的情况,比如finally中有return,或者try/catch都有return
}
public static int test3(){
System.out.println("catch 和 finally中同时return");
int i= 1;
try{
System.out.println("try");
i++;
System.out.println("i:"+i);
throw new NullPointerException();
}catch (Exception e){
System.out.println("catch");
i++;
System.out.println("i:"+i);
return i;
}finally{
System.out.println("finally");
i++;
System.out.println("i:"+i);
return i;
}
//小心这里,可能会出现不可达的情况,比如finally中有return,或者try/catch都有return
}
public static void main(String[] args){
System.out.println("返回值:"+test());
System.out.println("返回值:"+test2());
System.out.println("返回值:"+test3());
//主函数执行错误以后 就会到catch块 继续执行错误的话就会到
}
执行结果
try 中return
try
i:2
finally
i:3
返回值:2
try 和 finally中同时return
try
i:2
finally
i:3
返回值:3
catch 和 finally中同时return
try
i:2
catch
i:3
finally
i:4
返回值:4
try中有return,finally一定会执行。
try中有return, 会先将值暂存,无论finally语句中对该值做什么处理,最终返回的都是try语句中的暂存值。
当try,catch,finally语句中均有return语句,会忽略try中return。
还有一些情况
public static int test4(){
System.out.println("catch中报错 finally不返回");
try{
Integer.parseInt("execption");
System.out.println("try");
}catch (Exception e){
System.out.println("catch");
Integer.parseInt("execption");
//System.exit(0);//取消的话直接退出
}finally{
System.out.println("finally");
}
return 666;
}
运行结果:
catch中报错 finally不返回
catch
finally
Exception in thread "main" java.lang.NumberFormatException: For input string: "execption"
at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)
at java.lang.Integer.parseInt(Integer.java:580)
at java.lang.Integer.parseInt(Integer.java:615)
at com.example.demo.service.关键字.finallyy.Test.test4(Test.java:12)
at com.example.demo.service.关键字.finallyy.Test.main(Test.java:112)
public static int test5(){
System.out.println("catch中报错 finally又返回");
try{
Integer.parseInt("execption");
System.out.println("try");
}catch (Exception e){
System.out.println("catch");
Integer.parseInt("execption");
//System.exit(0);//取消的话直接退出
}finally{
System.out.println("finally");
return 666;
}
}
运行结果
catch中报错 finally又返回
catch
finally
返回值:666
对于有返回值的函数,当catch中有报错,finally没有返回值,会将整个错误抛出来;如果有返回值 就不会报错
public static int test6() {
try {
// do something
} catch (Exception e) {
// handle exception
throw new NullPointerException("An error occurred while handling the exception.");
} finally {
// do something else
int i = 1/0;
}
return 1;
}
结果
Exception in thread "main" java.lang.ArithmeticException: / by zero
at com.example.demo.service.关键字.finallyy.Test.test6(Test.java:30)
at com.example.demo.service.关键字.finallyy.Test.main(Test.java:126)
当异常发生时,程序将会跳转到catch块中,并抛出一个自定义异常CustomException。然后,程序将会执行finally块中的代码,其中包含除零操作,导致又抛出了一个新的异常ArithmeticException。
由于finally块中的异常将覆盖之前的异常,因此最终的异常将是ArithmeticException
线程池抛异常如何处理
InterruptedException 是 Java 中的一个异常类,它表示一个线程被中断的异常情况。当一个线程在等待、睡眠或者被阻塞时,另一个线程可以调用 interrupt() 方法来中断这个线程,即使这个线程没有主动调用可中断方法也可以中断它。
当一个线程被中断时,如果该线程正在执行一个可中断的操作(例如调用 sleep()、wait()、join() 等方法),或者调用了 Object 类的 wait()、wait(long)、wait(long, int)、join()、join(long)、join(long, int)、sleep() 方法中的其中一个,或者调用了 Thread 类的 sleep()、join()、join(long)、join(long, int) 方法,那么该线程会抛出 InterruptedException 异常。
一般来说,当线程收到 InterruptedException 异常时,应该在异常处理中进行适当的清理工作,然后退出或者恢复线程的运行,具体处理方式取决于应用的需求和设计。
在多线程编程中,处理 InterruptedException 异常是非常重要的,因为它涉及到线程的中断和恢复,而且在某些情况下可能会影响到程序的正确性和性能。