1.认识异常
所谓异常指的就是程序在运行出现错误时通知调用者的一种机制。异常的种类有很多, 不同种类的异常具有不同的含义, 也有不同的处理方式。
Java的异常处理机制能让程序在异常发生时,按照代码的预先设定的异常处理逻辑,针对性地处理异常,让程序尽最大可能恢复正常并继续执行,且保持代码的清晰。
2.异常的基本用法
2.1捕获异常
基本语法
try{
有可能出现异常的语句 ;
}[catch (异常类型 异常对象) {
} ... ]
[finally {
异常的出口
}]
- try 代码块中放的是可能出现异常的代码.
- catch 代码块中放的是出现异常后的处理行为.
- finally 代码块中的代码用于处理善后工作, 会在最后执行.
- 其中 catch 和 finally 都可以根据情况选择加或者不加
异常处理流程
- 程序先执行 try 中的代码
- 如果 try 中的代码出现异常, 就会结束 try 中的代码, 看和 catch 中的异常类型是否匹配.
- 如果找到匹配的异常类型, 就会执行 catch 中的代码
- 如果没有找到匹配的异常类型, 就会将异常向上传递到上层调用者.
- 无论是否找到匹配的异常类型, finally 中的代码都会被执行到(在该方法结束之前执行).
- 如果上层调用者也没有处理的了异常, 就继续向上传递.
- 一直到 main 方法也没有合适的代码处理异常, 就会交给 JVM 来进行处理, 此时程序就会异常终止.
2.2 抛出异常
throw抛出异常
public static void main(String[] args) {
System.out.println(divide(10, 0));
}
public static int divide(int x, int y) {
if (y == 0) {
throw new ArithmeticException("抛出除 0 异常");
}
return x / y;
}
// 执行结果
Exception in thread "main" java.lang.ArithmeticException: 抛出除 0 异常
at demo02.Test.divide(Test.java:14)
at demo02.Test.main(Test.java:9)
throws抛出异常
public static int divide(int x, int y) throws ArithmeticException {
if (y == 0) {
throw new ArithmeticException("抛出除 0 异常");
}
return x / y;
}
2.3关于finally的注意事项
public static void main(String[] args) {
System.out.println(func());
}
public static int func() {
try {
return 10;
} finally {
return 20;
}
}
// 执行结果
20
注意:
finally 执行的时机是在方法返回之前(try 或者 catch 中如果有 return 会在这个 return 之前执行 finally).
但是如果 finally 中也存在 return 语句, 那么就会执行 finally 中的 return, 从而不会执行到 try 中原有的return.
一般我们不建议在 finally 中写 return (被编译器当做一个警告).
3.Java的异常体系
- 顶层类 Throwable 派生出两个重要的子类, Error 和 Exception
- 其中 Error 指的是 Java 运行时内部错误和资源耗尽错误. 应用程序不抛出此类异常. 这种内部错误一旦出现,除了告知用户并使程序终止之外, 再无能无力. 这种情况很少出现.
- Exception 是我们程序猿所使用的异常类的父类.
- 其中 Exception 有一个子类称为 RuntimeException , 这里面又派生出很多我们常见的异常类NullPointerException , IndexOutOfBoundsException 等.
Java语言规范将派生于 Error 类或 RuntimeException 类的所有异常称为非受查异常, 所有的其他异常称为受查异常.
如果一段代码可能抛出受查异常, 那么必须显式进行处理.
显式处理的方式有两种:
a) 使用 try catch 包裹起来
public static void main(String[] args) {
System.out.println(readFile());
}
public static String readFile() {
File file = new File("d:/test.txt");
Scanner sc = null;
try {
sc = new Scanner(file);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
return sc.nextLine();
}
b) 在方法上加上异常说明, 相当于将处理动作交给上级调用者
public static void main(String[] args) {
try {
System.out.println(readFile());
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
public static String readFile() throws FileNotFoundException {
File file = new File("d:/test.txt");
Scanner sc = new Scanner(file);
return sc.nextLine();
}
4.自定义异常类
- 自定义异常,格式如下:
class 异常类名 extends Exception
{
public 异常类名(String msg)
{
super(msg);
}
}
- 标识可能抛出的异常:
throws 异常类名1,异常类名2
- 捕获异常:
try{
} catch(异常类名 y){
} catch(异常类名 y){
}
- 方法解释:
a.输出异常的信息
getMessage()
b.输出导致异常更为详细的信息
printStackTrace()
- 示例如下: CustomException.java
public class FormatException extends Exception
{
public FormatException(String message) {
super(message);
}
}
- 自定义异常通常会继承自 Exception 或者 RuntimeException
- 继承自 Exception 的异常默认是受查异常
- 继承自 RuntimeException 的异常默认是非受查异常