29 异常
定义
执行过程中国出现不正常情况,导致程序停止,java处理异常的方式是中断处理
异常不是语法错误,语法错误编译就不会通过
异常体系
1异常体系java.lang包下,其2个子类Error和Exception,前者是错误,不能处理,只能避免,后者是使用不当
2 3如上,我们还记得使用SimpleDateFormat实例时,parse需要throws ParseException,这是要我们在字符串解析不满足要求时能抛出异常
4如上,我们还可以把throws ParseException注释掉,然后使用try{}catch(Exception e){}结构捕获异常,
这种异常是编译时的异常
5运行时异常如上,我们打印超Index的元素,这里还是可以用try catch捕获,当然对于catch部分,可以使用自己的操作方式。
6如上就是个错误展示,提示堆溢出错误,这必须修改代码,无法规避的
分析异常产生和如果处理异常
7还是以简单索引越界来说明,当我们输入了越界索引,jvm会检测异常,创建异常对象,记录内容,原因,位置,这个getElement没有trycatch捕获,JVM就会把异常抛给调用者main方法处理,main也没有处理方法,最后返回到Jvm,jvm就做2件事,打印异常对象到控制台,终止java程序
异常关键字
try catch finally throw throws
throw在指定位置抛出指定异常
格式 throw new xxxException("异常原因和内容")
需要注意的是,如果是抛出RuntimeException异常,我们一般不做处理,交给jvm
如果是其他语法错误,我们需要处理这个异常,要么throws,要么try-catch
8如上,我们对数组做了处理,判断是否为null,这里就故意传入,生成异常,我们可以传入自定义的文字描述异常,但是这样方法内没有捕获,main也没有,Jvm只能终止程序
对于空指针异常和越界异常都属于运行异常,一般不做额外处理捕获,留给jvm处理
Objects空指针对象判断requireNonNull
9Objects工具类本身有个要求非空的方法,对于空对象会自带抛出异常
10这样,我们每次判别非空,就使用默认方法即可,
11当然此方法还支持重载,可以传消息字符串参数
throws异常处理
会把异常给方法的调用者处理,最终传给jvm,在方法声明时使用,一般配合throw
格式 修饰符 返回类型 函数名 参数列表 throws aaaException,bbbException{
throw new aaaException();
throw new bbbException();
}
其中,方法内部的异常必须throws声明,其对象可以是Exception或者其子类,如果抛出的异常有父子类关系,使用父类即可,调用此方法的方法要么继续throws交给上级或者直到Jvm,要么try-catch捕获异常
12如上,我们设定不是特定路径就抛出文件未找到异常,这时调用它的main方法也会要求使用throws或者trycatch,我们在红色提示信息里可以看到,先由函数抛出异常,然后又main抛出异常,Jvm只能打印终止程序
try-catch异常处理
我们之前使用throws-throw,抛出异常后后面的程序就会中断,如果没有处理直到Jvm就会终止程序,而try-catch就是对特定异常实现处理
格式 try{可能生成异常的代码}catch(异常类型 异常变量名){出现异常的处理,一般工作中会把异常记录到日志中}
try可能生成多个异常,就要配合使用多个catch
13Throwable类处理异常方法
14如上3个方法,getMessage()返回异常的简短描述
toString()返回throwable的详细描述
printStackTrace()打印异常对象,此方法信息最全面
15Finally代码块
finally代码是必须和try一起配合使用,try{}catch{}finally(此代码无论是否出现异常都会执行)
finally一般用于资源回收释放(IO)
16多异常捕获
分3种处理方法,1分别处理,2一次捕获,分别处理3一次捕获一次处理
17如上,我们的2条语句分别会生成2个异常
18分别处理如上,对每条语句进行捕获
19由于第一个先捕获,所以没有出现第二个异常,这里需要注意的是,如果异常有父子类关系,子类必须写在上面,否则会报错
20因为在父类捕获时就会捕获子类,如上,我们把顺序颠倒就会报错,因为数组的索引越界异常继承自索引越界异常
21所以说的第三种使用父类的捕获即可,甚至可以使用Exception
22finally return注意事项
23代码如上,虽然没有任何异常,都会执行finally,我try里执行了return,但是finally的return才是最终返回的值
父子类抛出异常
如果父类抛出多个异常,子类重写方法可抛出相应异常或异常子类,或者不抛出异常
父类如果没有抛出异常,子类方法不能抛出异常,生成异常只能trycatch捕获,不能声明抛出
24代码如上
自定义异常
我们在Exception那知道其有很多子类,但是我们也会根据需要,使用自定义的异常(已有异常不够使用)
格式和自定义类一样
public class xxxException extends Exception(或RuntimeException){}
内部定义无参和message的2种构造方法
如果继承Exception说明是编译期异常,我们就必须抛出或者捕获
如果继承RuntimeException说明是运行期异常,我们交给jvm处理
25如上,定义异常,感觉没什么说的
26设置如果用户在信息列表就报错,否则天使添加成功,如上为添加成功
27 28当我们extends的是RuntimeException时,其实可以不写throws,因为交给jvm即可,我们若把其改成Exception,则会标红
29