Skip to content

❤️ 异常体系

  • 非检查型异常 = error + RuntimeException、检查型异常 = 非 RuntimeException
  • error 是专门为 JVM 设计的,我们不应该去使用
  • RuntimeException 运行时异常
    • getMessage() 返回此异常的详细信息字符串
    • toString() 返回简短的异常类名 + 异常原因
    • printStackTrace() 输出异常错误信息到控制台【异常类名 + 位置 + 原因】
  • 非RuntimeException 编译时异常,在写的时候已经有红线提示了,必须被 throw,或者 try…catch…(算是给用户一个 warn,你必须要对这个异常有所处理)

JVM 会自己默认处理异常,那我们为什么还要自己处理呢?

因为 JVM 的默认处理方案会终止程序的运行,但我们在实际开发中就算程序出错了,我们依然还要继续运行

❤️ 异常处理

💛 try…catch…

java
try {
	可能出现异常的代码
	……
} catch(异常类名,变量名) {
	异常处理的代码
	……
}
……
A

NOTE

  • try 住的代码块要尽可能的小,因为 JVM 不会对 try 住的代码进行优化~~【重排序、内联】~~,怕导致不可预知的结果
  • 一般不会 try 住 throwable 异常,因为里面包含了 error (不是程序代码能处理的),除非是对于将本服务器的请求委托给外部时,由于外部可能会抛出 error 级别的异常,如果我们不 catch 一个 throwable,会导致我们的服务也崩溃

执行流程

  • 执行 try 内的代码
    • 未出现异常,不执行 catch 内的代码
    • 出现异常
      • 生成一个异常类对象,该对象被提交给 Java 运行时系统
      • Java 运行时系统到 catch 中匹配异常类,匹配成功,则执行 catch 内代码
      • 接着继续向下执行,直到代码 A

[!hint] 经典案例

  • for 循环里面 try …… catch ……,如果 try 里面报错,for 循环继续执行
  • try 里面 for 循环,如果 try 里面报错,for 循环会终止

💛 try…finally…

  • 不要在 finally 块中 return,而且会导致 catch 块的异常不会被处理
java
public int testMethod() {
    try {
        return 1;  // 这里返回1
    } finally {
        return 2;  // 但是最终返回的是2
    }
}

💛 try(resource) …… catch ……

resource 的代码会在 try 语法块执行完毕后,自动释放资源

java
try (ResourceType resource = new ResourceTypeConstructor()) {
    // 使用 resource 的代码块
} catch (ExceptionType e) {
    // 异常处理代码
}

💛 throws

throws 仅仅是抛出异常,并没有做任何处理,如果异常一直抛到了主程序,那程序就会崩溃,但是如果异常被 throw 了,但是在某个地方被 catch 了,那程序就不会崩溃

java
public void method() throws 异常名 {
	……
}

❤️ 自定义异常

java
public class demo {
	// 异常类
	static class scoreException extends Exception {
		// 无参构造
		public scoreException() {}

		// 带参构造
		public scoreException(String message) {
			// 传给Exception,Exception传给Throwable中的detailMessage
			super(message);
		}
	}

	public static void main(String[] args) throws scoreException {
		Scanner sc = new Scanner(System.in);
		int i = sc.nextInt();
		
		if (i < 0 || i > 100){
			throw new scoreException("你输入的分数有误");
		}else {
			System.out.println("分数正常");
		}
	}
}

❤️ 使用异常

  • 如果用户对于异常无能为力(只能 throw、或者打印异常信息 ……),那 api 的设计者应该将这个异常设置为运行时异常 RuntimeException,无需强制用户处理
  • 非检查型异常用户无需进行捕获,也不应该捕获

❤️ 异常大全

💛 注释异常

java
System.out.println("bug");   //\u000A is a newline

---
java: 需要';'

由于注释里的\u000A导致的,因为读程序时\u000A 会转换为一个换行符


java
System.out.println("bug");   //look inside c:\users

---
非法的Unicode转义

由于\u 后面没有跟着 4 位的十六进制数