异常
异常
异常概述
异常是导致程序中断的一种指令流。发生异常时,默认情况下程序会打印异常信息并在发生异常的位置中断,不再执行后面的代码。为了让程序在出现异常之后可以继续执行,必须引入异常处理语句来完善代码编写。
异常的体系结构
try-catch方法处理异常
Java通过try、catch和finally三个关键字组成异常处理格式。
![image-20210322195831334](D:\Program Files\Typora\Java\image\image-20210322195831334.png)
执行流程:
- 程序从try里面的代码开始执行
- 出现异常,就会跳转到对应的catch里面去执行,try代码块未执行的代码将被跳过
- 执行完毕之后,程序还可以继续向下执行
- 如果有些代码必须要被执行,可以将其加到finally块中(无论有没有异常,finally中的代码都将被执行)
public class TestAbnormal {
public static void main(String[] args) {
try{
System.out.println("计算出发:10/0 = "+(10/0)); //这里出现异常
System.out.println("计算完毕。"); //出现异常后,将不再执行后面的语句,这条代码被跳过
}catch (ArithmeticException e){ //处理算术异常
System.out.println("*****出现异常了*****");
e.printStockTrace();//异常类中提供了printStackTrace()方法,可以输出异常的完整信息。
}
System.out.println("程序结束了。");
}
}
/*执行结果:
*****出现异常了*****
程序结束了。
java.lang.ArithmeticException: / by zero
at abnormalTest.TestAbnormal.main(TestAbnormal.java:6)
*/
Throwable成员方法
方法名 | 说明 |
---|---|
public String getMessage() | 返回此 throwable 的详细消息字符串 |
public String toString() | 返回异常的类名 |
public void printStackTrace() | 把异常的错误信息输出在控制台 |
public class ExceptionDemo02 {
public static void main(String[] args) {
System.out.println("开始");
method();
System.out.println("结束");
}
public static void method() {
try {
int[] arr = {1, 2, 3};
System.out.println(arr[3]); //JVM自动实例化了一个异常类的对象 new ArrayIndexOutOfBoundsException();
System.out.println("这里能够访问到吗");
} catch (ArrayIndexOutOfBoundsException e) {
//e.printStackTrace();
//public String getMessage():返回此 throwable 的详细消息字符串
// System.out.println(e.getMessage());
//结果:Index 3 out of bounds for length 3
//public String toString():返回此可抛出的简短描述
// System.out.println(e.toString());
//java.lang.ArrayIndexOutOfBoundsException: Index 3 out of bounds for length 3
//public void printStackTrace():把异常的错误信息输出在控制台
e.printStackTrace();
/*java.lang.ArrayIndexOutOfBoundsException: Index 3 out of bounds for length 3 at com.itheima_02.ExceptionDemo02.method(ExceptionDemo02.java:18)
*/
}
}
}
为了处理更多的异常类型,一个try可以和多个catch组合。不过每一种类型的异常都编写一条catch语句太过麻烦,如果可以利用子类对象向父类对象自动转型的多态性就可以简化了。
编译时异常和运行时异常的区别
-
编译时异常
- 都是Exception类及其子类
- 必须显示处理,否则程序就会发生错误,无法通过编译
-
运行时异常
- 都是RuntimeException类及其子类
- 无需显示处理,也可以和编译时异常一样处理
当程序运行中出现异常时,JVM会根据异常的类型自动实例化一个对象。如果没有try、catch语句,JVM会默认输出异常的的信息,然后结束程序。如果有try、catch语句,那么只要使用Exception类作为catch的参数就可以接收所有的异常类对象了,因为所有异常类都是Exception类的子类。
public class TestAbnormal {
public static void main(String[] args) {
try{
System.out.println("计算出发:10/0 = "+(10/0)); //这里出现异常
System.out.println("计算完毕。"); //出现异常后,将不再执行后面的语句,这条代码被跳过
}catch (Exception e){ //这样就可以处理所有类型的异常了
System.out.println("*****出现异常了*****");
e.printStockTrace();//异常类中提供了printStackTrace()方法,可以输出异常的完整信息。
}
System.out.println("程序结束了。");
}
}
thorws方式处理异常
Java 中允许在方法的后面使用 throws 关键字对外声明该方法有可能发生的异常,这样调用者在调用方法时,就明确地知道该方法有异常,并且必须在程序中对异常进行处理,否则编译无法通过。
- 编译时异常必须要进行处理,那么有两种处理方式:try...catch...或者throws,如果采用throws这种方式,将来谁调用谁处理。
- 运行时异常可以不处理,出现问题后再返回修改代码。
定义格式
public void method() throws 异常类名{
}
示例代码
public class TestThrows {
public static void main(String[] args) {
try{
System.out.println(TestThrows.div(10,0)); //调用此方法必须进行异常处理
}catch (Exception e){
System.out.println("出现异常了!!!");
e.printStackTrace();
}
}
public static int div(int x,int y)throws Exception{ //如果方法出错会明确的抛出异常
return x/y;
}
}
/*执行结果:
出现异常了!!!
java.lang.ArithmeticException: / by zero
at abnormalTest.TestThrows.div(TestThrows.java:14)
at abnormalTest.TestThrows.main(TestThrows.java:6)
*/
自定义异常
实际开发中,Java提供的异常类并不能满足我们的需要,比如学生的成绩必须在0-100之间,所以我们需要自定义异常。如果想要自定义一个异常类,只要此类继承Exception类即可。
public class ScoreException extends Exception {//Exception是编译时异常,必须进行异常处理
public ScoreException() {}
public ScoreException(String message) {
super(message); //调用父类Exception类的有参构造方法
}
}
前面的所有异常都是Java定义的,可以使用throw来自定义异常类型。
老师类
public class Teacher {
public void checkScore(int score) throws ScoreException {//throws其实是为了提示程序员这里会抛出一个异常
if(score<0 || score>100) {
throw new ScoreException("你给的分数有误,分数应该在0-100之间");//这里抛出的异常可以用printStackTrace方法打印
} else {
System.out.println("成绩正常");
}
}
}
测试类
public class Demo {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("请输入分数:");
int score = sc.nextInt();
Teacher t = new Teacher();
try {
t.checkScore(score);//此方法会throw一个异常,所以必须用try-catch语句接受
} catch (ScoreException e) {
e.printStackTrace();//此方法继承自Throwable,会打印错误的信息
}
}
}
常见面试题:请分析throw和throws的区别:
throw:指的是人为抛出一个异常类对象
throws:在方法的声明中使用,表示在调用此方法时必须处理异常。
throws
- 用在方法声明后面,跟的是异常类名
- 表示会抛出异常,需要程序员使用try-catch处理
- 表示的是出现异常的可能性,不一定会真的出现异常
throw
- 用在方法体内,跟的是异常对象名
- 表示抛出异常,由方法体内的语句处理
- 执行throw一定是出现了异常