首页 > 编程语言 >java异常机制

java异常机制

时间:2022-10-08 22:34:27浏览次数:48  
标签:语句 java 处理 try catch 机制 异常 public

异常

  • 异常的概述

    异常就是程序出现了不正常的情况

 

异常(Exception)的概念

异常指程序运行过程中出现的非正常现象,例如除数为零、需要处理的文件不存在、数组下标越界等。在 Java 的异常处理机制中,引进了很多用来描述和处理异常的类,称为异常类。

异常类定义中包含了该类异常的信息和对异常进行处理的方法。

public class Test {
     public static void main(String[] args) {
     System.out.println("111");
     int a = 1/0;
     System.out.println("222");
     }
}

 

编译时异常和运行时异常的区别

  • 编译时异常

    • 都是Exception类及其子类

    • 必须显示处理,否则程序就会发生错误,无法通过编译

  • 运行时异常

    • 都是RuntimeException类及其子类

    • 无需显示处理,也可以和编译时异常一样处理

JVM默认处理异常的方式(理解)

  • 如果程序出现了问题,我们没有做任何处理,最终JVM 会做默认的处理,处理方式有如下两个步骤:

    • 把异常的名称,错误原因及异常出现的位置等信息输出在了控制台

    • 程序停止执行

查看异常信息 (理解)

  控制台在打印异常信息时,会打印异常类名,异常出现的原因,异常出现的位置

  我们调bug时,可以根据提示,找到异常出现的位置,分析原因,修改异常代码

throws方式处理异常

package Nomal_API.APIdemo.ThrowsDemo;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

public class ThrowsDemo1 {

        public static void main(String[] args) throws ParseException{
            System.out.println("开始");
//        method();
            method2();

            System.out.println("结束");
        }

        //编译时异常
        public static void method2() throws ParseException {  // throws 表示声明异常,调用该方法有可能会出现这样的异常
            String s = "2048-08-09";
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
            Date d = sdf.parse(s);
            System.out.println(d);
        }

        //运行时异常
        public static void method() throws ArrayIndexOutOfBoundsException { // throws 表示声明异常,调用该方法有可能会出现这样的异常
            int[] arr = {1, 2, 3};
            System.out.println(arr[3]);
        }
    }

注意事项

  • 这个throws格式是跟在方法的括号后面的

  • 编译时异常必须要进行处理,两种处理方案:

      • 【1】try...catch …

      • 或者【2】 throws,如果采用 throws 这种方案,在方法上进行显示声明,将来谁调用这个方法谁处理

  • 运行时异常因为在运行时才会发生,所以在方法后面可以不写,运行时出现异常默认交给jvm处理

throw抛出异常

  • 格式

    throw new 异常();

  • 注意

    这个格式是在方法内的,表示当前代码手动抛出一个异常,下面的代码不用再执行了

  • throws和throw的区别

throws throw
用在方法声明后面,跟的是异常类名 用在方法体内,跟的是异常对象名
表示声明异常,调用该方法有可能会出现这样的异常 表示手动抛出异常对象,由方法体内的语句处理

Java 是采用面向对象的方式来处理异常的。

  处理过程:

    抛出异常:在执行一个方法时,如果发生异常,则这个方法生成代表该异常的一个对象,停止当前执行路径,并把异常对象提交给 JRE。

    捕获异常:JRE 得到该异常后,寻找相应的代码来处理该异常。JRE 在方法的调用栈中查找,从生成异常的方法开始回溯,直到找到相应的异常处理代码为止。

异常分类

Java 中定义了很多异常类,这些类对应了各种各样可能出现的异常事件,所有异常对象都是派生于 Throwable 类的一个实例。如果内置的异常类不能够满足需要,还可以创建自己的异常类。

Java 对异常进行了分类,不同类型的异常分别用不同的 Java 类表示,

  所有异常的根类为 java.lang.Throwable,

  Throwable 下面又派生了两个子类:Error 和 Exception。

  Java异常类的层次结构如图所示:

Error

Error 是程序无法处理的错误,表示运行应用程序中较严重问题。大多数错误与代码编写者执行的操作无关,而表示代码运行时 JVM(Java 虚拟机)出现的问题。

例如,Java 虚拟机运行错误(Virtual MachineError),当 JVM 不再有继续执行操作所需的内存资源时,将出现 OutOfMemoryError。这些异常发生时,Java 虚拟机(JVM)一般会选择线程终止。

Error 表明系统 JVM 已经处于不可恢复的崩溃状态中。 

Exception

Exception 是程序本身能够处理的异常。

Exception 类是所有异常类的父类,其子类对应了各种各样可能出现的异常事件。 通常 Java 的异常可分为:

  1. RuntimeException 运行时异常

  2. CheckedException 已检查异常 

RuntimeException 运行时异常

派生于 RuntimeException 的异常,如被 0 除、数组下标越界、空指针等,其产生比较频繁,处理麻烦,如果显式的声明或捕获将会对程序可读性和运行效率影响很大。因此由系统自动检测并将它们交给缺省的异常处理程序。

编译器不处理 RuntimeException, 程序员需要增加“逻辑处理来避免这些异常”。

【示例】ArithmeticException 异常:试图除以 0

public class Test3 {
    public static void main(String[ ] args) {
    int b=0;
    System.out.println(1/b);
    }
}

try-catch方式处理异常

try {


      可能出现异常的代码;
  } catch(异常类名 变量名) {


    异常的处理代码;
}

执行流程

  • 程序从 try 里面的代码开始执行

  • 出现异常,就会跳转到对应的 catch 里面去执行

  • 执行完毕之后,程序还可以继续往下执行

  • 一个 try 语句必须带有至少一个 catch 语句块或一个 finally 语句块。 
  • 当异常处理的代码执行结束以后,不会回到 try 语句去执行尚未执行的代码。 

catch:

  • 每个 try 语句块可以伴随一个或多个 catch 语句,用于处理可能产生的不同类型的异常对象。

catch 捕获异常时的捕获顺序:

  • 如果异常类之间有继承关系,先捕获子类异常再捕获父类异常。

finally:

  • 不管是否发生了异常,都必须要执行。
  • 通常在 finally 中关闭已打开的资源,比如:关闭文件流、释放数据库连接等。

try-catch-finally 语句块的执行过程详细分析:

  • 程序首先执行可能发生异常的 try 语句块。如果 try 语句没有出现异常则执行完后跳至finally 语句块执行;
  • 如果 try 语句出现异常,则中断执行并根据发生的异常类型跳至相应的catch 语句块执行处理。catch 语句块可以有多个,分别捕获不同类型的异常
  • catch 语句块执行完后程序会继续执行 finally 语句块。finally 语句是可选的,如果有的话,则不管是否发生异常,finally 语句都会被执行。

 

package Nomal_API.APIdemo.ThrowsDemo;

public class tryCatchDemo {
    public static void main(String[] args) {
        System.out.println("开始");
        method();
        System.out.println("结束");
    }

    public static void method() {
//        try中的代码表示正常运行时执行的代码
        try {
            int[] arr = {1, 2, 3};
            System.out.println(arr[3]);
            System.out.println("这里能够访问到吗");
//            如果发生了异常,则执行catch中的代码,【如果发生数组指针越界】
        } catch (ArrayIndexOutOfBoundsException e) {
            System.out.println("你访问的数组索引不存在,请回去修改为正确的索引");
        }
    }
}

注意

  1. 如果 try 中没有遇到问题,怎么执行?

        会把try中所有的代码全部执行完毕,不会执行catch里面的代码

  2. 如果 try 中遇到了问题,那么 try 下面的代码还会执行吗?

        那么直接跳转到对应的catch语句中,try下面的代码就不会再执行了 当catch里面的语句全部执行完毕,表示整个体系全部执行完全,继续执行下面的代码

  3. 如果出现的问题没有被捕获,那么程序如何运行?

        那么try...catch就相当于没有写.那么也就是自己没有处理. 默认交给虚拟机处理.

  4. 同时有可能出现多个异常怎么处理?

        出现多个异常,那么就写多个catch就可以了. 注意点:如果多个异常之间存在子父类关系.那么父类一定要写在下面

Throwable成员方法(应用)

  • 常用方法

    方法名 说明
    public String getMessage() 返回此 throwable 的详细消息字符串
    public String toString() 返回此可抛出的简短描述
    public void printStackTrace() 把异常的错误信息输出在控制台

自定义异常

  • 自定义异常概述

    当Java中提供的异常不能满足我们的需求时,我们可以自定义异常

  • 实现步骤

    1. 定义异常类

    2. 写继承关系

    3. 提供空参构造

    4. 提供带参构造

package Nomal_API.APIdemo.ThrowsDemo;


import java.util.Scanner;

//自定义异常方法 只需要生成空参构造和有参构造
class AgeOutOfBoundsException extends RuntimeException {
    public AgeOutOfBoundsException() {
    }

    public AgeOutOfBoundsException(String message) {
        super(message);
    }
}
//写一个学生类
class Student {
    private String name;
    private int age;

    public Student() {
    }

    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        if (age >= 18 && age <= 25) {
            this.age = age;
        } else {
            //如果Java中提供的异常不能满足我们的需求,我们可以使用自定义的异常
            throw new AgeOutOfBoundsException("年龄超出了范围");
        }
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

public class customExedemo {
    public static void main(String[] args) {
        // 键盘录入学生的姓名和年龄,其中年龄为 18 - 25岁,
        // 超出这个范围是异常数据不能赋值.需要重新录入,一直录到正确为止。

        Student s = new Student();

        Scanner sc = new Scanner(System.in);
        System.out.println("请输入姓名");
        String name = sc.nextLine();
        s.setName(name);
        while (true) {
            System.out.println("请输入年龄");
            String ageStr = sc.nextLine();
            try {
                int age = Integer.parseInt(ageStr);
                s.setAge(age);
                break;
            } catch (NumberFormatException e) {
                System.out.println("请输入一个整数");
                continue;
            } catch (AgeOutOfBoundsException e) {
                System.out.println(e.toString());
                System.out.println("请输入一个符合范围的年龄");
                continue;
            }
           /*if(age >= 18 && age <=25){
               s.setAge(age);
               break;
           }else{
               System.out.println("请输入符合要求的年龄");
               continue;
           }*/
        }
        System.out.println(s);

    }
}

使用异常机制的建议

  要避免使用异常处理代替错误处理,这样会降低程序的清晰性,并且效率低下。

  处理异常不可以代替简单测试---只在异常情况下使用异常机制。

  不要进行小粒度的异常处理---应该将整个任务包装在一个 try 语句块中。

  异常往往在高层处理

 

标签:语句,java,处理,try,catch,机制,异常,public
From: https://www.cnblogs.com/e-link/p/16770509.html

相关文章