Java中的异常详解(概念,用法)

一.什么是异常?


  

   代码程序在运行时有可能会发生各种非正常的状况,如程序运行时磁盘空间不足,网络连接中断,被加载的类不存在等,针对这些非正常的情况,Java语言中引入了异常,并且以异常类的形式对这些非正常情况进行封装,通过异常处理机制对程序运行时发生的各种问题进行处理。

二.异常体系


异常类都来自于Throwable类

下图表示Java内置的异常类之间的继承关系:
在这里插入图片描述 ①顶层类Throwable派生出两个重要的子类,Error和Exception
 ②Error指的是Java运行时内部错误和资源耗尽错误,应用程序不抛出此类异常,这种内部错误一旦出现,除了告知用户并且程序终止之外,再无能为力。但这种情况很少出现。
 ③Exception是所有异常类的父类
 ④Exception类又派生出一个运行时异常类,运行时异常类就派生出很常见的数组下标越界异常,空指针异常类等

如下代码:

public class Test {
    public static void main(String[] args) {
        int result=func(2,0);
        System.out.println(result);
    }

    public static int func(int x,int y){
        return x/y;
    }
}

运行结果:
在这里插入图片描述  上述代码就产生了算术异常,代码中出现了被0除的错误。所以在这个异常发生后,程序会立即结束,无法继续向下执行。


  
Throwable常用方法:

方法声明功能描述
String getMessage返回此throwable的详细消息字符串
void printStackTrace将此throwable及其追踪输出至标准错误流
void printStackTrace(PrintStream s)将此throwable及其追踪输出到指定的输出流



三.异常的基本用法

1.捕获异常

  基本语法:

try{
   //可能出现异常的语句
}catch(异常类型 异常对象){
   //......
}finally{
  //.......
}

  catch代码块中放的是出现异常后的处理行为
  finally代码块中的代码用于处理善后工作,在最后执行
  其中catch和finally可以根据实际情况选择加或者不加



代码示例1(不处理异常)

public class Test {
    public static void main(String[] args) {
        int[] arr={1,2,3};
        System.out.println("before");
        System.out.println(arr[100]);
        System.out.println("after");
    }
}

执行结果:
在这里插入图片描述


代码示例2(使用try catch处理后)

public class Test {
    public static void main(String[] args) {
        int[] arr={1,2,3};
        try {
            System.out.println("before");
            System.out.println(arr[100]);
            System.out.println("after");
        }catch(ArrayIndexOutOfBoundsException e){
            e.printStackTrace();
        }
        System.out.println("after try catch");
    }
}

执行结果:
在这里插入图片描述  仔细观察上述两个代码运行结果,可以发现一旦try中出现异常,那么try中的代码块就不会再执行,而是交给catch中的代码来执行。catch执行完毕会继续往下执行。




代码示例3(异常类型要匹配)

public class Test {
    public static void main(String[] args) {
        int[] arr={1,2,3};
        try{
            System.out.println("before");
            arr=null;
            System.out.println(arr[100]);
            System.out.println("after");
        }catch(ArrayIndexOutOfBoundsException e){
            e.printStackTrace();
        }
        System.out.println("after try");
    }
}

执行结果:
在这里插入图片描述  上述代码catch不能捕获到空指针异常,因为异常捕获类型不匹配。所以catch可以有多个,或者用一个catch捕获所有异常(因为Exception类是所有异常类的父类,所以可以用Exception类捕获所有异常)。



代码示例4(一个catch捕获所有异常)

 public static void main(String[] args) {
        int[] arr={1,2,3};
        try{
            System.out.println("before");
            arr=null;
            System.out.println(arr[100]);
            System.out.println("after");
        }catch(Exception e){     //可以捕获所有异常
            e.printStackTrace();
        }
        System.out.println("after try");
    }

执行结果:
在这里插入图片描述


代码示例5(finally用法)

public class Test {
    public static int func() {
        try {
            int a = 10/0;
            return 88;
        }catch (ArithmeticException e) {
            e.printStackTrace();
            System.out.println("算术异常");
            return 8;
        }finally {
            return 9;    //如果将finally中return 9屏蔽掉,输出返回的是catch中的8
        }
    }
    
    public static void main(String[] args) {
            int ret = func();
            System.out.println(ret);
            System.out.println("after");
    }
}


执行结果:
在这里插入图片描述  注意:尽量不要将return语句放在finally中,因为会抑制catch中或者try中的return语句


2.异常处理流程

  ①程序先执行try中的代码块
  ②如果try中的代码块出现异常,就会结束try中的代码,看和catch中的异常类型是否匹配
  ③如果找到匹配的异常类型,就会执行catch中的代码
  ④如果没有找到,就会将异常向上传递到上层调用者
  ⑤无论是否找到匹配的异常类型,finally中的代码都会被执行
  ⑥如果上层调用者也没有处理异常,就继续向上传递
  ⑦一直到main方法也没有合适的处理异常,就会由JVM来进行处理,此时程序就会异常终止


3.抛出异常(throw关键字)

  除了Java内置类会抛出一些异常之外,也可以手动抛出某个异常,使用throw关键字。

代码示例:

public class Test {

    public static void main(String[] args) {
        System.out.println(divide(10,0));
    }
    
    public static int divide(int x,int y){
        if(y==0){
            throw new ArithmeticException("抛出除 0 异常");
        }
        return x/y;
    }
}

执行结果:
在这里插入图片描述

4.异常说明(throws关键字)

  
  在处理异常时,通常希望知道这段代码中究竟会出现哪些可能的异常,可以使用throws关键字,把可能抛出的异常显示的标注在方法定义的位置,提醒调用者要注意捕获这些异常。

代码示例:

public class Test {

    public static void main(String[] args) {
        System.out.println(divide(10,0));
    }

    public static int divide(int x,int y)throws  ArithmeticException{
        if(y==0){
            throw new ArithmeticException("抛出除 0 异常");
        }
        return x/y;
    }
}




四.自定义异常类

  
  实际生活中有些场景需要对异常类进行扩展,创建合适的异常类

代码示例:

class UserError extends Exception{    //自定义异常类继承Exception类
    public UserError(String message){
        super(message);
    }
}

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


public class Test {

    public static void main(String[] args) {
        try{
            login("admin","123456");
        }catch( UserError userError){
            userError.printStackTrace();
        }catch(PasswordError passwordError ){
            passwordError.printStackTrace();
        }
    }
    
    public static void login(String username,String password)throws UserError,PasswordError{
        if(!Test.username.equals(username)){
            throw new  UserError("用户名错误");
        }
        if(!Test.password.equals(password)){
            throw new  PasswordError("密码错误");
        }
        System.out.println("登录成功");
    }


注意:
①自定义异常类通常会继承自Exception类或者RuntimeException类
②继承自Exception类的异常默认是受查异常(编译时期异常)
③继承自RuntimeException的异常默认是非受查异常

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值