异常
错误: Error -> StackOverError 严重问题, 内存相关, 必须要解决的
异常: Exception -> 不那么严重
分类
RuntimeException
RuntimeException -> 运行时异常 [可以不需要处理,也叫未检查异常]
- NullPointerException空指针异常
- ArrayIndexOutOfBoundsException数组下标越界异常
- ClassCastException强制类型转换异常
- IllegalArgumentException - 传递非法参数异常
- ArithmeticException - 算术运算异常
- ArrayStoreException - 向数组中存放与声明类型不兼容对象异常
- NegativeArrayException数组负下标异常
- NegativeArraySizeException - 创建一个大小为负数的数组错误异常
- NumberFormatException - 数字格式异常
- SecurityException - 安全异常
Exception
Exception 已检查异常 [必须要处理的异常,也叫编译时异常]
Throwable:可抛出的,给提示的。以上异常、错误都是可抛出的。
- IOException输入输出异常(FileNotFoundException…基本就是找不到文件异常,找不到类异常找不到方法异常,找不到连接对象异常,总结来说就是"找不到异常")
- SQLException操作数据库异常
- UnsupportedEncodingException
- ParseException
异常处理
遇到未处理的运行时异常, 程序终止, 并且打印错误栈路径
try - catch
捕获异常
e.printStackTrace(); // 将异常出现的栈路径打印出来,但程序还是可以继续的
try - catch注意事项
- 可能出现异常的代码, 必须写在try中
- try 后面 必须有至少一个 catch 代码块
可以有一个 finally 代码块 - try代码块中的代码出现异常, 程序不会终止,
try中在出现异常的那行代码之后的所有语句都不会执行
catch中 是为了出现异常后准备的代码 - 一个try后面可以跟多个catch捕获不同的异常
多个catch一定是父类型异常放在子类型异常后面
无关的异常类型, 顺序不作要求 - catch中定义的是父类异常, 那么可以将父类所有的子类异常一起捕获
- try-catch 可以嵌套
- finally 无论有没有出现异常, 都会执行到的语句块
即使在try 或者 catch 写了return, 也会执行到finally
finally 扫尾工作, 比如用来释放资源。且finally中的一些计算不会影响到主方法的调用。
throws
抛出异常
运行时异常可以直接抛出,已检查异常必须要处理
throws 声明在方法上, 等同于将异常交给方法调用者继续处理,上级调用者又需要继续处理这个异常,因此不是一劳永逸的,套娃
产生异常的情况:
- 代码有误, 执行会主动抛出异常
- 手动抛出异常对象
throw 异常对象
// 手动抛出异常
public class Demo05 {
// 主方法向外抛出异常, 是抛给JVM, JVM接收到异常, 中断处理
public static void main(String[] args) throws ParseException {
// try {
// 会产生一个ParseException, 属于已检查异常, 必须处理
method1();
// } catch (ParseException e) {
// }
}
// method1方法声明了异常信息, 那么调用这个方法的时候就会可能产生一个声明的异常
// throws声明异常, 等同于将异常抛给调用者来处理
public static void method1() throws ParseException {
// 已检查异常 - 必须要处理
// 第一种处理方式: try-catch
try {
throw new IOException("IO异常是因为什么产生的");
} catch (IOException e) {
}
// 第二种处理方式: 在方法声明上添加 throws 声明
throw new ParseException("这是格式错了", 0);
// 运行时异常,可以不处理
// throw new NullPointerException("对象是null");
// throw new RuntimeException("这个运行时异常是你代码哪里写错了");
}
结论
异常处理的原则:
- 自己能解决的, 就自己解决, try-catch
- 自己不能解决的, 再向外抛出, throws
API
构造方法 new xxException(String message): message就是异常的信息
e.printStackTrace(): 打印异常的栈路径
e.getMessage(): 获得异常信息
自定义异常
class MyException extends Exception: 已检查异常
class MyException extends RuntimeException: 运行时异常
只需要自动生成构造方法即可
// 自定义的已检查异常
public class MyException extends Exception {
// 只需要添加构造方法即可
public MyException() {
}
public MyException(String message) {
super(message);
}
public MyException(String message, Throwable cause) {
super(message, cause);
}
public MyException(Throwable cause) {
super(cause);
}
public MyException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
super(message, cause, enableSuppression, writableStackTrace);
}
}
// 使用自定义异常
public class Demo06 {
public static void main(String[] args) {
// 模拟用户登录的过程
try {
login("lucy", "1234");
System.out.println("lucy欢迎你登录成功! - 页面跳转");
} catch (MyException e) {
System.out.println(e.getMessage());//获得异常信息
System.out.println("页面不跳转, 重新登录");
}
}
public static int login(String name, String password) throws MyException {
// 模拟登录业务逻辑处理
if ("lucy".equals(name) && "123".equals(password)) {
return 0;
} else {
// throw 抛出异常, 等同于return 方法结束
// 方法如果需要返回值, 相当于将异常返回
throw new MyException("用户名/密码错误");
}
}
}