JAVA异常

JAVA异常

1.初识异常

    异常指的就是程序在运行时出现错误时通知调用者的一种机制.我们在编写代码的过程中,遇到过许多的异常,比如

1.
System.out.println(10 / 0);
// 执行结果:    //0异常
Exception in thread "main" java.lang.ArithmeticException: / by zero

2.
int[] arr = {1, 2, 3};
System.out.println(arr[100]);
// 执行结果   //数组越界异常
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 100

3.
int[] arr=null;
System.out.println(arr[0]);
//执行结果   //空指针异常
Exception in thread "main" java.lang.NullPointerException


2.异常的处理

2.1 异常的抛出

    异常分为受查异常和非受查异常,受查异常就是我们说的编译异常,非受查异常就是运行异常.

  运行时异常:都是RuntimeException及其子类异常,比如NullPointerException,IndexOutOfBoundsException等,这些异常是不检查异常,程序中可以选择捕获处理,也可以不处理。这些异常一般是由程序逻辑错误引起的,程序应该从逻辑角度尽可能避免这类异常的发生。

  运行时异常的特点是Java编译器不会检查它,也就是说,当程序中可能出现这类异常,即使没有用try-catch语句捕获它,也没有用throws子句声明抛出它,也会编译通过。
  非运行时异常(编译异常):是RuntimeException以外的异常,类型上都属于Exception类及其子类。从程序语法角度讲是必须进行处理的异常,如果不处理,程序就不能编译通过。如IOException,SQLException等以及用户自定义的Exception异常,一般情况下不自定义检查异常。
在这里插入图片描述    在Java里面,我们借助关键字throw,抛出一个指定的异常对象,将错误信息反馈给调用者。如果出现异常但是我们没有手动抛出的时候,其实是JVM检测到后帮我们抛出的。

public class exception {
    public static void test(int a){
        if(a==1){
            throw new NullPointerException();
        }
    }
    public static void main(String[] args) {
        test(1);
    }
}

在这里插入图片描述

注意事项:

  1.throw必须写在方法体的内部

  2.抛出的必须是Expection或者Expection的子类对象。

  3.如果抛出的是运行时异常或者是其子类,那么就可以不用管,交给JVM处理就好

  4.如果你抛出的是一个受查异常,也就是编译时异常,那你就必须要手动的进行异常的声明,不然程序连编译都过不去

  5.异常一旦抛出,其后面的代码就不会执行了

  6.当我们没有解决这个异常的时候,我们就会把这个异常交给JVM处理,一旦交给JVM程序就奔溃了

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

2.2 捕获异常

    异常的捕获主要有两种:异常的声明throws,以及try - catch捕获处理

2.2.1 异常声明throws

    throws处在方法声明的参数列表之后,当方法中抛出编译时异常,此时用户不想处理该异常,就可以借助throws声明一下这个异常,然后让方法的调用者去处理。即当前方法不处理异常,提醒方法的调用者处理.
在这里插入图片描述
在这里插入图片描述

  1.声明的异常必须是Expection或者Expection的子类.

  2.方法内部如果抛出了多个编译时异常,那么参数列表后面throws需要声明多个异常,之间用逗号隔开.

  3.方法将编译时异常用throws进行声明之后,那么就需要我们的调用者去进行处理了。如果调用者也不想处理,那就继续用throws进行声明。都没有人处理,最后交给JVM处理.

2.2.2 try - catch

    对于throws而言,它其实对异常没有进行真正的处理,而是将其甩给了调用者,然后如果就这样一层层的甩出去的话,最终还是会交给到JVM的手上进行处理。如果想处理异常,就需要使用try - catch.

public class exception {
    public static void test(int a) throws CloneNotSupportedException {
        if(a==1){
            throw new CloneNotSupportedException();
        }
        if(a==2){
            throw new NullPointerException();
        }
    }
    public static void main(String[] args) throws CloneNotSupportedException {
        try{
            test(2);   //try当中放入可能会有异常的代码,比如这里的test()
        }catch (NullPointerException e){
            System.out.println("捕获到了NullPointerException");  //catch对异常进行捕获并处理
        }
        System.out.println("捕获异常之后执行的代码");
    }
}

    如果你try-catch捕获到的异常与你catch中定义的不是同一个类型,那照样还是处理不了,会交给JVM

public class exception {
    public static void test(int a) throws CloneNotSupportedException {
        if(a==1){
            throw new CloneNotSupportedException();
        }
        if(a==2){
            throw new NullPointerException();
        }
    }
    public static void main(String[] args) throws CloneNotSupportedException {
        try{
            test(2);
        }catch (CloneNotSupportedException e){
            System.out.println("捕获到了NullPointerException");
        }
        System.out.println("捕获异常之后执行的代码");
    }
}

在这里插入图片描述

2.3 异常注意事项

在这里插入图片描述
在这里插入图片描述

    如果我们要捕获的多个异常之间存在父子类关系,那一定是子类在前,父类在后。因为父类异常类包含所有的子类异常类,所以你把父类写在前面,会把所有有关的异常都会进行捕获,那么后面写的子类的捕获也就没有任何的意义了。
在这里插入图片描述
    当try当中存在多个异常的时候,从上往下执行谁先抛出异常就捕获哪个异常,一次只能捕捉到一个异常
在这里插入图片描述
在这里插入图片描述

    对于受查异常来说,当try当中没有抛出catch这个受查异常的时候,这里检测不到就会报错

public static void main(String[] args) throws CloneNotSupportedException {
        int[] arr=null;
        try{
            System.out.println(10/0);
            System.out.println(arr.length);   // try当中没有CloneNotSupportedException
        }catch (NullPointerException e){
            e.printStackTrace();
            System.out.println("捕获到了NullPointerException");
        }catch(CloneNotSupportedException e){
            e.printStackTrace();
            System.out.println("捕获到了CloneNotSupportedException");
        }
        System.out.println("捕获异常之后执行的代码");
    }
}

在这里插入图片描述

    try块和之前的throw手动抛异常一样,try块中抛出异常的位置之后的代码是不会执行的
在这里插入图片描述
在这里插入图片描述

2.4 finally的使用

finally 表示最后的善后工作, 例如释放资源,无论是否存在异常, finally 中的代码一定都会执行到.

 public static void main(String[] args) throws CloneNotSupportedException {
        Scanner sc=new Scanner(System.in);
        try{
            System.out.println(10/0);
        }catch (ArithmeticException e){
            System.out.println("捕获到了ArithmeticException");
        } catch (NullPointerException e){
            e.printStackTrace();
            System.out.println("捕获到了NullPointerException");
        }finally {
            sc.close();
            System.out.println("执行finally代码部分");
        }
        System.out.println("捕获异常之后执行的代码");
    }
}

在这里插入图片描述

  throw 与 throws 的区别?

  throw是直接抛出一个异常,多用于抛出自定义类型的异常,抛出的异常会直接被JVM处理,此时程序也会结束执行。throws是声明一个异常,此时只是让方法本身不用去处理这个异常,而让调用者去处理,如果调用者也不处理继续使用throws最终会被JVM处理,throws可以让程序暂时编译层面上不会报错。

2.4 异常的执行流程

  1.程序先执行 try 中的代码

  2.如果 try 中的代码出现异常, 就会结束 try 中的代码, 看和 catch 中的异常类型是否匹配

  3.如果找到匹配的异常类型, 就会执行 catch 中的代码

  4.如果没有找到匹配的异常类型, 就会将异常向上传递到上层调用者

  5.无论是否找到匹配的异常类型, finally 中的代码都会被执行到(在该方法结束之前执行)

  6.如果上层调用者也没有处理的了异常, 就继续向上传递

  7.一直到 main 方法也没有合适的代码处理异常, 就会交给 JVM 来进行处理, 此时程序就会异常终止.

public class exception {
    public static void fun() throws CloneNotSupportedException {
        String s1 = null;
        s1.length();
    }
    public static void main(String[] args) throws CloneNotSupportedException {
        try{
            fun();
        }catch (NullPointerException e) {
            e.printStackTrace();
        }
    }
}

在这里插入图片描述

3.JAVA异常体系

在这里插入图片描述

  1.顶层类 Throwable 派生出两个重要的子类, Error 和 Exception

  2.其中 Error 指的是 Java 运行时内部错误和资源耗尽错误. 应用程序不抛出此类异常. 这种内部错误一旦出现,除了告知用户并使程序终止之外, 再无能无力. 这种情况很少出现,异常是产生后程序员可以通过代码进行处理,使程序继续执行.

  3.异常就是一个类,分为编译时异常和运行时异常,编译时异常也叫作受查异常,运行时异常叫做非受查异常

4.自定义异常类

    Java中虽然已经给我们提供了很多的异常类,但是考虑到开发过程中的遇到的一些特殊的异常情况,此时需要我们自己去定义这么一个异常类。

public class UserNameException  extends Exception{
    public UserNameException(String message){
        super(message);
    }
}

public class PasswordException extends Exception{
    public PasswordException(String message){
        super(message);
    }
}

public class Login {
    public static String uname = "zs";
    public static String upassword = "123";

    public static void logininfo(String name, String password) throws UserNameException, PasswordException {
        if (!uname.equals(name)) {
            throw  new UserNameException("用户名出错了");
        }
        if (!upassword.equals(password)) {
            throw  new PasswordException("密码出错了");
        }
        System.out.println("登录成功");
    }

    public static void main(String[] args) {
        try {
            logininfo("z", "123");
        } catch (UserNameException e) {
            e.printStackTrace();
        } catch (PasswordException e) {
            e.printStackTrace();
        }
    }
}

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值