zoukankan      html  css  js  c++  java
  • Java中的异常详解

    Java中的异常详解


    前言

    生活中的异常:

    1. 每天上班坐公交车去,正常的话半个小时,但是有时候会出现堵车(一定会出现的),或者遇到交通事故等,就有可能造成上班迟到的情况,这就是一种异常情况。
    2. 睡觉的时候,睡的正香,突然一个电话过来,被吵醒了。
    3. 在大街上走着,突然被绊倒了。

    概述

    Java中的异常:

    • 异常是指在程序的运行过程中所发生的不正常的事件,它会中断正在运行的程序。简单来说就是程序出现了不正常的情况。
    • 异常本质就是Java当中对可能出现的问题进行描述的一种对象体现。

    常见异常:

    • 除数不能为0异常(ArithmeticException)
    • 空指针异常(NullPointException)
    • 数组越界异常(ArrayIndexOutOfBoundsException)
    • 类型转换异常(ClassCastException)

    Throwable类

    Throwable 类是 Java 语言中所有错误或异常的超类。

    成员方法:

    • public String getMessage():返回此 throwable 的详细消息字符串
    • public String toString():获取异常类名和异常信息。
    • public void printStackTrace():获取异常类名和异常信息,以及异常出现在程序的位置。
    • public void printStackTrace(PrintStream s):通常用该方法将异常内容保存在日志文件中,以便查阅。

    Error和Exception

    1. Error:称为错误,由Java虚拟机生成并抛出,程序对其不做处理。

    2. Exception:所有异常类的父类,其子类对应了各种各样可能出现的异常事件,一般需要用户显示的声明或捕获。


    Exception类

    所有异常类的父类,其子类对应了各种各样可能出现的异常事件,一般需要用户显示的声明或捕获。

    运行时期异常(RuntimeException):

    • 运行时期异常,又称为非受检异常,RuntimeException及其所有子类都是运行时期异常。

    编译时期异常:

    • 不是继承自RuntimeException的Exception的子类都成为编译时期异常

    异常处理

    如果我们不做任何处理,异常将会交由虚拟机来处理。

    虚拟机的处理方式:

    • 把异常的名称,异常出现的位置,异常原因,等信息输出打印在控制台,并同时将程序停止执行。

    思考:

    在实际开发当中显然直接将应用程序挂掉的这种方式是不可取的,就算程序有异常,我们也理应让程序继续执行下去,提高用户体验。那我们又该怎么做呢?

    分析

    异常的执行流程:

    1. 程序执行到错误行,系统会创建一个异常对象,并且抛给我们

      ArithmeticException exp = new ArithmeticException("/by zero");

      ​ throw exp;

    2. 程序进入catch块进行逐个匹配,匹配成功,程序执行catch块代码

      ArithmeticException ae = exp;

      ​ Exception e = exp;

    3. 匹配失败,交给jvm处理

    jvm默认是如何处理异常的?

    1. 打印错误信息

      a.异常名称 java.lang.ArithmeticException

      b.异常的消息 / by zero

      c.异常所发生的方法位置 at com.sxt.exceptiondemo.ExceptionDemo02.main

      d.异常所在Java文件中 ExceptionDemo02.java

      e.异常发生行号 14

    2. 终止程序

      System.exit(0);

    处理异常的标准方式:

    1. 能够显示处理的尽量显示处理,提高程序的可读性。
    2. 但是一定要在异常处理的最后加上 父类Exception处理。

    处理方式

    1. try...catch...finally
    2. throws抛出异常
    • try...catch...finally

      • try...catch...finally的处理格式:
        异常处理的格式:
        try{
        //放置程序可能出现问题的代码
        }catch(异常类 异常名){
        //这里放置异常处理的代码
        } finally{
        //释放资源
        }

      • 多个异常的处理
        格式:try{
        ...
        }catch(异常类名 变量名) {
        ...
        }catch(异常类名 变量名) {
        ...
        } catch...

        排列catch 语句的顺序:

        1. 先子类后父类
        2. 发生异常时按顺序逐个匹配
        3. 只执行第一个与异常类型匹配的catch语句

    Throws和Throw

    throws关键字

    • 概述:在定义一个方法的时候可以使用throws关键字声明,使用throws声明的方法表示此方法不处理异常,而交给方法的调用者进行处理。
    • 格式: [修饰符] 返回值类型 方法名(参数列表) [throws 异常类1,异常类2....]{
      }

    注意:
    1、如果一个方法声明的是编译时期异常,则在调用这个方法之处必须处置这个异常(谁调用谁处理)。
    2、重写一个方法时,它所声明的异常范围不能被扩大

     public static int calc() throws ArithmeticException{
                   int a = 10;
                   int b = 0;
                   int result = a/b;
                   return result;
           }
    

    throw关键字

    • 在方法代码中主动抛出一个异常。如果方法代码中自行抛出的异常是编译时期异常,则这个方法要用throw关键字声明这个异常。
    public static void method2() throws ArithmeticException {
                   int a = 10;
                   int b = 0;
                   if (b == 0) {
                       // throw
                           throw new ArithmeticException("除数为0了!");
                   }
                   System.out.println(a/b);
           }
    

    throws和throw的区别

    1. throws用在方法声明后面,跟的是异常类名,throw用在方法体内,跟的是异常对象名。
    2. throws可以跟多个异常类名,用逗号隔开,throw只能抛出一个异常对象名。
    3. throws表示抛出异常,由该方法的调用者来处理,throw表示抛出异常,由方法体内的语句处理。
    4. throws表示出现异常的一种可能性,并不一定会发生这些异常,throw则是抛出了异常,执行throw则一定抛出了某种异常。

    finally关键字

    finally修饰的代码块一定会被执行,除非在执行到finally之前程序异常退出或者调用了系统退出的方法。

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

    注意:

    finally碰到return时finally一定会执行,那执行顺序?

    public class ExceptionDemo09 {
    	public static void main(String[] args) {
    
    		System.out.println(test()); // 4 3
    	}
    
    	public static int test() {
    		int x = 1;
    		try {
    			System.out.println(x++ / 0); // 2
    		} catch (Exception e) {
    			x++; //
    			return x; // return 3;
    		} finally {
    			++x; // 4
    			System.out.println(x); // 4
    		}
    		return x;
    	}
    }
    
    

    分析:

    在try语句中,在执行return语句时,要返回的结果已经准备好了,就在此时,程序转到finally执行了。

    在转去之前,try中先把要返回的结果存放到不同于x的局部变量中去,执行完finally之后,在从中取出返回结果。

    因此,即使finally中对变量x进行了改变,但是不会影响返回结果。它应该使用栈保存返回值。


    自定义异常

    在工作中有许多异常需要自己写。那如何写一个异常呢?

    • 编写一个分数必须在0-100分之间的异常,并且使用这个异常。

    步骤:

    • 定义一个异常继承Throwable或者Exception或者RuntimeException

    • 编写构造方法

      • 带参

      • 无参

    public class ExceptionDemo {
           public static void main(String[] args) {
                   Scanner input = new Scanner(System.in);
                   System.out.println("请输入一个分数:");
                   double score = input.nextDouble();
                   Teacher teacher = new Teacher();
                   try {
                           System.out.println(teacher.isBetween0To100(score) ? "分数合法" : "分数不合法");
                   } catch (ScoreException e) {
    //                        e.printStackTrace();
                           System.err.println(e.getMessage());
                   } catch (Exception e) {
                           e.printStackTrace();
                   } finally {
                           input.close();
                   }
                   System.out.println("分数批改完毕!");
                                   
           }
    }
    
    class ScoreException extends Exception{
           
           public ScoreException(){}
           
           public ScoreException(String message) {
                   super(message);
           }
    }
    
    class Teacher{
           
           public boolean isBetween0To100(double score) throws ScoreException{
                   if (score > 100 || score < 0) {
                           throw new ScoreException("分数必须在0-100分之间!!!");
                   }
                   return true;
           }
    }
    

    以上

    @Fzxey

  • 相关阅读:
    【阿里前端面试点】目标,想成为一名好的前端工程师
    JavaScript实现数据双向绑定的三种方式
    a标签的下载链接,如果是图片,点击链接是下载一个图片而不是直接打开,应该怎么办?(添加download属性)
    AngularJs scope详解
    setTimeout可以传第三个甚至更多个参数
    (转) css3中的border-radius详解
    (转) JS原生对象、内置对象、宿主对象的区别
    纯css写的步骤条
    css如何实现滚动条隐藏但鼠标仍然可以滚动
    Js 与浮点数
  • 原文地址:https://www.cnblogs.com/fzxey/p/10771124.html
Copyright © 2011-2022 走看看