java中的异常

目录

1.异常的概念与体系结构

1.1异常的概念

1.2异常体系结构

1.3异常的分类

2.异常的处理

2.1防御式编程

2.2异常的抛出

2.2.1throw

2.3异常的捕获

2.3.1异常声明throws

2.3.2try--catch捕获并处理

2.3.3finally

3.自定义异常


1.异常的概念与体系结构

1.1异常的概念

在java中将程序过程中发生的不正常行为成为异常

1.算数异常

2.数组越界异常

3.空指针异常

1.2异常体系结构

异常种类繁多,为了对不同异常或者错误进行很好的分类管理,Java内部维护了一个异常的体系结构:

1.Throwable:是一场体系的顶层类,其派生出两个重要子类Error 和Exception

2.Error:是指虚拟机·1无法解决的严重问题 比如JVM的内部错误和资源耗尽,StackOverflowError和OutOfMemoryError,一旦发生回力乏术。

3.Exception:异常产生后程序员可以通过代码进行处理,使程序继续执行。比如:感冒、发烧。我们平时所说 的异常就是Exception。

1.3异常的分类

异常在不同的时候的发声可以分为编译时异常和运行时异常

1.编译时异常

在程序编译时发生的异常被称为编译时异常,也被称为受检查异常(Checked Exception)

2.运行时异常

在程序执行时发生的异常,被称为运行时异常,也被称为非检查异常(Unchecked Exception

RunTimeException 以及其子类对应的异常,都称为运行时异常 。比如: NullPointerException
ArrayIndexOutOfBoundsException ArithmeticException
注意:编译时出现的语法性错误,不能称之为异常。例如将 System.out.println 拼写错了 , 写成了
system.out.println. 此时编译过程中就会出错 , 这是 " 编译期 " 出错。而运行时指的是程序已经编译通过得到
class 文件了 , 再由 JVM 执行过程中出现的错误

2.异常的处理

2.1防御式编程

1. LBYL : Look Before You Leap. 在操作之前就做充分的检查 . 即: 事前防御型

缺陷:正常流程和错误处理流程代码混在一起 , 代码整体显的比较混乱。
2. EAFP : It's Easier to Ask Forgiveness than Permission. " 事后获取原谅比事前获取许可更容易 ". 也就是先操
, 遇到问题再处理 . 即: 事后认错型

优势:正常流程和错误流程是分离开的 , 程序员更关注正常流程,代码更清晰,容易理解代码
异常处理的核心思想就是 EAFP
Java 中, 异常处理主要的 5 个关键字: throw try catch finally throws

2.2异常的抛出

在编写程序时,如果程序中出现错误,此时就需要将错误的信息告知给调用者
有两种一种是JVM 抛出  一种是throw

2.2.1throw

语法形式

例如

注意事项

1.throw只能写在方法体内部

2.抛出的对象只能是Exception或者是Exception子类的对象

3. 如果抛出的是 RunTimeException 或者 RunTimeException 的子类,则可以不用处理,直接交给 JVM 来处理
4. 如果抛出的是编译时异常,用户必须处理,否则无法通过编译
5. 异常一旦抛出,其后的代码就不会执行

2.3异常的捕获

异常的捕获也是异常的处理,主要包括两种一.throws  二.try--catch

2.3.1异常声明throws

处在方法声明时参数列表之后,当方法中抛出编译时异常,用户不想处理该异常,此时就可以借助 throws 将异常抛出
给方法的调用者来处理。即 当前方法不处理异常,提醒方法的调用者处理异常

所以这就是掩耳盗铃

throws后面声明当前方法可能会抛出的异常,但是这里的异常没有被处理,只是交给了JVM处理,一旦交给JVM处理,程序就会被终止

注意事项:

1.throws必须跟在方法的参数列表之后。

2.声明的异常必须是Exception和Exception的子类

3.方法内部如果抛出了多个异常,throws之后必须跟多个异常类型,之间用逗号隔开, 如果抛出多个异常类型
具有父子关系,直接声明父类即可

4.调用声明抛出异常方法时,主函数必须解决异常,否则继续使用throws声明

但是异常依然没有被处理。

2.3.2try--catch捕获并处理

throws 对异常并没有真正处理,而是将异常报告给抛出异常方法的调用者,由调用者处理。如果真正要对异常进行
处理,就需要 try-catch
语法形式
抛出异常
没有抛出异常

注意事项:

1.当try语句中有先后两个异常时,只会先匹配try中先出现的异常,异常后面的代码就不会再执行

一个catch中也可以包括用或语句包括两条异常

2.如果抛出的异常与catch中的异常不匹配,及异常不会被成功捕获,也不会被处理,就继续往外抛,直到JVM捕获中断

3.try中可能会抛出多个不同的异常对象,则必须用多个catch来捕获----即多种异常,多次捕获

4.如果异常的处理方法一样可以写成这样

5.如果异常之间具有父子关系,一定是子类异常在前catch,父类异常在后catch,否则语法错

6.也可以用Exception一次性捕获(Exception是这些异常的父类)不推荐

  由于 Exception 类是所有异常类的父类 . 因此可以用这个类型表示捕捉所有异常 .
备注 : catch 进行类型匹配的时候 , 不光会匹配相同类型的异常对象 , 也会捕捉目标异常类型的子类对象 .
如刚才的代码 , NullPointerException ArrayIndexOutOfBoundsException 都是 Exception 的子类 ,
因此都能被捕获到 .

2.3.3finally

在写程序时, 有些特定的代码,不论程序是否发生异常,都需要执行,finally就可以实现这种情况

fianlly的两个例子

一:存在的意义

这段代码分两种情况

第一种:正常输入的是一个整数,data的值就直接会被返回,就不会执行sc.close这行代码,会造成空间资源的浪费。

第二种情况:输入的不是一个整数,发生异常就会执行sc.close代码。就不会造成资源的浪费

解决这种情况的方法就是把sc.close这行代码放进finally中。

第二段代码

答案是20 还是10

是20.一般我们不建议在 finally 中写 return (被编译器当做一个警告)

异常处理流程总结
1.程序先执行 try 中的代码
2.如果 try 中的代码出现异常 , 就会结束 try 中的代码 , 看和 catch 中的异常类型是否匹配 .
3.如果找到匹配的异常类型 , 就会执行 catch 中的代码
4.如果没有找到匹配的异常类型 , 就会将异常向上传递到上层调用者 .
5.无论是否找到匹配的异常类型 , finally 中的代码都会被执行到 ( 在该方法结束之前执行 ).
6.如果上层调用者也没有处理的了异常 , 就继续向上传递 .
  一直到 main 方法也没有合适的代码处理异常 , 就会交给 JVM 来进行处理 , 此时程序就会异常终止 .

3.自定义异常

我们实现一个用户登陆功能
public class LogIn {
private String userName = "admin";
private String password = "123456";
public static void loginInfo(String userName, String password) {
if (!this.userName.equals(userName)) {
}
if (!this.password.equals(password)) {
}
System.out.println("登陆成功");
}
public static void main(String[] args) {
loginInfo("admin", "123456");
}
}

自定义异常具体实现方法

1.自定义异常类,然后继承Exception或RunTimeException

2.实现一个带有String类型参数的构造方法,参数含义:异常出现的原因。

class UserNameException extends Exception {
public UserNameException(String message) {
super(message);
}
}
class PasswordException extends Exception {
public PasswordException(String message) {
super(message);
}
}

上面的login代码可以改成这样

public class LogIn {
private String userName = "admin";
private String password = "123456";
public static void loginInfo(String userName, String password)
throws UserNameException,PasswordException{
if (!userName.equals(userName)) {
throw new UserNameException("用户名错误!");
}
if (!password.equals(password)) {
throw new PasswordException("用户名错误!");
}
System.out.println("登陆成功");
}
public static void main(String[] args) {
try {
loginInfo("admin", "123456");
} catch (UserNameException e) {
e.printStackTrace();
} catch (PasswordException e) {
e.printStackTrace();
}
}
}

注意事项
自定义异常通常会继承自 Exception 或者 RuntimeException
继承自 Exception 的异常默认是受查异常
继承自 RuntimeException 的异常默认是非受查异常

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值