一、Java异常类层次结构
在 Java 中,所有的异常都有一个共同的祖先 java.lang
包中的 Throwable
类。Throwable
类有两个重要的子类:
Exception
:程序本身可以处理的异常,可以通过catch
来进行捕获。Exception
又可以分为 Checked Exception (受检查异常,必须处理) 和 Unchecked Exception (不受检查异常,可以不处理)。Error
:Error
属于程序无法处理的错误 ,我们没办法通过catch
来进行捕获 。例如Java 虚拟机运行错误(Virtual MachineError
)、虚拟机内存不够错误(OutOfMemoryError
)、类定义错误(NoClassDefFoundError
)等 。这些异常发生时,Java 虚拟机(JVM)一般会选择线程终止。
Checked Exception 和 Unchecked Exception 有什么区别?
Checked Exception 即受检查异常,Java 代码在编译过程中,如果受检查异常没有被 catch
/throw
捕获 或者throw
往外抛处理的话,就没办法通过编译 。
除了RuntimeException
及其子类以外,其他的Exception
类及其子类都属于受检查异常 。常见的受检查异常有: IO 相关的异常、ClassNotFoundException
、SQLException
…。
Unchecked Exception 即 不受检查异常 ,Java 代码在编译过程中 ,我们即使不处理不受检查异常也可以正常通过编译。
RuntimeException
及其子类都统称为非受检查异常,例如:NullPointerException
、NumberFormatException
(字符串转换为数字)、ArrayIndexOutOfBoundsException
(数组越界)、ClassCastException
(类型转换错误)、ArithmeticException
(算术错误)等。
二、Throwable类常用方法
public String getMessage()
: 返回异常发生时的简要描述public String toString()
: 返回异常发生时的详细信息public String getLocalizedMessage()
:返回异常对象的本地化信息。使用Throwable
的子类覆盖这个方法,可以生成本地化信息。如果子类没有覆盖该方法,则该方法返回的信息与getMessage()
返回的结果相同public void printStackTrace()
:在控制台上打印Throwable
对象封装的异常信息
三、try-catch-finally
-
try
块: 用于捕获异常。其后可接零个或多个catch
块,如果没有catch
块,则必须跟一个finally
块。 -
catch
块: 用于处理 try 捕获到的异常。 -
finally
块: 无论是否捕获或处理异常,finally
块里的语句都会被执行。当在try
块或catch
块中遇到return
语句时,finally
语句块将在方法返回之前被执行。注意:不要在 finally 语句块中使用 return! 当 try 语句和 finally 语句中都有 return 语句时,try 语句块中的 return 语句不会被执行。
public static void main(String[] args) { System.out.println(f(2));; } public static int f(int value) { try { return ++value; } finally { if (value == 2) { return 0; } } }
输出:
0
finally 中的代码一定会执行吗?
在以下 2种特殊情况下,finally 块不会被执行:
- 在
try
或finally
块中用了System.exit(int)
退出程序。但是,如果System.exit(int)
在异常语句之后,finally
还是会被执行 - 程序所在的线程死亡。
代码示例:
try {
System.out.println("Try to do something");
throw new RuntimeException("RuntimeException");
} catch (Exception e) {
System.out.println("Catch Exception -> " + e.getMessage());
// 终止当前正在运行的Java虚拟机
System.exit(1);
} finally {
System.out.println("Finally");
}
四、使用 try-with-resources
来代替try-catch-finally(⭐️ ⭐️ ⭐️ )
-
适用范围(资源的定义): 任何实现
java.lang.AutoCloseable
的对象 -
关闭资源和 finally 块的执行顺序: 在
try-with-resources
语句中,任何 catch 或 finally 块在声明的资源关闭后运行《Effecitve Java》中明确指出:
面对必须要关闭的资源,我们总是应该优先使用
try-with-resources
而不是try-finally
。随之产生的代码更简短,更清晰,产生的异常对我们也更有用。try-with-resources
语句让我们更容易编写必须要关闭的资源的代码,若采用try-finally
则几乎做不到这点。 代码示例:
BufferedReader br = null; try { br = new BufferedReader(new FileReader("test.txt")); br.readLine(); } catch (Exception e) { e.printStackTrace(); } finally { if (br != null) try { br.close(); } catch (IOException e) { e.printStackTrace(); } }
将上面的代码例子改造:
try (BufferedReader br = new BufferedReader(new FileReader("test.txt"))) { br.readLine(); } catch (Exception e) { e.printStackTrace(); }
代码变得非常简洁。
注意:try-with-resource中声明的变量会隐式的加上final 关键字,所以无法再进行赋值。
五、自定义异常
在Java中要想创建自定义异常,需要继承Throwable或者他的子类Exception。
因为父类已经把异常信息的操作都完成了,所在子类只要在构造时,将异常信息传递给父类通过super 语句即可。
代码示例:
public class CustomException extends Exception {
//无参构造方法
public CustomException(){
super();
}
//有参的构造方法
public CustomException(String message){
super(message);
}
// 用指定的详细信息和原因构造一个新的异常
public CustomException(String message, Throwable cause){
super(message,cause);
}
//用指定原因构造一个新的异常
public CustomException(Throwable cause) {
super(cause);
}
}
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/68416.html