一、异常
- 发现错误的理想阶段是在编译期间,如果不行,则只能在运行期间处理
- 容器,泛型,js中引入的ts,都是将运行期错误提前到编译期
- 如果当前自己能处理,那就处理
- 如果自己处理不了,就看看别人能不能处理, 把这个问题抛出来,交给更高一层去处理
1. 基本异常
# 异常发生时
1. 系统使用new,在堆上创建出一个异常对象
2. 当前程序的执行路径被终止,并且在当前环境弹出对异常对象的引用
3. 异常处理机制接管程序,寻找一个合适的地方来继续执行程序
4. 要么换一种方式来执行,要么继续执行下去
# 异常参数
1. throw关键字: 可以理解为一个异常对象的this引用
2. 类比于方法的一种返回值
3. 错误信息可以用异常的 类名 或者 异常信息来表示
# 异常处理模式
1. 终止模型
2. 恢复模型
2. 自定义异常
- 选择意思相近的异常来继承
- 自定义异常的名字非常关键: 见名知意
3. 异常说明
- library为方法提供异常说明,说明该方法可能发生的异常
- 强制客户端程序在代码中去处理这个异常
- 通过throws关键字在方法声明后面实现
- 被检查的异常
- 自定义的受检查异常: 必须是Exception的子类,或者非 RuntimeException 的子类
- 声明:
1.1 要么在方法声明处单独抛出,
1.2 要么在try 模块抛出同时必须要求在方法声明处抛出
1.3 调用方就要强制去处理
package com.erick;
public class Demo04 {
public static void main(String[] args) {
}
private static void method02() {
/*编译器就回强制要求: 要么继续抛出该异常,要么使用try catch来处理该异常*/
method01();
}
/*1. 自定义的受检查异常: 必须是Exception的子类,并且不是 RuntimeException*/
private static void method01() throws ErickException {
System.out.println("hello,exception");
}
}
class ErickException extends Exception {
public ErickException() {
}
public ErickException(String message) {
super(message);
}
}
4. 异常信息
package com.erick;
public class Demo05 {
public static void main(String[] args) {
try {
int num = 1 / 0;
} catch (Exception e) {
System.out.println(e.getClass()); // class java.lang.ArithmeticException
System.out.println(e.getClass().getName()); //java.lang.ArithmeticException
System.out.println(e.getClass().getSimpleName()); //ArithmeticException
System.out.println(e.getMessage()); // by zero
System.out.println(e.getCause()); // null
}
}
}
package com.erick;
public class Demo05 {
public static void main(String[] args) {
try {
second();
} catch (Exception e) {
// com.erick.Demo05.first(Demo05.java:20)
// com.erick.Demo05.second(Demo05.java:16)
// com.erick.Demo05.main(Demo05.java:6)
/*获取到栈调用的轨迹*/
StackTraceElement[] stackTrace = e.getStackTrace();
for (StackTraceElement element : stackTrace) {
System.out.println(element);
}
/*java.lang.ArithmeticException: / by zero
at com.erick.Demo05.first(Demo05.java:26)
at com.erick.Demo05.second(Demo05.java:22)
at com.erick.Demo05.main(Demo05.java:6)*/
// 栈调用的轨迹,异常逻辑
e.printStackTrace();
}
}
private static void second() {
first();
}
private static void first() {
int num = 1 / 0;
}
}
5. 异常链
- 捕获原来的异常,并抛出新的异常,就会把原来的异常信息丢失
- Error, Exception, RuntimeException这三个类: 可以传递cause来保存原来异常信息
- 其他类需要用initCause来保存
package com.erick;
public class Demo05 {
public static void main(String[] args) {
third02();
}
private static void third01() {
try {
second();
} catch (Exception e) {
/*1. 捕获原来的异常,并抛出新的异常,就会把原来的异常信息丢失*/
/* Exception in thread "main" java.lang.RuntimeException: ErickException
at com.erick.Demo05.third(Demo05.java:12)
at com.erick.Demo05.main(Demo05.java:5)
*/
throw new RuntimeException("ErickException");
}
}
private static void third02() {
try {
second();
} catch (Exception e) {
// 1. 捕获的异常不是 Error Exception RuntimeException
// 必须使用新异常的initCause
RuntimeException erickException = new RuntimeException("ErickException");
erickException.initCause(e);
throw erickException;
}
}
private static void second() {
first();
}
private static void first() {
int num = 1 / 0;
}
}
package com.erick;
public class Demo06 {
public static void main(String[] args) {
method01();
}
private static void method01() {
try {
method002();
} catch (Exception e) {
// 捕获的异常属于三个基本异常中的,因此可以用cause的方式来传递异常链
throw new RuntimeException("ErickException", e);
}
}
private static void method002() {
method003();
}
private static void method003() {
throw new RuntimeException("HAHAHAHA");
}
}
二、标准异常