1.异常的定义及分类
1.异常的简单定义:程序在编译过程或运行时出现的不正常行为
2.异常分类:Java中的异常可分为Error(错误)和Exception(异常)两类。前者程序本身无法处理(一般涉及jvm方面),而后者程序可通过一定的方式进行处理。
| 第一类异常 | 第二类异常 |
|---|---|
| 编译时被检测的异常 | 编译时不被检测的异常(运行时异常,RuntimeException以及其子类) |
以下为java异常体系继承关系,Error与Exception的父类为Throwable(可抛出)
3.异常类常用方法:
String getMessage()
返回此对象的详细消息字符串。
[异常信息]void printStackTrace()
将此对象及其追踪输出至标准错误流。
[异常名称:异常信息,异常出现的位置,堆栈跟踪信息]
tips:jvm中的默认异常处理机制String toString()
返回此对象的简短描述。
[异常名称:异常信息]
tips:java为了增强代码阅读性会将父类名作为子类后缀名(借鉴)
4.使用异常的好处
| 将程序运行中的问题进行封装 | 将正常流程代码与问题处理代码进行分离,增强代码可读性 |
|---|
2.常见异常
| 异常名称 | 说明 |
|---|---|
| java.lang.ArrayIndexOutOfBoundsException | 数组索引越界异常 |
| java.lang.ArithmeticException | 算术条件异常 |
| java.lang.NullPointerException | 空指针异常 |
| java.lang.ClassNotFoundException | 找不到类异常 |
| java.lang.NegativeArraySizeException | 数组长度为负异常 |
| java.lang.ArrayStoreException | 数组中包含不兼容的值抛出的异常 |
| java.lang.IllegalArgumentException | 非法参数异常 |
| IOException | 操作输入流和输出流时可能出现的异常 |
| EOFException | 文件已结束异常 |
| FileNotFoundException | 文件未找到异常 |
3.异常的处理
常用格式一[捕捉+处理+关闭资源]:
try{
//待检测的代码
}catch(异常类 变量名){
}finally{
//一定会执行的操作
}
常用格式二[捕捉+处理]:
try{
//待检测的代码
}catch(异常类 变量名){
}
常用格式三[捕捉+关闭资源]:
try{
//待检测的代码
}finally{
// 一定会执行的操作
}
注意1:在try catch语句中的代码块自成一块变量作用域
注意2:finally中的语句一般用于关闭资源或一些必须执行的操作
注意3:finally中的语句即使在return后依旧会执行,除非程序执行System.exit(0)[jvm结束]
执行过程: try–>catch()(父类的引用接收子类对象)–>finally
注意: try代码块中一旦发生异常,异常语句后面的代码就停止执行
4.异常声明
格式: 方法名() throws Exception
说明:在方法上声明异常,便于提高安全性,让调用者进行处理,不处理则编译失败
处理过程:遇到异常–>捕捉或抛出(极端情况:抛出异常给jvm虚拟机)
5.多异常处理
1.声明异常时建议声明更具体的异常,这样在处理更加具有针对性
2.处理时可以添加多个catch语句对相应具体异常进行处理
3.如果多个catch块中的异常出现继承关系,则父类异常块应该放在后面(catch顺序执行)
4.建议在catch中对异常进行具体的处理,而不要仅仅进行简单的异常说明
处理方式举例:[将异常以文件形式记录下来(异常日志文件)]
简单举例:
try {
int end=eo.getEnd(-1,0);
} catch (SpecialException e) {
System.out.println("错误的首位数为:"+e.getNum());
}catch(ArithmeticException e2){
System.out.println(e2,toString());
}
6.自定义异常
应用场景:对具体项目中的特有问题进行自定义异常封装(参照java的异常封装思想)
//演示自定义异常
class SpecialException extends Exception{
int numExc;//特殊异常数据
public SpecialException(String msg){
super(msg);//调用父类构造方法
}
public SpecialException(String msg,int numExc){
super(msg);//调用父类构造方法
this.numExc=numExc;
}
public int getNum(){
return numExc;
}
}
//测试用类
class ExceptionOwn{
public int getEnd(int a,int b) throws SpecialException{
if(a>5)
throw new SpecialException("希望您的首位数字不要超过5");//抛出自定义异常信息的自定义异常
if(a<0)
throw new SpecialException("首位数字不能小于0",a);//抛出自定义异常信息的自定义异常
if(b==0)
throw new ArithmeticException("注意第二位参数不能为0");//抛出自定义异常信息的系统异常
return a/b;
}
}
1.建议自定义异常类以exception结尾[后缀名] extends Exception
2.自定义异常只能在代码中手动抛出([例:通过条件判断语句在特殊情况下使用throw关键字手动抛出])
3.若在方法中通过throw抛出自定义异常,必须进行以下两种处理方式:
在方法内部进行try catch 处理[自己处理];在方法上进行声明让该方法的调用者进行处理
4.一般情况下,方法内出现异常,方法上需要使用throws关键字进行声明
特殊:runtimeException 在方法中出现throw关键字,方法上可以不用throws声明,如果在方法上抛出该异常,调用者可以不用对该异常进行try catch处理
在该类情况下程序的设计者希望程序停止运行(因为这是由于调用者的错误使用造成的,程序无法继续运行;此时程序设计者希望使用者重新编写代码)
[例] NullPointerException ArithmeticException IndexOutOfBoundsException
自定义异常处理思想:如果该异常出现后,程序无法继续运行。则可以令该异常继承RuntimeException
定义自定义异常的异常信息: 在自定义异常类构造方法中直接调用super(msg)即可
还可以对异常信息进行特色化处理(例如输出运行中的输入数据)[通过定义多参数的构造函数以及相应的变量,并定义相应的getter方法]
throws和throw的区别:
throws使用在方法上;throw使用在方法内
throws后面跟异常类,可以跟多个,用逗号隔开;throw后者后跟异常对象
自定义系统异常的异常信息:在方法中通过throw new 系统异常(msg)
public int getEnd(int a,int b) throws SpecialException{
if(b==0)
throw new ArithmeticException("注意第二位参数不能为0");//抛出自定义异常信息的系统异常
return a/b;
}
7.异常在子类父类覆盖中的使用特点
1.子类继承父类,并对父类中有异常抛出的方法进行覆盖。则该方法在子类中只能抛出父类中的异常或其子类异常,不能抛出新的异常。
2.如果父类中的方法抛出多个异常,则子类在覆盖该方法时只能抛出父类中异常的子集。
3.如果父类或接口中的方法无异常抛出,则子类覆盖该方法时也不能抛出异常。如果出现异常,则只能在方法内部用try进行处理。
8.一个完整的简单异常应用实例
场景描述:司机驾驶汽车,汽车类可能会抛出两个异常,随其状态值而改变。针对汽车具体的异常,司机类也可能会抛出特殊异常。其中有对各异常的简单处理。
package com.dream.home_1102.exception;
//定义货车发动机过热异常
class CarHotException extends Exception{
public CarHotException(String msg){
super(msg);
}
}
//定义货车发动机损毁异常
class CarDestroyException extends Exception{
public CarDestroyException(String msg){
super(msg);
}
}
//定义司机无法继续驾驶异常
class DriverStopException extends Exception{
public DriverStopException(String msg){
super(msg);
}
}
//定义汽车类
class Car{
private int state=3;//汽车是否正常运行的状态码
public Car(int s){
state=s;
}
//定义汽车行驶方法
public void run() throws CarHotException,CarDestroyException{
if(state==2)
throw new CarHotException("发动机过热");
if(state==3)
throw new CarDestroyException("发动机已经损坏");
System.out.println("汽车正在行驶");
}
//定义汽车停止冷却方法
public void restCold(){
state=1;
System.out.println("经过修整,汽车的发动机温度回归正常");
}
}
//定义司机类
class Driver{
private String name;
public Driver(String name){
this.name=name;
}
public void drive(Car c) throws DriverStopException{
try {
c.run();
} catch (CarHotException e) {
System.out.println(e.toString());
c.restCold();
} catch (CarDestroyException e) {
throw new DriverStopException("司机停止行驶"+e.getMessage());
}
}
}
public class ManagerException {
public static void main(String[] args) {
Driver k=new Driver("K先生");
Car car1=new Car(1);
Car car2=new Car(2);
Car car3=new Car(3);
try {
k.drive(car1);
k.drive(car2);
k.drive(car3);
} catch (DriverStopException e) {
System.out.println(e.toString());
System.out.println("K先生可以考虑换一辆车了");
}
}
}
运行结果:
汽车正在行驶
com.dream.home_1102.exception.CarHotException: 发动机过热
经过修整,汽车的发动机温度回归正常
com.dream.home_1102.exception.DriverStopException: 司机停止行驶发动机已经损坏
K先生可以考虑换一辆车了
本文深入讲解Java中的异常处理机制,包括异常的定义、分类、处理方式等核心概念,并通过实例展示了如何自定义异常以及异常在子类父类覆盖中的使用特点。
426

被折叠的 条评论
为什么被折叠?



