目录
一、什么是异常(Exception)?
二、解决方案:try-catch
三、异常的概念
四、异常的体系图(重点)
小结:
五、常见的五大运行时异常
1、NullPointerException空指针异常
2、ArithmeticException数学运算异常
3、ArrayIndexOutOfBoundsException数组下标越界异常
4、ClassCastException类型转换异常
5、NumberFormatException数字格式不正确异常
六、编译异常
七、异常处理机制
1、try-catch-finally
编辑
2、throws
八、自定义异常
九、throw和throws的区别
目录的图片:
一、什么是异常(Exception)?
下面代码中的注释写的很清楚。
package com.hspedu.Exception;
public class Exception01 {
public static void main(String[] args) {
int num1 = 10;
int num2 = 0;
//1.当执行到num1/num2,因为num2 = 0,程序就会抛出异常ArithmeticException。Arithmetic(adj 算术的)
//2.抛出异常后,程序就退出,因为崩溃了,下面的代码不再执行。
//3.在2中叙述的情况,在现实中不合理,不应该因为出现了一个不算致命的问题,就导致整个系统崩溃。
//4.因此java设计者提供了一个叫 异常处理机制 来解决该问题。
int res = num1/num2;
System.out.println("程序继续运行......"); //不会输出该句
}
}
二、解决方案:try-catch
如果一段代码可能出现异常,可以使用try-catch异常处理机制来解决,从而保证程序的健壮性。
下面是try-catch机制的小例子:
package com.hspedu.Exception;
public class Exception01 {
public static void main(String[] args) {
int num1 = 10;
int num2 = 0;
//1.当执行到num1/num2,因为num2 = 0,程序就会抛出异常ArithmeticException。Arithmetic(adj 算术的)
//2.抛出异常后,程序就退出,因为崩溃了,下面的代码不再执行。
//3.在2中叙述的情况,在现实中不合理,不应该因为出现了一个不算致命的问题,就导致整个系统崩溃。
//4.因此java设计者提供了一个叫 异常处理机制 来解决该问题。
//5.有了try-catch机制后,即使出现了异常,程序仍然能够运行
try {
int res = num1/num2;
} catch (Exception e){
//e.printStackTrace(); //这种是标准写法
System.out.println("出现异常的原因= " + e.getMessage()); //e.getMessage()就是获取异常信息,这样写更舒服一点
}
System.out.println("程序继续运行......"); //不会输出该句
}
}
三、异常的概念
前面的例子就是运行时异常。
四、异常的体系图(重点)
对下图的解读(只是部分):Throwable类实现了Serializable接口,并继承了父类Object。Error和Exception都是Throwable类的子类,Exception下又分为运行时异常(RuntimeException)和编译时异常(像FileNotFoundException和ClassNotFoundException都是编译时异常)。虚线代表实现类接口,实现是代表继承,该图清晰的体现了继承和实现接口关系。
小结:
五、常见的五大运行时异常
1、NullPointerException空指针异常
在需要使用对象的地方用null时,抛出该异常。
继承关系如下图:
下面是案例:
package com.hspedu.Exception;
//这就是一个空指针异常
public class NullPointerException {
public static void main(String[] args) {
String name = null;
System.out.println(name.length());
}
}
2、ArithmeticException数学运算异常
当出现异常的运算条件时,抛出该异常,eg:整数除以0的时候。(上面有案例)
继承关系如下图:
3、ArrayIndexOutOfBoundsException数组下标越界异常
索引为负数or超出数组范围,抛出该异常。
继承关系如下图:
4、ClassCastException类型转换异常
将对象强制转换为不是实例的子类时,抛出该异常。(涉及到对象的多态)
继承关系如下图:
5、NumberFormatException数字格式不正确异常
将字符串转换成数值的时,不能适当转换,抛出该异常。
继承关系如下图:
六、编译异常
编译异常是指在编译期间,就必须处理的异常,否则代码不能通过编译。
常见的编译异常:
- SQLException //操作数据库时,查询表可能发生异常
- IOException //操作文件时,发生的异常
- FileNotFoundException //当操作一个不存在的文件时,发生异常
- ClassNotFoundException //加载类,而该类不存在时,发生的异常
- EOFException //操作文件,到文件末尾发生异常
- IIIegalArgumentException //参数异常
七、异常处理机制
异常处理就是当异常发生时,处理异常的方式。
1、try-catch-finally
在代码中捕获发生的异常,自行处理。
模板:
try{
//代码(可能有异常)
}catch (Exception e){
//捕获到异常:
//1.异常发生
//2.系统将异常封装成Exception对象e,传递给catch代码块
//3.得到异常对象后,程序员自行处理,在这里可以添加业务逻辑,
// 或者只是单纯的打印异常也行
//4.如果没有发生异常,catch代码块不执行
}finally {
//1.不管try代码块是否有异常发生,始终都要执行final
//2.所以通常将关闭连接、释放资源的代码,放在finally里面
}
Tips:
(1)如果try代码块可能有多个异常,可以使用多个catch分别捕获不同类型的异常,并作出相应处理。但是要求子类异常写在前面,不然会报错,例如下面的catch(Exception e)就写在了最后,因为如果catch(Exception e)写在前面,在这个catch代码块 就直接捕获了所有异常,下面再写catch不同类型的异常,没有意义。
(2)可以try-finally配合使用,这种做法相当于没有捕获异常,程序会直接崩掉。应用场景是:执行一段代码,不管是否发生异常,都必须执行某个业务逻辑。
try{
//代码
}finally{
//总是执行
}
(3)当try块中的异常发生后,try块中剩下的语句就不再执行,将执行catch块中的语句,如果有finally,还要再执行finally块中的语句。
2、throws
将发生的异常抛出,交给调用者(方法)处理,最顶级的处理者是JVM。
如果一个方法中可能出现异常,但是无法确定怎么处理该异常,则该方法应显式的声明抛出异常,表明该方法不对这些异常进行处理,而是由该方法的调用者负责处理。
解释:JVM调用main方法,main方法调用f1方法,f1方法调用f2方法。当f2方法中出现异常,有两种选择(1.在f2方法中try-catch-finally;2.throws给f1方法),后面的以此类推,最高可以抛给JVM。(JVM处理异常的方式很暴力(JVM说:都不管我也不管),1.输出异常信息;2.退出程序。)(村里除了问题,村长抛给县长,县长抛给市长,市长抛给省长,直到最高层(JVM))
模板:
//1.在方法声明中用throws语句抛出异常,throws关键字后面的异常类型可以是方法中产生的异常类型,
//例如FileNotFoundException,也可以是它的父类Exception。
//2.throws关键字后也可以是异常列表,即可以抛出多个异常。
// eg:public void f2() throws FileNotFoundException, NullPointerException, ArithmeticException
public void f2() throws FileNotFoundException, NullPointerException, ArithmeticException {
//创建了一个文件流对象
FileInputStream fileInputStream = new FileInputStream("d://a.txt");
}
Tips:
(1)对于运行时异常,程序中如果没有处理,默认就是throws的方式处理。
(2)子类重写父类的方法时,规定:子类重写的方法,所抛出的异常类型要么和父类抛出的异常一致,要么就是父类抛出的异常的类型的子类型。
(3)在throws过程中,如果有方法try-catch,就相当于处理异常,可以不用throws。
八、自定义异常
当程序中出现某些错误,但该错误信息并没有在Throwable子类中描述处理,此时可以自己设计异常类,用于描述该错误信息。
自定义异常的步骤:
例子:(看下面的例子就能明白自定义异常)
要求是接收Person对象年龄时,要求范围在18~120之间,否则抛出一个自定义异常(要求继承RuntimeException),并给出提示信息。
package com.hspedu.Exception;
public class customException {
public static void main(String[] args) {
int age = 80;
//要求范围在18~120之间,否则抛出一个自定义异常
if (!(age >= 18 && age <= 120)){
//这里我们可以通过构造器,设置信息
//注意这里是throw!!不是throws!!
throw new AgeException("年龄需要在18~120之间");
}
System.out.println("你的年龄范围正确");
}
}
//自定义一个异常
//1.一般情况下,我们的自定义异常是继承RuntimeException,即把自定义异常做成是运行时异常
//好处是,可以使用默认的默认处理机制
class AgeException extends RuntimeException{
public AgeException(String message) { //构造器
super(message);
}
}