day_17 异常机制
- 异常发生的原因有很多,尤其是用户输入和要打开的资源不存在
- 这些异常出错后,导致程序生命周期终止执行,从错误代码开始,之后的代码都不会执行
- java中 有一个专门模拟异常的类,就是 Throwable , 所有异常都继承这个类
- 异常处理的两种方式
- throws : 抛出异常,告诉调用处,这里可能有什么问题
- 如果你把异常抛给了调用处.那么调用处要么也抛出去,要么解决
- try…catch… : 解决异常
- try{
- 高风险代码;
- }catch(异常类型 变量){
- 解决方案;
- }
public class Exception_02 {
//抛出异常
// public static void main(String[] args) throws FileNotFoundException {
public static void main(String[] args) {
// 打开资源文件
try {
//try...catch 解决异常
FileInputStream fis = new FileInputStream("D:/xxx");
System.out.println(123);
// } catch (Exception e) {
} catch (FileNotFoundException e) {
// 打印错误的追踪栈帧,比较常用,适合程序员排错
// e.printStackTrace();
// 获取错误信息,适合响应给用户
String msg = e.getMessage();
System.out.println(msg);
}
System.out.println(456);
}
}
当父类有异常且有子类继承时
子类抛出的异常只能包括父类或者比父类异常的子类
public class Exception_03 {
}
class A{
public void m1() throws IOException{
}
}
class B extends A{
@Override
// 方法覆写,不能比原方法拥有更宽泛的异常
// 抛出的异常类,可以是父类方法中抛出的类,也可以是对应的子类 , 但是不能是它的父类
// 父类抛出一个异常A , 那么子类 要么还抛出A , 要么抛出A的子类, 要么不抛异常 , 但是不能是A的父类
public void m1() throws FileNotFoundException{
}
}
- try{
高风险代码;
- } catch(异常类型 变量){
处理方案;
- } catch(异常类型 变量){
处理方案;
- }…
- catch中异常类型 不能有继承关系,如果有继承关系,需要从子类到父类
public class Exception_05 {
public static void main(String[] args) {
//异常依次从子类到父类,因为多态性,如果父类在首位会接收到几乎所有异常,后面语句无法执行无法精确到异常的细节
try {
FileInputStream fileInputStream = new FileInputStream("");
} catch (FileNotFoundException e) {
System.out.println("找不到文件");
// TODO: handle exception
} catch (NullPointerException e) {
System.out.println("不能为NULL");
} catch (Exception e) {
System.out.println("其他异常");
}
}
}
throws抛出异常并不会处理异常,是一种提醒机制
- throws 抛出异常,并不会处理异常,是一种提醒机制
- 如果你调用 的方法,抛出一个编译时异常,要么你就try…catch处理掉,要么你也抛出
- throws 是抛出异常,并不会解决异常,一般用于类库端(被调用的这个类)
- 而 try…catch… 是解决异常的,一般用于客户端(调用其他类的这个类,一般客户端都有main方法)
public class Exception_04 {
public static void main(String[] args) {
//try...catch 解决文件找不到异常
try {
m1();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static void m1() throws FileNotFoundException{
m2();
}
public static void m2()throws FileNotFoundException{
m3();
}
public static void m3() throws FileNotFoundException{
FileInputStream fis = new FileInputStream("xxx异常");
}
}
当抛出多个异常时,逗号隔开没有先后顺序
public static void main(String[] args) throws Exception,
FileNotFoundException, IOException {
}
Finally
finally : 必须执行的语句块 比如 打开的资源,需要关闭
finally 不能单独出现,必须和try一起使用 或者和 try…catch…一起使用
finally语句块 只有一种不执行的情况,那就是关闭虚拟机 System.exit(0);
public class Exception_07 {
public static void main(String[] args) {
try {
int a = 0;
int b = 3;
// 除数不能为0,会出错
int c = b / a;
System.out.println(c);
} catch (Exception e) {
e.printStackTrace();
// 终止方法执行
return;
// System.exit(0);
} finally {
// 但是finally会执行
System.out.println("2222");
}
// 执行不到,因为上面有return
System.out.println("1111");
}
}
执行结果为异常抛出,并输出2222,因为有return语句,程序终止1111不执行,但是finally会执行,
除非JVM虚拟机关闭
例题:
public class Exception_08 {
public static void main(String[] args) {
int result = m1();
// 11
System.out.println(result);
}
public static int m1() {
int i = 10;
try {
// 因为finally中有return,并且优先级是比较高的
// 所以在编译的时候 就把这里的return去掉了,只有i++
return i++;
// i++;
} catch (Exception e) {
e.printStackTrace();
} finally {
// 11
System.out.println(i+"------------");
}
return i;
}
}
finally优先级比try高。return语句执行finally中的,try语句的return i++,语句编译为i++.
自动关闭资源
/**
Java1.7新特性 自动关闭资源
try{
开启资源;
}catch(异常类型 变量){
处理措施;
}finally{
关闭资源
}
try(开启资源){
高风险代码;
}catch(异常类型 变量){
处理措施;
}
public class Exception_10 {
public static void main(String[] args) {
//自动关闭资源
try(FileInputStream fileInputStream = new FileInputStream("xxx");){
// 操作
}catch (Exception e) {
e.printStackTrace();
}
}
}
- 需求 完成用户登陆
- 1 如果用户名不是admin 则提示用户名不存在
- 2 如果密码不是root 则提示密码不正确
- 客户端负责数据录入
- service 负责 逻辑校验
客户端类Client
public class Client {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.println("请输入用户名和密码 : ");
String username = scanner.next();
String password = scanner.next();
try {
UserService.login(username, password);
System.out.println("登陆成功");
} catch (UserException e) {
// e.printStackTrace();
System.out.println(e.getMessage());
}
}
}
自定义异常类 UserException
/**
* 1 继承一个已有的异常类
* 判断你应该是运行是异常还是编译时异常,如果是运行时异常需要继承 RuntimeException 否则就继承Exception即可
* 一般情况下 我们写的 一定是 编译时异常
* 2 公共的无参构造
* 3 公共的有参构造,传入字符串,并在构造方法中把该字符串传递给父类
*
* @author 天亮教育-帅气多汁你泽哥
* @Date 2021年10月20日 下午3:42:07
*/
public class UserException extends Exception {
public UserException() {
}
public UserException(String msg) {
super(msg);
}
}
逻辑实现类 UserService
package ThrowExample;
public class UserService {
public static void login(String username,String password) throws UserException{
if (username.equals("admin")) {
if (password.equals("root")) {
// TODO 登陆成功
// return "登陆成功";
}else {
// TODO 密码不正确
// return "密码不正确" ;
throw new UserException("密码不正确");
}
}else{
// TODO 用户名不正确
// return "用户名不正确";
throw new UserException("用户名不正确");
}
}
}
Test.java
package ThrowExample;
public class Test {
public static void main(String[] args) throws UserException {
// 异常源
throw new UserException("xxxxxxxx");
}
}