异常概述
异常 : 就是程序在运行时出现不正常的情况
异常由来 : 出现的问题也是现实生活中的一个具体事物,可以通过java类的形式进行描述,并封装成对象,其实就是java对不正常情况进行描述后的对象体现
对于问题的划分: 两种: 一种是严重的问题 , 一种的是非严重问题
对于严重的 : java通过 Error 类进行描述 ,对于Error一般不编写针对性的代码进行处理
对于非严重的 : java通过 Exception 类进行描述 , 对于Exception 可以使用针对性的处理方式进行处理
无论Error或者Exception 都具有一些共性内容
- Throwble : Java 语言中所有错误或异常的超类
Thrwble子类: Error , Exception
异常的处理:
java提供了特有的语句进行处理
try{
需要被检测的代码
}catch (异常类 变量){
处理异常的代码(处理方式)
catch是用于处理异常,如果没有catch就代表异常没有被处理过,如果该异常是检测时异常,则必须声明
}finally {
一定会执行的语句
}
class XX {
public int div(int a, int b) {
return a / b;
/*
进行运算时,假设除数为0,则java虚拟机识别到了一个算数异常ArithmeticException
并new了此异常的对象,因为java中早已将此异常封装成了对象
然后java虚拟机就把这异常对象抛给了该功能的调用者:现在被主函数调用
* */
}
}
public class DEMO {
public static void main(String[] args) {
/*如果没有try,则异常对象抛给主函数后,主函数没办法处理该异常,又抛给了虚拟机,因为主函数被虚拟机调用,
虚拟机就调用了默认的异常处理机制,导致了程序停止,后面的程序没法继续
*/
try {
sop(x.div(5, 0));
/*异常对象传到此处,被try监测到了这个异常
try就将此异常丢给了catch
*/
} catch (Exception e) { //catch 了 Exception类型的异常,Exception e=new ArithmeticException();
sop("除零啦"); //处理方式
sop(e.getMessage()); //打印异常信息
sop(e.toString()); //打印异常名称 : 异常信息
e.printStackTrace(); //打印异常名称 : 异常信息 /异常的位置
//其实jvm默认的异常处理机制,就是在调用 printStackTrace 方法,打印异常的堆栈的跟踪信息
} finally {
}
sop("over");//错误由catch解决了,不会影响该程序运行
}
public static void sop(Object obj) {
System.out.println(obj);
}
}
throws Exception 声明异常
-
throws Exception :功能上通过throws 的关键字声明了该功能有可能会出现问题
-
调用者在使用该功能时,必须对其进行 捕获(try/catch) 或 声明以便抛出(throws Exception)
class XX {
public int div(int a, int b)throws Exception {//在功能上通过throws 的关键字声明了该功能有可能会出现问题
return a / b;
}
}
public class DEMO {
public static void main(String[] args)throws Exception { //如果程序出现异常则抛给虚拟机处理
XX x = new XX();
System.out.println(x.div(5, 1));
}
多异常
- 声明异常时,建议声明更为具体的异常,这样处理方式可以更为具体
- 函数中只要有异常发生,该函数就立即结束,剩下的代码不再执行
- 函数声明几个异常,就对应有几个catch块
class XX {
public int div(int a, int b) throws ArithmeticException, ArrayIndexOutOfBoundsException {
//声明功能可能会出现算术异常,角标越界异常
int[] arr = new int[a];
System.out.println(arr[4]); //如果a<=4则会出现角标越界异常,如果出现此异常,则立即抛出,下面程序不会执行
return a / b;
}
}
public class DEMO {
public static void main(String[] args) {
XX x = new XX();
try {
sop(x.div(5, 0));
} catch (ArithmeticException e) {
sop(e.toString());
sop("除数为零");
} catch (ArrayIndexOutOfBoundsException e) {
sop(e.toString());
sop("角标越界");
}
}
自定义异常
自定义异常:必须是自定义类继承Exception
-
原因:异常体系有一个特点,:因为异常类和异常对象都被抛出,他们具备可抛性,
这个可抛性是Throwable这个体系独有的特点
所以只有这个体系中的类或者对象才可以被throw和throws操作 -
当函数内部出现throw抛出异常对象,必须要有对应的处理动作
要么在内部try catch处理
要么在函数上声明异常 throws 该异常让调用者处理
/*
* 需求:除数为负数时,视为异常
* */
class FuShuException extends Exception{ //自定义异常,需要继承Exception
private int values; //定义一个values来表示异常值
FuShuException(String msg){ //输入异常信息
super(msg); //父类有该构造函数,直接super调用
}
FuShuException(String msg,int values){ //输入异常信息和异常的值
super(msg);
this.values=values;
}
public int getValues(){ //获取异常的值
return values;
}
}
class XX {
public int div(int a, int b) throws FuShuException{ //声明异常
if (b<0){
throw new FuShuException("除数出现了负数",b); //手动通过throw 关键字抛出一个自定义异常,自定义异常信息
}
return a / b;
}
}
public class DEMO {
public static void main(String[] args) {
XX x = new XX();
try {
sop(x.div(5,-5));
}catch (FuShuException e){
sop(e.toString());
sop("异常的值为"+e.getValues());
}
}
throws 和throw 区别
- throws 使用在函数上 ,后面跟的事异常类,声明该函数会出现的异常
- throw 使用函数内,后面跟的是异常对象
RuntimeException
- Exception中有一个特殊的子类异常RuntimeException (运行时异常)
如果在函数内抛出该异常,函数上可以不用声明,编译一样通过
如果在函数上声明了该异常,调用者可以不用进行处理(不需要try或者throws),编译一样通过
(简单来说就是RuntimeException可以不用声明抛出) - 之所以不用在函数上声明,是因为该异常不需要让调用者进行处理
当异常发生,开发者是希望让程序停止,因为再继续运行,可能会出现无法继续运算的情况
程序停止后,需要调用者对代码进行修正 - 在自定义异常时,如果该异常发生,影响或者无法继续运算,就让自定义异常继承RuntimeException
在异常发生时,就可以让该程序停止,让调用者修改正确的值才可以完整的执行全部程序
/*
* 需求:当调用者输入除数为负数时,程序立即停止
* 待调用者输入除数为正数时,程序才可以完整运行
* */
class FuShuException extends RuntimeException { //自定义异常,需要继承RuntimeException
FuShuException(String msg) { //输入异常信息
super(msg); //父类有该构造函数,直接super调用
}
}
class XX {
public int div(int a, int b) { //不需要声明异常b
if (b < 0) {
throw new FuShuException("除数为负数:" + b);
}
return a / b;
}
}
public class DEMO {
public static void main(String[] args) {
XX x = new XX();
x.div(5, -1); //除数为负数
}
异常练习
import java.util.*; //导入集合类包
/*
老师使用电脑上课
电脑可能出现蓝屏和冒烟
老师会因为电脑的原因而影响上课
蓝屏时,老师可以重启,继续上课
冒烟时,老师不能处理,出现了影响上课进度异常,需要将该异常抛出调用老师的人来处理
*/
class LanpingException extends Exception { //自定义一个蓝屏异常
LanpingException(String msg) {
super(msg);
}
}
class MaoyanException extends Exception { //自定义电脑冒烟异常
MaoyanException(String msg) {
super(msg);
}
}
class PlanException extends Exception { //自定义老师上课计划异常
PlanException(String msg) {
super(msg);
}
}
class Computer { //电脑类
private ArrayList<Integer> aa;
private int state; //设置一个值,1:电脑正常运行,2:电脑蓝屏,3:电脑冒烟
public void run() throws LanpingException, MaoyanException { //声明电脑运行会发生的异常
aa = new ArrayList<>();
aa.add(1);
aa.add(2);
aa.add(3);
Collections.shuffle(aa); //创建一个集合,存入1.2.3,并用shuffle随机打乱顺序
state = aa.get(0); //随机打乱顺序后获取第一个元素
if (state == 2) {
throw new LanpingException("蓝屏"); //当state=2.抛出一个蓝屏异常
} else if (state == 3) {
throw new MaoyanException("冒烟"); //当state=3,抛出一个冒烟异常
} else if (state == 1) {
System.out.println("电脑运行中...."); //当state=1,电脑正常运行
}
}
public void reset() { //电脑重启方法
System.out.println("电脑重启....");
}
}
class Teacher { //老师类
private String name;
private Computer com;
Teacher(String name) {
this.name = name;
com = new Computer();
}
public void teach() throws PlanException { //声明老师上课时会发生的异常
try {
com.run();
} catch (LanpingException e) {
System.out.println(e.toString());
com.reset(); //蓝屏处理的方式
} catch (MaoyanException e) {
System.out.println(e.toString());
throw new PlanException("因为电脑损坏影响讲课计划");
//将该冒烟异常转换,再抛出和该功能相关的异常
}
System.out.println(name + " 讲课中....");
}
}
public class DEMO {
public static void main(String[] args) {
Teacher t = new Teacher("陈老师");
try {
t.teach();
} catch (PlanException e) {
sop(e.toString());
sop("处理方式:"+"更换电脑");
}
}
public static void sop(Object obj) {
System.out.println(obj);
}
}