Java-异常-06
一、异常
1.1、异常概述
- 异常指程序运行中出现的不期而至的各种状况,如:文件找不到、网络连接失败、非法参数等。
- 异常发生在程序运行期间,它影响了正常的程序执行流程。
1.2、简单分类
-
编译时异常(又称受检异常):必须显示处理,否则程序就会发生错误,无法通过编译。
- 例如:要打开一个不存在文件时,一个异常就发生了,这些异常在编译时不能被简单地忽略。
-
运行时异常(又称非受检异常):无需显示处理,也可以和编译时异常一样处理。
-
所有的 RuntimeException 类及其子类被称为运行时异常。
-
例题:
public static void main(String[] args) { //method(); method2(); } // 编译时异常 public static void method2() { try { String s = "2020-12-9"; SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); Date d = null; d = sdf.parse(s); System.out.println(d); } catch (ParseException e) { e.printStackTrace(); } } // 运行时异常 public static void method() { try { int[] arr = {1, 2, 3}; System.out.println(arr[arr[3]]); //ArrayIndexOutOfBoundsException } catch (ArrayIndexOutOfBoundsException e) { e.printStackTrace(); } }
-
-
错误:错误不是异常,而是脱离程序员控制的问题。错误在代码中通常被忽略。
- 例如:当栈溢出时,一个错误就发生了,它们在编译也检查不到的。
1.3、异常体系结构
- Java 把异常当作对象来处理,并定义一个基类 java.lang.Throwable 作为所有异常的超类。
- 在 Java API 中已经定义了许多异常类,这些异常类分为两大类,错误 Error 和异常 Exception。
1.3.1、Error
- Error 类对象由 Java 虚拟机生成并抛出,大多数错误与代码编写者所执行的操作无关。
- Java 虚拟机运行错误(Virtual MachineError),当 JVM 不再有继续执行操作所需的内存资源时,将出现 OutOfMemoryError。这些异常发生时,Java 虚拟机(JVM)一般会选择线程终止
1.3.2、Exception
- 在 Exception 分支中有一个重要的子类 RuntimeException(运行时异常)
- ArraylndexOutOfBoundsException(数组下标越界)
- NullPointerException(空指针异常)
- ArithmeticException(算术异常)
- MissingResourceException(丢失资源)
- ClassNotFoundException(找不到类)等异常,这些异常是不检查异常,程序中可以选择捕获处理,也可以不处理。
- 这些异常一般是由程序逻辑错误引起的,程序应该从逻辑角度尽可能避免这类异常的发生。
- Error 和 Exception 的区别:Error 通常是灾难性的致命的错误,是程序无法控制和处理的,当出现这些异常时,Java 虚拟机(JVM)一般会选择终止线程;Exception 通常情况下是可以被程序处理的,并且在程序中应该尽可能的去处理这些异常。
1.4、JVM默认的处理方案
- 如果程序出现了问题,我们没有做任何处理,最终 JVM 会做默认的处理。
- 把异常的名称,异常原因及异常出现的位置等信息输出在了控制台。
- 程序停止执行。
1.5、异常处理机制
- 抛出异常
- 抓取异常
1.5.1、异常处理的五个关键字
1.5.1.1、try...catch 与 finally
try:设置异常的监控区域。catch:出现异常时,按照给定的异常进行捕获。finally:不管程序是否出现异常都执行。-
假设要捕获多个异常:cath() 中的异常要从小到大
-
格式:
try{ // 可能出现异常的代码; }catch(异常类名 变量名){ // 异常的处理代码。 } -
例题:
// try...catch... 与 finally public static void main(String[] args) { int a = 1; int b = 0; try { System.out.println(a/b); }catch (ArithmeticException e){ System.out.println("程序出现错误,变量 b 不能为 0"); // 打印错误的栈信息 e.printStackTrace(); }finally { System.out.println("finally"); } }
-
1.5.1.2、throw
throw:主动抛出异常-
例题:
// throw public static void main(String[] args) { new Dome01().test(1,0); } public void test(int a,int b){ if (b == 0){ // 出动抛出异常,一般用在方法中 throw new ArithmeticException(); } }
-
1.5.1.3、throws
-
throws:往上抛出异常-
格式:
throws 异常类名 -
例题:
public static void main(String[] args) { // 把异常抛到此处 try { new Dome01().test(1,0); } catch (ArithmeticException e) { e.printStackTrace(); } } // throws 往上抛出异常 public void test(int a,int b)throws ArithmeticException { System.out.println(a/b); }
-
-
throws 和 throw 的区别
- throws:
- 用在方法声明后面,跟的是异常类名。
- 表示抛出异常,由该方法的调用者来处理。
- 表示出现异常的一种可能性,并不一定会发生这些异常。
- throw:
- 用在方法体内,跟的是异常对象名。
- 表示抛出异常,由方法体内的语句处理。
- 执行 throw 一定抛出了某种异常。
- throws:
1.6、Throwable 的成员方法
| 方法名 | 说明 |
|---|---|
| public String getMessage() | 返回此 throwable 的详细消息字符串 |
| public String toString() | 返回此可抛出的简短描述 |
| public void printStackTrace() | 把异常的错误信息输出在控制台 |
1.6.1、getMessage() 方法
public static void main(String[] args) {
System.out.println("开始");
method();
System.out.println("结束");
}
public static void method(){
try{
int[] arr={1,2,3};
System.out.println(arr[10]);
}catch (ArrayIndexOutOfBoundsException e){
System.out.println(e.getMessage());
}
}
1.6.2、toString() 方法
public static void main(String[] args) {
System.out.println("开始");
method();
System.out.println("结束");
}
public static void method(){
try{
int[] arr={1,2,3};
System.out.println(arr[10]);
}catch (ArrayIndexOutOfBoundsException e){
System.out.println(e.toString());
}
}
1.6.3、printStackTrace() 方法
public static void main(String[] args) {
System.out.println("开始");
method();
System.out.println("结束");
}
public static void method(){
try{
int[] arr={1,2,3};
System.out.println(arr[10]);
}catch (ArrayIndexOutOfBoundsException e){
e.printStackTrace();
}
}
1.7、自定义异常
-
自定义异常类需要继承
Exception类 -
格式:
public class 异常类名 extends Exception{ 无参构造 带参构造 } -
语法:
// 自定义异常类 public class Dome02 extends Exception { // 传递数字 > 10 private String detail; public Dome02(){} public Dome02(String a) { this.detail = a; } // 重写 to String() 方法:异常的打印信息 @Override public String toString() { return "Dome02{" + detail + '}'; } }// 测试类 public static void main(String[] args) { try { test(1); } catch (Dome02 dome02) { // System.out.println("Dome02=>"+dome02); dome02.printStackTrace(); } } static void test(int a) throws Dome02 { System.out.println("传递的参数为:" + a); // 如果 a 大于 10则输出异常 if(a>10){ // 主动抛出异常 throw new Dome02("你输入了 >10 的数字"); // 提示信息 } System.out.println("OK"); } -
实际应用中的经验总结
- 处理运行时异常时,采用逻辑去合理规避同时辅助 try-catch 处理
- 在多重 catch 块后面,可以加一个 catch(Exception) 来处理可能会被遗漏的异常
- 对于不确定的代码,也可以加上 try-catch,处理潜在的异常
- 尽量去处理异常,切忌只是简单地调用 printStackTrace() 去打印输出
- 具体如何处理异常,要根据不同的业务需求和异常类型去决定
- 尽量添加 finally 语句块去释放占用的资源

浙公网安备 33010602011771号