1.之前碰到的异常
1 数组中 下标越界异常
2 对象中 空指针异常
3 递归中 栈内存溢出
4 多态中 类型转换异常
2.是什么
异常就是错误的一种描述
异常是java中专门响应错误的一种机制,能够有效的处理异常,并使得异常成为程序中的一部分,能够更有力的增强程序鲁棒性更易于调试
发生异常的原因有很多
1 用户输入了非法数据
2 要找的文件不存在
3 网络通信中断
4 JVM溢出
出现错误后,会终止程序生命周期执行,此时引入异常后,能够保证程序不会终止,并且还能够把错误信息,进行描述反馈
3.继承体系
4.Error
主要描述的是一些系统内部错误,比如我们之前碰到的栈内存溢出 OOM(内存溢出)
5.Exception
5.1 是什么
一般我们会把exception作为所有异常类的父类, 而exception又分为两大类
RuntimeException 和 非RuntimeException 运行时异常和非运行时异常(编译时异常)
运行时异常,一般是由于程序员粗心导致,比如空指针,比如 下标越界, 程序员完全可以通过if判断来解决这个问题
但是编译时异常,一般需要我们重点学习,另外编译时异常是我们在编码中就需要处理的,如果不处理,不能运行
5.2常用方法
public static void main(String[] args) {
try {
int a = 1;
int b = 0;
int c = a / b;
} catch (Exception e) {
// 获取错误信息 并打印 / by zero 一般用于响应给客户看
System.out.println(e.getMessage());
// 打印追踪栈帧 一般用于 给程序员看,方便解决错误和问题
e.printStackTrace();
}
System.out.println("====");
}
5.3Try
5.3.1 第一种用法
public static void main(String[] args) {
int a = 10;
int b = 0;
// 大部分运行时异常,都可以通过if来解决
// 但是if只能处理可以预知的错误
if (b == 0) {
System.out.println("除数不能为0");
} else {
int c = a / b;
System.out.println(c);
}
System.out.println("========");
}
//==================================================================
public static void main(String[] args) {
int a = 10;
int b = 0;
try {
// 高风险代码
int c = a / b;
System.out.println(c);
// 如果以上代码没有出现问题,则try会正常执行完成
// 就不会执行catch
} catch (Exception e) {
// 如果try中代码出现异常,则直接执行catch
System.out.println("除数不能为0");
}
System.out.println("====");
}
5.3.2 第二种用法
/**
try{
高风险代码
}catch(异常类型 变量){
处理方案
}catch(异常类型 变量){
处理方案
}
可以写多个catch 处理不同的异常
catch从上往下,要么异常类型没有继承关系,要么异常类型必须是由子到父
*/
public static void main(String[] args) {
try {
// 打开指定文件 传入文件路径
FileInputStream fis = new FileInputStream("xxx");
String s = null;
s.trim();
} catch (FileNotFoundException e) {
System.out.println("文件不存在");
} catch (NullPointerException e) {
System.out.println("变量不能为空");
}
}
5.3.3 第三种用法
/**
* try{
* 高风险代码
* }catch(异常类型 | 异常类型 变量...){
*
* }
*
* 可以同时捕捉多个异常,进行相同的处理措施
*
* 并且多个异常之间,不能有继承关系,如果有继承关系则直接写父类即可
*/
public static void main(String[] args) {
try {
// 打开指定文件 传入文件路径
FileInputStream fis = new FileInputStream("xxx");
String s = null;
s.trim();
} catch (FileNotFoundException | NullPointerException e2) {
System.out.println("出错了");
}
}
5.3.4 第四种用法
/**
* Java7开始,有两个改进
*
* 1 一个catch中 可以通过 | 捕捉多个异常
*
* 2 可以自动关闭资源
*
* try( 打开资源语句 ){
* }catch(异常类型 变量){
* }
*
* 传统写法是 try{ }catch(异常类型 变量){ }finally{ }
*/
public static void main(String[] args) {
try (FileInputStream fis = new FileInputStream("E:/a.txt");) {
// 打开资源
// 读取文件中内容
System.out.println(fis.read());
} catch (Exception e) {
// e.printStackTrace();
System.out.println("找不到文件");
}
}
5.4 Throws
5.4.1 第一种用法
/**
* throws 抛出异常,把问题抛出去,并没有解决
*
* 提醒调用处,这里可能出现问题,你处理一下
*
* 服务端(被调用出),一般使用throws抛出异常,因为不知道如何解决,所以把问题抛给调用处
*
* 客户端(调用处),一般使用try进行异常处理,因为只有调用处才知道,出问题应该如何处理
*/
public static void main(String[] args) {
try {
m1();
} catch (FileNotFoundException e) {
// e.printStackTrace();
System.out.println(e.getMessage());
}
System.out.println("=======");
}
public static void m1() throws FileNotFoundException {
m2();
}
public static void m2() throws FileNotFoundException {
m3();
}
public static void m3() throws FileNotFoundException {
new FileInputStream("sss");
}
5.4.2 第二种用法
// throws 抛异常,可以同时抛出多个
//多个用逗号隔开,并且多个异常中不用考虑继承和顺序
public static void main(String[] args) throws FileNotFoundException,
NullPointerException, Exception, RuntimeException {
}
5.4.3 注意--方法覆写
不能比原方法拥有更宽泛的异常
子类覆写的方法,可以不抛出异常
要么和父类方法抛出的异常一样
要么是父类方法抛出异常类的子类
要么不抛出,把异常处理
不能是父类方法抛出异常类的父类
5.5 Finally
5.5.1是什么
finally 是必须执行的语句块,写在finally中的代码,一定会执行
只有一种情况不会执行,就是 System.exit(0) 退出JVM虚拟机
因为其执行的特征,所以一般用于关闭资源操作
不能单独使用,需要结合try 或者 try..catch..一起使用
5.5.2 怎么用
public static void main(String[] args) {
// 1
try {
} finally {
}
// 2
try {
// System.exit(0) ;
// 这里会报错, 除数不能为0
System.out.println(10 / 0);
// 所以这里的代码执行不到
System.out.println("=====try");
} catch (Exception e) {
// 因为出错,所以执行catch
System.out.println("----catch");
// 终止方法执行
return;
} finally {
// 这里依然执行,因为 finally必须执行,所以finally优先级大于return
System.out.println("-----finally");
}
// 因为catch中有return, 所以这里不执行
System.out.println("=========");
}
5.5.3 注意事项
不能单独使用
除了关闭虚拟机以外,finally一定会执行
5.5.4 应用案例
public static void main(String[] args) {
FileInputStream fis = null;
try {
// 打开资源
fis = new FileInputStream("E:/a.txt");
// 读取文件中内容
System.out.println(fis.read());
} catch (Exception e) {
// e.printStackTrace();
System.out.println("找不到文件");
} finally {
// 关闭资源
if (fis != null) {
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
5.6 Throw
异常源点,创建一个异常
throw new 异常类( 错误信息 );
public static void main(String[] args) {
try {
m1();
} catch (FileNotFoundException e) {
// 自己抛出的异常
System.out.println(e.getMessage());
// 异常追踪栈帧
e.printStackTrace();
}
}
public static void m1() throws FileNotFoundException {
// 创建一个异常 , 一般需要结合throws 抛出
// throw 会终止方法执行
throw new FileNotFoundException("自己抛出的异常");
}
5.7 自定义异常类
5.7.1 定义语法
1 继承一个已有的异常类
如果是运行时异常,一般继承RuntimeException
如果是编译时异常,一般继承Exception
但是我们自定义的一般是编译时异常 所以直接继承Exception即可
2 提供无参构造
3 提供有参构造,用于传递错误信息,并把错误信息传递给父类构造
public StudentException() {
}
public StudentException(String mgs) {
super(mgs);
}
5.7.2 应用场景
比如,写一个用户管理模块
5.7.2.1 用户类
package com.ThrowExample.model;
public class User {
private String username;
private String password;
private String nickname;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getNickname() {
return nickname;
}
public void setNickname(String nickname) {
this.nickname = nickname;
}
public User(String username, String password, String nickname) {
super();
this.username = username;
this.password = password;
this.nickname = nickname;
}
public User() {
super();
}
public User(String username, String password) {
super();
this.username = username;
this.password = password;
}
}
5.7.2.2 Controller
package com.ThrowExample.controller;
import java.util.Scanner;
import com.ThrowExample.model.User;
import com.ThrowExample.service.UserService;
import com.ThrowExample.util.UserException;
// 前端交互,接收用户输入
public class UserController {
public static void main(String[] args) {
// 获取用户输入
Scanner scanner = new Scanner(System.in);
System.out.println("请输入用户名 : ");
String username = scanner.next();
System.out.println("请输入密码 : ");
String password = scanner.next();
// 封装User对象
User user = new User(username, password);
// 传入进行登陆校验
UserService userService = new UserService();
try {
User loginUser = userService.login(user);
System.out.println("登陆成功...正在跳转主页");
} catch (UserException e) {
// 获取错误信息
System.out.println(e.getMessage());
}
}
}
5.7.2.3 Service
package com.ThrowExample.service;
import com.ThrowExample.dao.UserDao;
import com.ThrowExample.model.User;
import com.ThrowExample.util.UserException;
// 业务逻辑处理
public class UserService {
public User login(User user) throws UserException{
// 1 用户输入的信息 user
// 2 根据用户名获取用户信息
UserDao userDao = new UserDao();
User oldUser = userDao.loadByUsername(user.getUsername());
// 3 校验
if (oldUser == null) {
throw new UserException("用户名不存在");
}
if (!user.getPassword().equals(oldUser.getPassword())) {
throw new UserException("密码不正确");
}
// 登陆成功,返回用户信息
return oldUser;
}
}
5.7.2.4 Dao
package com.ThrowExample.dao;
import com.ThrowExample.model.User;
// 数据库操作
public class UserDao {
// 需求 : 根据用户名获取用户信息
public User loadByUsername(String username) {
if (username.equals("admin")) {
User user = new User("admin", "root", "管理员");
return user;
}
return null;
}
}
5.7.2.5异常类
package com.ThrowExample.util;
public class UserException extends Exception {
public UserException() {
}
public UserException(String msg) {
super(msg);
}
}