Java:异常的捕获及处理,你懂了嘛?

异常的概念:

异常是一种导致程序中断的指令流,如果不对异常进行正确的处理,则可能导致程序的中断指向,造成不必要的损失

异常的分类:

Throwable是所有异常的父类

Error:

严重问题,这个问题发生后,一般不针对编写的代码进行处理,通常都是有Jvm抛出的问题。

Exception:

RuntimeException:

运行时异常,该类及其子类都是,这种异常不处理,是可以编译通过的,但是运行时就会出错。

除了RuntimeException:

这类异常被称为编译时异常,这类异常必须要处理,不处理就运行不了。

异常的结构:

这是异常常见的一种结构写法:

try{
    
    

​       可能出现异常的代码:

}catch(异常名称){
    
    

​		处理方案:

}finally{
    
    

​       关闭资源
}

代码案例:

public class ExceptionTest {
    
    
    public static void main(String[] args) {
    
    
        int a =10;
        int b =0;
//        System.out.println(a/b);//分母不能为0,运行时异常,算数异常ArithmeticException。
//        System.out.println("end");
        try {
    
    
            System.out.println(a/b);
        }catch (RuntimeException e){
    
    
            System.out.println("除数不能为0");
        }finally {
    
    
            System.out.println("end");
        }
    }
}

注意事项:

try:

里面代码越少越好,因为被try包裹着代码执行时要走异常处理机制,需要Jvm给该机制分配额外资源。

catch:

里面至少有一行代码

多个异常处理:

代码案例:

public class ExceptionTest {
    
    
    public static void main(String[] args) {
    
    
        int a =10;
        int b =0;
        int c[]={
    
    1,2,3};
       // System.out.println(c[3]);//ArrayIndexOutOfBoundsException
        try {
    
    
            System.out.println(a / b);
            System.out.println(c[3]);
        }catch (ArrayIndexOutOfBoundsException e){
    
    
            System.out.println("数组索引越界");
        }
        catch (RuntimeException e){
    
    
            System.out.println("除数不能为0");
        }
        finally {
    
    
            System.out.println("end");
        }
    }
}

三种处理方法:

1.一个try多个catch

扫描二维码关注公众号,回复: 12121149 查看本文章

2.多个try对应多个catch,同时将多个异常抛出

3.一个try…catch,但是cath中异常写Exception,它可以匹配所有的子类异常

优缺点:

优点:省略了一些代码

缺点:try块中,如果前面的出现异常,则不会执行后面的代码。

注意:

1.同时存在多个异常时,当捕捉到第一个异常时,则直接跳转到finally,后续异常则不会再处理。

2.如果你不知道try中将会出现哪种异常,则可以使用父类的异常名称去捕获它(当然,能具体尽量具体)

3.多个异常中,存在等级关系,由小到大的捕获

异常新特性(jdk7以后):

public class ExceptionDemo3 {
    
    
    public static void main(String[] args) {
    
    
        int a =10;
        int b =0;
        int c[]={
    
    1,2,3};
        try {
    
    
            System.out.println(a / b);
            System.out.println(c[3]);
        }catch (ArrayIndexOutOfBoundsException|ArithmeticException  e){
    
    //同级异常可以通过|写在一起
            System.out.println("不好!有情况!");
        }
        finally {
    
    
            System.out.println("end");
        }
    }
}

Throwable:

概述:

Throwable 类是 Java 语言中所有错误或异常的超类。
只有当对象是此类(或其子类之一)的实例时,才能通过 Java 虚拟机或者 Java throw 语句抛出

常见方法:

①返回此 throwable 的详细消息字符串。

public String getMessage()

②返回此 throwable 的简短描述。

public String toString()

③将此 throwable 及其追踪输出至标准错误流。

public void printStackTrace()

④将此 throwable 及其追踪输出到指定的输出流。

public void printStackTrace(PrintStream s)

代码案例:

/**
 * Throwable
 *
 */
public class ExceptionDemo4 {
    
    
    public static void main(String[] args) {
    
    
     int a=0;
     int b=10;
     try{
    
    
         System.out.println(b/a);
     }catch (Exception e){
    
    
         System.out.println(e.getMessage());//返回此 throwable 的详细消息字符串。
         System.out.println(e);//调用toString方法,打印异常类名和异常信息。
         e.printStackTrace();//获取异常类名和异常信息,还有异常在程序中出现的问题,返回值void
     }
    }
}

throws与throw:

throws:

概述:

定义功能方式时,需要把出现的问题暴露出来,让调用者去处理。那么就需要通过throws在方法上标识。

格式:

权限修饰符 返回值类型 方法名()形参列表)throws 异常类型1,异常类型2…{}

注意:

1.throws必须跟在方法括号后面
2.一般情况下,throws别在main后面

编译时与运行时异常:

编译时的异常:以后谁调用该方法,一定要处理该异常。
运行时的异常:以后谁调用该方法,可以不一定处理该异常。

代码案例:

public class throwsTest {
    
    
    public static void main(String[] args) {
    
    
        try {
    
    
            method();
        } catch (Exception e) {
    
    
            e.printStackTrace();
        }
    }
    public static void method()throws Exception {
    
    
        int a =0;
        int b =10;
        System.out.println(b/a);
    }
}

throw

概述:

在功能方法内部出现某种情况,程序不能继续运行,需要进行跳转时,就用throw把异常对象抛出。

代码案例:

public class throwDemo {
    
    
    public static void main(String[] args) {
    
    
        method();
    }
    public static void method(){
    
    
        int a=10;
        int b=0;

        if(b==0){
    
    
            throw new ArithmeticException();
        }else {
    
    
            System.out.println(a/b);
        }
    }
//    public static void method() throws Exception {
    
    
//        int a=10;
//        int b=0;
//
//        if(b==0){
    
    
//            throw new Exception();
//        }else {
    
    
//            System.out.println(a/b);
//        }
//    }
}

区别:

throws

①用在方法声明后面,跟的是异常类名

②可以跟多个异常类名,用逗号隔开

③表示抛出异常,由该方法的调用者处理

④throws表示出现异常的一种可能性,并不一定会发生这些异常

throw

①用在方法体内,跟的是异常对象名

②只能抛出一个异常对象名

③表示抛出异常,由方法体内的语句处理

④throw则抛出了异常,执行throw则一定抛出了某种异常

异常的使用:

使用异常区别:

如果该功能可以将问题处理,就要try……catch处理

如果处理不了,就交给调用者处理,使用throws

区别:

如果程序还需要继续运行,就使用try……catch

如果程序不需要继续运行,就使用throws

finally:

特点:

被finally控制的语句体一定会执行

特殊情况下:在执行到finally之前jvm停止运行了,如System.exit(0)

public class finallyDemo {
    
    
    public static void main(String[] args) {
    
    
        int a=10;
        int b=0;
        try {
    
    
            System.out.println(a/b);
        }catch (Exception e){
    
    
            System.out.println("分母不能为0");
            //System.exit(0);有这句则不执行finally
        }
        finally {
    
    
            System.out.println("结束啦");
        }
    }
}

作用:

用于释放资源,在IO流操作和数据库操作中会见到。

面试题:

①final、finally、finalize区别?

final:最终的意思,可以修饰类,成员变量,成员方法
修饰类:类不能被继承
修饰变量:变量不能被修改
修饰方法:方法不能被重写
finally:
它是异常的一部分,用于释放资源。一般来说,无论异常是否发生,finally都执行。
finalize:
Object的一个方法,用于垃圾回收

②如果catch里面有return语句,请问finally的代码会执行吗?如果会,顺序是在return前还是后?:

会,并且在return之前执行。

准确来说,是在finally是在return运行中执行,先让 return 200,但是还没返回走,这时候发现还有finally语句,在执行finally语句,此时a=400,改变的是变量值,但是return 200 的这个路径已经形成,不能改变,因此返回200

public class finallyDemo2 {
    
    
    public static void main(String[] args) {
    
    
        System.out.println(method());
    }
    public static int method(){
    
    
        int a=100;
        try {
    
    
            System.out.println(a/0);
        }catch (Exception E){
    
    
            a=200;
            return a;
        }finally {
    
    
            a=400;
            System.out.println(a);
        }
        return 0;
    }
}

在这里插入图片描述

自定义异常:

概述:

虽然java中有很多个异常类型,但是它只是我们常见的类型,并不能涵盖所有的异常。而我们在开发过程中,会遇到各种各样的异常,这时候我们就要使用自己定义的异常类的。

书写方式:

我们只需要写一个普通类,继承Exception,或者RuntimeException

①继承自Exception

②继承自RuntimeException

代码案例:

public class MyException extends Exception {
    
    
    public MyException(){
    
    

    }
    public MyException(String s){
    
    
        super(s);//一定要访问父类的有参构造,这样才能把异常信息打印到控制台
    }
}
class Teacher{
    
    
    public void check(int score) throws MyException {
    
    
        if(score>100 || score<0){
    
    
            throw new MyException("成绩只能在0-100之间");
        }else {
    
    
            System.out.println("你输入的成绩没问题");
        }
    }
}
class Student{
    
    
    public static void main(String[] args) throws MyException {
    
    
        System.out.println("请输入一个成绩:");
        Scanner input =new Scanner(System.in);
        int score = input.nextInt();
        Teacher t = new Teacher();
        t.check(score);
    }
}

注意事项:

①子类覆盖父类方法时,子类的方法必须抛出相同的异常或者父类异常的子类(父亲坏了,儿子不能比父亲更坏)

②如果父类抛出了多个异常,子类覆盖父类时,只能抛出相同的异常或者是它的子集,子集不能抛出父类没有的异常

③如果被覆盖的方法没有编译异常的抛出,那么子类的方法绝对不可以抛出编译异常,如果子类方法内有编译异常发生,那么子类只能try不能throws

public class MyException2 {
    
    
    public static void main(String[] args) {
    
    
        zi z = new zi();
        z.show();
        z.method();
    }
}
class fu{
    
    
    public void  show() throws ArrayIndexOutOfBoundsException{
    
    

    }
    public void  method(){
    
    
        
    }
}

class zi extends fu{
    
    
    @Override
    public void show() throws ArrayIndexOutOfBoundsException{
    
    
        super.show();
    }

    @Override
    public void method() throws ArithmeticException{
    
    
        int a =10;
        int b =0;
        System.out.println(a/b);
    }
}

猜你喜欢

转载自blog.csdn.net/zjdzka/article/details/110422940