Java基础-day17

异常处理和文本I/O

Java 可以让一个方法可以抛出一个异常 ,该异常可以被调用者捕获和处理 。

try-throw-catch

import java.util.Scanner;

public class QuotientWithException {
    public static int quotient(int number1, int number2){
        if(number2 == 0)
            throw new ArithmeticException("Divisor cannot be zero");
        return number1 / number2;
    }

    public static void main(String[] args) {
        Scanner input = new Scanner(System.in);
        System.out.println("Enter two integers:");
        int number1 = input.nextInt();
        int number2 = input.nextInt();

        try {
            int result = quotient(number1, number2);
            System.out.println(number1 + " / " + number2 + " = " + result);
        }

        catch (ArithmeticException ex){
            System.out.println("Exception: an integer " +
                    "cannot be divided by zero ");
        }
        System.out.println("Execution continues...");
    }
}
Enter two integers:
5 0
Exception: an integer cannot be divided by zero 
Execution continues...
Enter two integers:
3 2
3 / 2 = 1
Execution continues...

语句

throw new ArithmeticException("Divisor cannot be zero");
  1. 通过异常类java.lang.ArithemeticException创建一个异常类对象,从而抛出异常
  2. 当异常抛出后,正常的执行流程被中断
  3. 抛出异常就是将异常从一个地方传递到另一个地方
  4. try 块包含了正常情况下执行的代码
  5. 异常被catch 块所捕获 。 catch块中的代码执行以处理异常
  6. throw 语句类似于方法的调用 , 但不同于调用方法的是
    • 它调用的是 catch 块
    • 在执行完 catch 块之后 , 程序控制不返回到 throw 语句;而是执行 catch 块后的下一
      条语句

异常处理最根本的优势就是将检测错误(由被调用的方法完成)从处理错误(由调用方法完成)中分离出来 。

很多库方法都会抛出异常

import java.util.InputMismatchException;
import java.util.Scanner;

public class InputMismatchExceptionDemo {
    public static void main(String[] args) {
        Scanner input = new Scanner(System.in);
        boolean continueInput = true;

        do {
            try {
                System.out.println("Enter an integer:");
                int number = input.nextInt();
                System.out.println("The number entered is " + number);
                continueInput = false;
            }
            catch (InputMismatchException ex){
                System.out.println("Try again.");
                input.nextLine();       // 丢弃当前输入行
            }

        }while (continueInput);
    }
}

Enter an integer:
3.00
Try again.
Enter an integer:
0
The number entered is 0

异常类型

异常是对象 , 而对象都采用类来定义 。 异常的根类是 java.lang.Throwable

Snipaste_2020-04-22_14-28-27

Throwable类是所有异常类的根 。 所有的 Java 异常类都直接或者间接地继承自Throwable 。 可以通过继承 Exception 或者 Exception 的子类来**创建自己的异常类 **

RuntimeExceptionError 以及它们的子类都称为免检异常 ( unchecked exception ) 。 所有其他异常都称为必检异常 ( checked exception ) , 意思是指编译器会强制程序员检査并通过 try - catch 块处理它们 , 或者在方法头进行声明

关于异常处理的更多知识

Java异常处理的三种操作:

  1. 声明一个异常
  2. 抛出一个异常
  3. 捕获一个异常

Snipaste_2020-04-22_14-37-59

声明异常

方法要拋出的其他异常都必须在方法头中显式声明 , 这样 , 方法的调用者会被告知有异常

public void myMethod() throws IOException

关键字 throws 表明 myMethod 方法可能会抛出异常IOException。如果方法可能会抛出多个异常, 就可以在关键字 throws 后添加一个用逗号分隔的异常列表

public void myMethod()
    throws Exception1, Exception2, ..., ExceptionN

如果方法没有在父类中声明异常 , 那么就不能在子类中对其进行继承来声明异常

抛出异常

检测到错误的程序可以创建一个合适的异常类型的实例并抛出它 , 这就称为抛出一个异常。假如程序发现传递给方法的参数与方法的合约不符 ( 例如 , 方法中的参数必须是非负的 , 但是传入的是一个负参数 ) , 这个程序就可以创建 IllegalArgumentException 的一个实例并抛出它

IllegalArgumentException ex = 
    new IllegalArgumentException("Wrong Argument");
throw ex;
或者表示为:
    
throw new IllegalArgumentException("Wrong Argument");

捕获异常

当抛出一个异常时 , 可以在try - catch块中捕获和处理它

try{
    statements;
}
catch(Exception1 exVar1){
    handler for exception1;
}
catch(Exception2 exVar2){
    handler for exception2;
}
...
catch(ExceptionN exvarN){
    handler for exceptionN;
}

如果在执行 try 块的过程中没有出现异常 , 则跳过 catch 子句

如果 try 块中的某条语句抛出一个异常 , Java 就会跳过 try 块中剩余的语句 , 然后开始査找处理这个异常的代码的过程

Snipaste_2020-04-22_15-07-06

Snipaste_2020-04-22_15-07-16

注意

  1. 从一个通用的父类可以派生出各种异常类 。 如果一个 catch 块可以捕获一个父类的异常对象,它就能捕获那个父类的所有子类的异常对象 。
  2. 在 catch 块中异常被指定的顺序是非常重要的。 如果父类的 catch 块出现在子类的catch 块之前 , 就会导致编译错误
Snipaste_2020-04-22_15-11-30
  1. Java 强迫程序员处理必检异常
Snipaste_2020-04-22_15-15-28
  1. 对于使用同样的处理代码处理多个异常的情况 , 可以使用新的 JDK 7 的多捕获特征( multi - catch feature ) 简化异常的代码编写
catch(Exception1|Exception2|...|ExceptionN ex){ // 如果其中一个异常被捕获,则执行处理的代码
    // Same code for handling these exceptions;	
}

从异常中获取信息

可以利用下面这些java.lang.Throwable类中的实例方法获取有关异常的信息

Snipaste_2020-04-22_15-45-00

实例

Snipaste_2020-04-22_15-54-54Snipaste_2020-04-22_15-55-01

Snipaste_2020-04-22_15-55-17

finally子句

无论异常是否产生 , finally 子句总是会被执行的

try{
    statements;
}
catch(TheException ex){
    handling ex;
}
finally{
    finalStatements;
}
Snipaste_2020-04-22_16-17-35

何时使用异常

当错误需要被方法的调用者处理的时候 , 方法应该抛出一个异常 。

try 块包含正常情况下执行的代码 。 catch 块包含异常情况下执行的代码 。 异常处理将错误处理代码从正常的程序设计任务中分离出来 , 这样 , 可以使程序更易读 、 更易修改

不要用 try - catch 块处理简单的 、 可预料的情况

重新抛出异常

如果异常处理器不能处理一个异常 , 或者只是简单地希望它的调用者注意到该异常 , Java 允许该异常处理器重新抛出异常 。

Snipaste_2020-04-22_16-27-30

链式异常

catch 块重新抛出原始的异常 。 有时候,可能需要同原始异常一起抛出一个新异常(带有附加信息), 这称为链式异常

Snipaste_2020-04-22_16-34-20

main方法调用 method1()( 第 4 行 ), method1调用 method2 ( 第 13 行 ) , method2 拋出一
个异常 ( 第 21 行 ) 。 该异常被 method1的 catch 块所捕获 , 并在第 16 行被包装成一个新异
常 。 该新异常被抛出 , 并在 main 方法中的 catch 块中被捕获 ( 第 6 行 ) 。 示例输出在第 7 行中 printStackTrace() 方法的结果 。 首先 , 显示从 method1中抛出的新异常 , 然后显示从
method 2 中抛出的原始异常

创建自定义异常类

可以通过派生 java.lang.Exception 类来定义一个自定义异常类

Snipaste_2020-04-22_16-49-06

要创建一个InvalidRachusExMption类 , 必须传递一个半径 。

Snipaste_2020-04-22_16-50-24

Write by Gqq

原文地址:https://www.cnblogs.com/zgqcn/p/12820910.html