【Java基础】17.异常处理


前言

在 Java 中,异常处理是一种重要的编程概念,用于处理程序执行过程中可能出现的错误或异常情况。
异常是程序中的一些错误,但并不是所有的错误都是异常,并且错误有时候是可以避免的。
比如说,你的代码少了一个分号,那么运行出来结果是提示是错误 java.lang.Error ,如果你用 System.out.println(11/0) ,那么你是因为你用 0 做了除数,会抛出 java.lang.ArithmeticException 的异常。


一、异常的概念

异常是程序在"编译"或者"执行"的过程中可能出现的问题。
异常是应该尽量提前避免的。
异常可能也是无法做到绝对避免的,异常可能有太多情况了,开发中只能提前干预!!
异常一旦出现了,如果没有提前处理,程序就会退出 JVM 虚拟机而终止,开发中异常是需要提前处理的。
研究异常并且避免异常,然后提前处理异常,体现的是程序的安全, 健壮性!!!
Java 会为常见的代码异常都设计一个类来代表。

异常发生的原因有很多,通常包含以下几大类:

  • 用户输入了非法数据。
  • 要打开的文件不存在。
  • 网络通信时连接中断,或者JVM内存溢出。

这些异常有的是因为用户错误引起,有的是程序错误引起的,还有其它一些是因为物理错误引起的。

1.异常的3种类型

  • 检查性异常/编译时异常:继承了Exception,编译阶段就报错,必须处理,否则代码不通过。最具代表的检查性异常是用户错误或问题引起的异常,这些异常在编译时强制要求程序员处理。例如要打开一个不存在文件时,一个异常就发生了,这些异常在编译时不能被简单地忽略。
    这类异常通常使用 try-catch 块来捕获并处理异常,或者在方法声明中使用 throws 子句声明方法可能抛出的异常。
try {
    // 可能会抛出异常的代码
} catch (IOException e) {
    // 处理异常的代码
}

或者

public void readFile() throws IOException {
    // 可能会抛出IOException的代码
}
  • 运行时异常: 继承了RuntimeException,编译阶段不会报错,运行时才可能出现。这些异常在编译时不强制要求处理,通常是由程序中的错误引起的,例如 NullPointerException、ArrayIndexOutOfBoundsException 等,这类异常还是建议提前处理!!
try {
    // 可能会抛出异常的代码
} catch (NullPointerException e) {
    // 处理异常的代码
}
  • 错误: 错误不是异常,而是脱离程序员控制的问题,错误在代码中通常被忽略。例如,当栈溢出时,一个错误就发生了,它们在编译也检查不到的。

编译时异常实例:

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

/**
 * @ClassName: ExceptionDemo
 * @Description: 编译时异常
 * 编译时异常:继承自Exception的异常或者其子类,没有继承RuntimeException
 * 编译时异常是编译阶段就会报错,必须程序员编译阶段就处理的。否则代码编译就报错!!
 * @author: Zh
 * @date: 2024/4/16 21:34
 */
public class ExceptionDemo {
    public static void main(String[] args) throws ParseException {

        String date = "2015-01-12 10:23:21";
        // 创建一个简单日期格式化类:
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM-dd HH:mm:ss");
        SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        // 编译时异常,报错,日期格式不对
        // Exception in thread "main" java.text.ParseException: Unparseable date: "2015-01-12 10:23:21"
        // Date d = sdf.parse(date);
        // System.out.println(d);
        Date d1 = sdf1.parse(date);
        System.out.println(d1);
    }
}

运行时异常实例:

/**
 * @ClassName: ExceptionDemo
 * @Description: 运行时异常
 * 运行时异常的概念:
 * 继承自RuntimeException的异常或者其子类,
 * 编译阶段是不会出错的,它是在运行时阶段可能出现的错误,
 * 运行时异常编译阶段可以处理也可以不处理,代码编译都能通过!!
 * 常见运行时异常:
 * 1.数组索引越界异常: ArrayIndexOutOfBoundsException。
 * 2.空指针异常 : NullPointerException。直接输出没有问题。但是调用空指针的变量的功能就会报错!!
 * 3.类型转换异常:ClassCastException。
 * 4.迭代器遍历没有此元素异常:NoSuchElementException。
 * 5.数学操作异常:ArithmeticException。
 * 6.数字转换异常: NumberFormatException。
 * @author: Zh
 * @date: 2024/4/16 21:38
 */
public class ExceptionDemo {
    public static void main(String[] args) {
        System.out.println("程序开始。。。。。。");

        /** 1.数组索引越界异常: ArrayIndexOutOfBoundsException。*/
        int[] arr = {1, 2, 3}; // 0 1 2
        System.out.println("数组索引越界:" + arr[2]); // 3
        // System.out.println(arr[3]); // 运行出错,程序终止

        /** 2.空指针异常 : NullPointerException。直接输出没有问题。但是调用空指针的变量的功能就会报错!! */
        String name = null;
        System.out.println("空指针:" + name); // null
        // System.out.println(name.length()); // 运行出错,程序终止

        /** 3.类型转换异常:ClassCastException。 */
        Object o = 23;
        Integer i = (Integer) o;
        System.out.println("类型转换:" + i);
        // String s = (String) o;  // 运行出错,程序终止

        /** 5.数学操作异常:ArithmeticException。 */
        int a = 10 / 2;
        System.out.println("数学操作:" + a);
        //int c = 10 / 0; // 运行出错,程序终止

        /** 6.数字转换异常: NumberFormatException。 */
        String number = "23";
        Integer it = Integer.valueOf(number);
        System.out.println("数字转换:" + (it + 1));
        String number1 = "23aabbc";
        // Integer it1 = Integer.valueOf(number1); // 运行出错,程序终止

        System.out.println("程序结束。。。。。");
    }
}

2.支持异常处理的关键字和类

Java 提供了以下关键字和类来支持异常处理:

  • try:用于包裹可能会抛出异常的代码块。
  • catch:用于捕获异常并处理异常的代码块。
  • finally:用于包含无论是否发生异常都需要执行的代码块。
  • throw:用于手动抛出异常。
  • throws:用于在方法声明中指定方法可能抛出的异常。
  • Exception类:是所有异常类的父类,它提供了一些方法来获取异常信息,如 getMessage()、printStackTrace() 等。

二、Exception 类的层次

所有的异常类是从 java.lang.Exception 类继承的子类。
Exception 类是 Throwable 类的子类。除了Exception类外,Throwable还有一个子类Error 。
Java 程序通常不捕获错误。错误一般发生在严重故障时,它们在Java程序处理的范畴之外。
Error 用来指示运行时环境发生的错误。
例如,JVM 内存溢出。一般地,程序不会从错误中恢复。
异常类有两个主要的子类:IOException 类和 RuntimeException 类。
Exception 类的层次

  • Exception:才是异常类,它才是开发中代码在编译或者执行的过程中可能出现的错误,它是需要提前处理的。以便程序更健壮!
  • Error : 错误的意思,严重错误Error,无法通过处理的错误,一旦出现,程序员无能为力了,只能重启系统,优化项目。比如内存奔溃,JVM 本身的奔溃。这个程序员无需理会。

三、内置异常类

Java 语言定义了一些异常类在 java.lang 标准包中。
标准运行时异常类的子类是最常见的异常类。由于 java.lang 包是默认加载到所有的 Java 程序的,所以大部分从运行时异常类继承而来的异常都可以直接使用。
Java 根据各个类库也定义了一些其他的异常。

1.非检查性异常

下面中列出了 Java 的非检查性异常。

  • ArithmeticException:当出现异常的运算条件时,抛出此异常。例如,一个整数"除以零"时,抛出此类的一个实例。
  • ArrayIndexOutOfBoundsException:用非法索引访问数组时抛出的异常。如果索引为负或大于等于数组大小,则该索引为非法索引。
  • ArrayStoreException:试图将错误类型的对象存储到一个对象数组时抛出的异常。
  • ClassCastException:当试图将对象强制转换为不是实例的子类时,抛出该异常。
  • IllegalArgumentException:抛出的异常表明向方法传递了一个不合法或不正确的参数。
  • IllegalMonitorStateException:抛出的异常表明某一线程已经试图等待对象的监视器,或者试图通知其他正在等待对象的监视器而本身没有指定监视器的线程。
  • IllegalStateException:在非法或不适当的时间调用方法时产生的信号。换句话说,即 Java 环境或 Java 应用程序没有处于请求操作所要求的适当状态下。
  • IllegalThreadStateException:线程没有处于请求操作所要求的适当状态时抛出的异常。
  • IndexOutOfBoundsException:指示某排序索引(例如对数组、字符串或向量的排序)超出范围时抛出。
  • NegativeArraySizeException:如果应用程序试图创建大小为负的数组,则抛出该异常。
  • NullPointerException:当应用程序试图在需要对象的地方使用 null 时,抛出该异常。
  • NumberFormatException:当应用程序试图将字符串转换成一种数值类型,但该字符串不能转换为适当格式时,抛出该异常。
  • SecurityException:由安全管理器抛出的异常,指示存在安全侵犯。
  • StringIndexOutOfBoundsException:此异常由 String 方法抛出,指示索引或者为负,或者超出字符串的大小。
  • UnsupportedOperationException:当不支持请求的操作时,抛出该异常。

2.检查性异常类

下面列出了 Java 定义在 java.lang 包中的检查性异常类。

  • ClassNotFoundException:应用程序试图加载类时,找不到相应的类,抛出该异常。
  • CloneNotSupportedException:当调用 Object 类中的 clone 方法克隆对象,但该对象的类无法实现 Cloneable 接口时,抛出该异常。
  • IllegalAccessException:拒绝访问一个类的时候,抛出该异常。
  • InstantiationException:当试图使用 Class 类中的 newInstance 方法创建一个类的实例,而指定的类对象因为是一个接口或是一个抽象类而无法实例化时,抛出该异常。
  • InterruptedException:一个线程被另一个线程中断,抛出该异常。
  • NoSuchFieldException:请求的变量不存在。
  • NoSuchMethodException:请求的方法不存在。

四、异常处理

1.捕获异常

使用 try 和 catch 关键字可以捕获异常。try/catch 代码块放在异常可能发生的地方。

try/catch代码块中的代码称为保护代码,使用 try/catch 的语法如下:

try
{
   // 程序代码
}catch(ExceptionName e1)
{
   //Catch 块
}

Catch 语句包含要捕获异常类型的声明。当保护代码块中发生一个异常时,try 后面的 catch 块就会被检查。
如果发生的异常包含在 catch 块中,异常会被传递到该 catch 块,这和传递一个参数的方法是一样。
实例:

public class ExceptionDemo2 {
    public static void main(String args[]){
        try{
            int a[] = {22,55,88};
            System.out.println("Access element 0 :" + a[0]);
            System.out.println("Access element 1 :" + a[1]);
            System.out.println("Access element 2 :" + a[2]);
            System.out.println("Access element 3 :" + a[3]);
        }catch(ArrayIndexOutOfBoundsException e){
            System.out.println("Exception thrown  :" + e);
        }
        System.out.println("Out of the block");
    }
}

编译运行结果如下:

Access element 0 :22
Access element 1 :55
Access element 2 :88
Exception thrown  :java.lang.ArrayIndexOutOfBoundsException: Index 3 out of bounds for length 3
Out of the block

2.多重捕获块

一个 try 代码块后面跟随多个 catch 代码块的情况就叫多重捕获。
多重捕获块的语法如下所示:

try{
   // 程序代码
}catch(异常类型1 异常的变量名1){
  // 程序代码
}catch(异常类型2 异常的变量名2){
  // 程序代码
}catch(异常类型3 异常的变量名3){
  // 程序代码
}

上面的代码段包含了 3 个 catch块。
可以在 try 语句后面添加任意数量的 catch 块。
如果保护代码中发生异常,异常被抛给第一个 catch 块。
如果抛出异常的数据类型与 ExceptionType1 匹配,它在这里就会被捕获。
如果不匹配,它会被传递给第二个 catch 块。
如此,直到异常被捕获或者通过所有的 catch 块。
实例:

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * @ClassName: ExceptionDemo3
 * @Description: try/catch多重捕获块
 * @author: Zh
 * @date: 2024/4/16 23:00
 */
public class ExceptionDemo3 {
    public static void main(String[] args) {
        System.out.println("程序开始。。。。");
        parseTime2("2023-11-23 23:23:23");
        System.out.println("程序结束。。。。");
    }

    public static void parseTime2(String date) {
        try {
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM-dd HH:mm:ss");
            Date d = sdf.parse(date);
            System.out.println(d);

            InputStream is = new FileInputStream("E:/meinv.jpg");
        } catch (FileNotFoundException e) {
            System.out.println("parseTime2:FileNotFoundException e");
        } catch (ParseException e) {
            System.out.println("parseTime2:ParseException e");
        }
    }
}

编译运行结果如下:

程序开始。。。。
parseTime2:ParseException e
程序结束。。。。

3.throws/throw 关键字

在Java中, throw 和 throws 关键字是用于处理异常的。
throw 关键字用于在代码中抛出异常,而 throws 关键字用于在方法声明中指定可能会抛出的异常类型。

1.throw 关键字

throw 关键字用于在当前方法中抛出一个异常。
通常情况下,当代码执行到某个条件下无法继续正常执行时,可以使用 throw 关键字抛出异常,以告知调用者当前代码的执行状态。
例如,下面的代码中,在方法中判断 num 是否小于 0,如果是,则抛出一个 IllegalArgumentException 异常。

/**
 * @ClassName: ThrowDemo
 * @Description: throw关键字
 * 用于在当前方法中抛出一个异常。
 * @author: Zh
 * @date: 2024/4/16 23:12
 */
public class ThrowDemo {
    public static void main(String[] args) {
        checkNumber(-10);
    }

    public static void checkNumber(int num) {
        if (num < 0) {
            throw new IllegalArgumentException("数字必须为正数。");
        }else {
            System.out.println(num + "是正数。");
        }
    }

}

运行结果如下:

Exception in thread "main" java.lang.IllegalArgumentException: 数字必须为正数。
	at com.itheima.d7_exception_handle.ThrowDemo.checkNumber(ThrowDemo.java:11)
	at com.itheima.d7_exception_handle.ThrowDemo.main(ThrowDemo.java:5)

2.throws 关键字

throws 关键字用于在方法声明中指定该方法可能抛出的异常。当方法内部抛出指定类型的异常时,该异常会被传递给调用该方法的代码,并在该代码中处理异常。

/**
 * @ClassName: ThrowsDemo
 * @Description: throws关键字
 * 用于在方法声明中指定该方法可能抛出的异常。
 * @author: Zh
 * @date: 2024/4/16 23:14
 */
public class ThrowsDemo {
    public static void main(String[] args) {
        try {
            checkAge(-34);
        } catch (IllegalArgumentException e) {
            e.printStackTrace();
        }
    }

    public static void checkAge(int age) throws IllegalArgumentException {
        if (age < 0 || age > 200) {
            // 抛出去一个异常对象给调用者
            // throw :在方法内部直接创建一个异常对象,并从此点抛出
            // throws : 用在方法申明上的,抛出方法内部的异常
            throw new IllegalArgumentException(age + " is illeagal!");
        } else {
            System.out.println("年龄合法:推荐商品给其购买~~");
        }
    }
}

运行结果如下:

java.lang.IllegalArgumentException: -34 is illeagal!
	at com.itheima.d7_exception_handle.ThrowsDemo.checkAge(ThrowsDemo.java:24)
	at com.itheima.d7_exception_handle.ThrowsDemo.main(ThrowsDemo.java:13)

3.finally关键字

finally 关键字用来创建在 try 代码块后面执行的代码块。
无论是否发生异常,finally 代码块中的代码总会被执行。
在 finally 代码块中,可以运行清理类型等收尾善后性质的语句。
finally 代码块出现在 catch 代码块最后,语法如下:

try{
  // 程序代码
}catch(异常类型1 异常的变量名1){
  // 程序代码
}catch(异常类型2 异常的变量名2){
  // 程序代码
}finally{
  // 程序代码
}

实例:

public class FinallyDemo {
    public static void main(String args[]){
        int a[] = new int[2];
        try{
            System.out.println("Access element three :" + a[3]);
        }catch(ArrayIndexOutOfBoundsException e){
            System.out.println("Exception thrown  :" + e);
        }
        finally{
            a[0] = 6;
            System.out.println("First element value: " +a[0]);
            System.out.println("The finally statement is executed");
        }
    }
}

运行结果如下:

Exception thrown  :java.lang.ArrayIndexOutOfBoundsException: Index 3 out of bounds for length 2
First element value: 6
The finally statement is executed

五、编译时异常处理方式

1.编译时异常处理方法1

抛出异常的方式:代表可以抛出一切异常。
抛出异常格式:

方法 throws Exception{}

实例:

import java.io.FileInputStream;
import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * @ClassName: ExceptionDemo01
 * @Description: 编译时异常, 处理方式一
 * 抛出异常格式:
 * 方法 throws 异常1 ,  异常2 , ..{}
 * 建议抛出异常的方式:代表可以抛出一切异常,
 * 方法 throws Exception{}
 * 方式一:
 * 在出现编译时异常的地方层层把异常抛出去给调用者,调用者最终抛出给JVM虚拟机。
 * JVM虚拟机输出异常信息,直接干掉程序,这种方式与默认方式是一样的。
 * 虽然可以解决代码编译时的错误,但是一旦运行时真的出现异常,程序还是会立即死亡!
 * 这种方式并不好!
 * 小结:方式一出现异常层层跑出给虚拟机,最终程序如果真的出现异常,程序还是立即死亡!这种方式不好!
 * @author: Zh
 * @date: 2024/4/16 21:43
 */
public class ExceptionDemo01 {

    public static void main(String[] args) throws Exception {
        System.out.println("程序开始。。。。。");
        parseTime("2011-11-11 11:11:11");
        System.out.println("程序结束。。。。。");
    }

    public static void parseTime(String date) throws Exception {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date d = sdf.parse(date);
        System.out.println(d);

        // 报错:FileNotFoundException,系统找不到指定的路径
        InputStream is = new FileInputStream("E:/meinv.jpg");
    }

}

报错信息:

程序开始。。。。。
Fri Nov 11 11:11:11 CST 2011
Exception in thread "main" java.io.FileNotFoundException: E:\meinv.jpg (系统找不到指定的路径。)
	at java.base/java.io.FileInputStream.open0(Native Method)
	at java.base/java.io.FileInputStream.open(FileInputStream.java:216)
	at java.base/java.io.FileInputStream.<init>(FileInputStream.java:157)
	at java.base/java.io.FileInputStream.<init>(FileInputStream.java:111)
	at com.itheima.d7_exception_handle.ExceptionDemo01.parseTime(ExceptionDemo01.java:38)
	at com.itheima.d7_exception_handle.ExceptionDemo01.main(ExceptionDemo01.java:28)

2.编译时异常处理方法2

在出现异常的地方自己处理,谁出现谁处理。
抛出异常格式:

try{
    // 可能出现异常的代码!
    }catch (Exception e){
    e.printStackTrace(); // 直接打印异常栈信息
    }

实例:

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * @ClassName: ExceptionDemo02
 * @Description: 编译时异常, 处理方式二
 * 方式二:在出现异常的地方自己处理,谁出现谁处理。
 * 自己捕获异常和处理异常的格式:捕获处理
 * 格式:
 * try{
 * // 监视可能出现异常的代码!
 * }catch(异常类型1 变量){
 * // 处理异常
 * }catch(异常类型2 变量){
 * // 处理异常
 * }...
 * 监视捕获处理异常企业级写法:
 * try{
 * // 可能出现异常的代码!
 * }catch (Exception e){
 * e.printStackTrace(); // 直接打印异常栈信息
 * }
 * Exception可以捕获处理一切异常类型!
 * 小结:
 * 第二种方式,可以处理异常,并且出现异常后代码也不会死亡。
 * 这种方案还是可以的。
 * 但是从理论上来说,这种方式不是最好的,上层调用者不能直接知道底层的执行情况!
 * @author: Zh
 * @date: 2024/4/16 22:07
 */
public class ExceptionDemo02 {
    public static void main(String[] args) {
        System.out.println("程序开始。。。。");
        System.out.println("----建议的try catch方式----");
        parseTime("2011-11-11 11:11:11");
        System.out.println("----其他try catch方式----");
        parseTime1("2022-12-22 22:22:22");
        parseTime2("2023-11-23 23:23:23");
        parseTime3("2024-10-24 24:24:24");
        System.out.println("程序结束。。。。");
    }

    /**
     * 建议的try catch方式
     *
     * @param date
     */
    public static void parseTime(String date) {
        try {
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM-dd HH:mm:ss");
            Date d = sdf.parse(date);
            System.out.println(d);

            InputStream is = new FileInputStream("E:/meinv.jpg");
        } catch (Exception e) {
            e.printStackTrace(); // 打印异常栈信息
        }
    }


    public static void parseTime1(String date) {
        try {
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM-dd HH:mm:ss");
            Date d = sdf.parse(date);
            System.out.println(d);

            InputStream is = new FileInputStream("E:/meinv.jpg");
        } catch (FileNotFoundException | ParseException e) {
            System.out.println("parseTime1:FileNotFoundException|ParseException e");
            e.printStackTrace(); // 打印异常栈信息
        }
    }

    public static void parseTime2(String date) {
        try {
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM-dd HH:mm:ss");
            Date d = sdf.parse(date);
            System.out.println(d);

            InputStream is = new FileInputStream("E:/meinv.jpg");
        } catch (FileNotFoundException e) {
            System.out.println("parseTime2:FileNotFoundException e");
            e.printStackTrace(); // 打印异常栈信息
        } catch (ParseException e) {
            System.out.println("parseTime2:ParseException e");
            e.printStackTrace();
        }
    }

    public static void parseTime3(String date) {
        try {
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM-dd HH:mm:ss");
            Date d = sdf.parse(date);
            System.out.println(d);
        } catch (ParseException e) {
            // 解析出现问题
            System.out.println("出现了解析时间异常哦,走点心!!");
        }
        try {
            InputStream is = new FileInputStream("E:/meinv.jpg");
        } catch (FileNotFoundException e) {
            System.out.println("您的文件根本就没有啊,不要骗我哦!!");
        }
    }
}

报错信息:

程序开始。。。。
----建议的try catch方式----
java.text.ParseException: Unparseable date: "2011-11-11 11:11:11"
	at java.base/java.text.DateFormat.parse(DateFormat.java:399)
	at com.itheima.d7_exception_handle.ExceptionDemo02.parseTime(ExceptionDemo02.java:56)
	at com.itheima.d7_exception_handle.ExceptionDemo02.main(ExceptionDemo02.java:41)
java.text.ParseException: Unparseable date: "2022-12-22 22:22:22"
	at java.base/java.text.DateFormat.parse(DateFormat.java:399)
	at com.itheima.d7_exception_handle.ExceptionDemo02.parseTime1(ExceptionDemo02.java:69)
	at com.itheima.d7_exception_handle.ExceptionDemo02.main(ExceptionDemo02.java:43)
java.text.ParseException: Unparseable date: "2023-11-23 23:23:23"
	at java.base/java.text.DateFormat.parse(DateFormat.java:399)
	at com.itheima.d7_exception_handle.ExceptionDemo02.parseTime2(ExceptionDemo02.java:82)
	at com.itheima.d7_exception_handle.ExceptionDemo02.main(ExceptionDemo02.java:44)
----其他try catch方式----
FileNotFoundException|ParseException e
ParseException e
出现了解析时间异常哦,走点心!!
您的文件根本就没有啊,不要骗我哦!!
程序结束。。。。

3.编译时异常处理方法3

在出现异常的地方把异常一层一层的抛出给最外层调用者,最外层调用者集中捕获处理!!(规范做法)
实例:

import java.io.FileInputStream;
import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * @ClassName: ExceptionDemo03
 * @Description: 编译时异常,处理方式三
 * 方式三: 在出现异常的地方把异常一层一层的抛出给最外层调用者,最外层调用者集中捕获处理!!(规范做法)
 * 小结:
 * 编译时异常的处理方式三:底层出现的异常抛出给最外层调用者集中捕获处理。
 * 这种方案最外层调用者可以知道底层执行的情况,同时程序在出现异常后也不会立即死亡,这是
 * 理论上最好的方案。
 * 虽然异常有三种处理方式,但是开发中只要能解决你的问题,每种方式都又可能用到!!
 * @author: Zh
 * @date: 2024/4/16 22:22
 */
public class ExceptionDemo03 {
    public static void main(String[] args) {
        System.out.println("程序开始。。。。");
        try {
            parseTime("2011-11-11 11:11:11");
            System.out.println("功能操作成功~~~");
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println("功能操作失败~~~");
        }
        System.out.println("程序结束。。。。");
    }

    public static void parseTime(String date) throws Exception {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy、MM-dd HH:mm:ss");
        Date d = sdf.parse(date);
        System.out.println(d);

        InputStream is = new FileInputStream("D:/meinv.jpg");
    }

}

报错信息:

程序开始。。。。
java.text.ParseException: Unparseable date: "2011-11-11 11:11:11"
	at java.base/java.text.DateFormat.parse(DateFormat.java:399)
	at com.itheima.d7_exception_handle.ExceptionDemo03.parseTime(ExceptionDemo03.java:35)
	at com.itheima.d7_exception_handle.ExceptionDemo03.main(ExceptionDemo03.java:24)
功能操作失败~~~
程序结束。。。。

六、运行时异常处理方法

可以不处理,编译阶段又不报错。但是按照理论规则:建议还是处理,只需要在最外层捕获处理即可。
实例:

/**
 * @ClassName: Test
 * @Description: 运行时异常,处理方法。
 * 可以不处理,编译阶段又不报错。
 * 按照理论规则:建议还是处理,只需要在最外层捕获处理即可
 * @author: Zh
 * @date: 2024/4/16 22:26
 */
public class Test {
    public static void main(String[] args) {
        System.out.println("程序开始。。。。。。。。。。");
        try {
            chu(10, 0);
        } catch (Exception e) {
            e.printStackTrace();
        }
        System.out.println("程序结束。。。。。。。。。。");
    }

    public static void chu(int a, int b) { // throws RuntimeException{
        System.out.println(a);
        System.out.println(b);
        int c = a / b;
        System.out.println(c);
    }
}

报错信息:

Connected to the target VM, address: '127.0.0.1:14490', transport: 'socket'
程序开始。。。。。。。。。。
10
0
程序结束。。。。。。。。。。
java.lang.ArithmeticException: / by zero
	at com.itheima.d8_exception_handle_runtime.Test.chu(Test.java:25)
	at com.itheima.d8_exception_handle_runtime.Test.main(Test.java:15)
Disconnected from the target VM, address: '127.0.0.1:14490', transport: 'socket'
  • 71
    点赞
  • 37
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值