Java 异常处理

目录

 一、Java异常体系结构

Error 

Exception

受检查异常

未受检查异常

二、异常处理的方式

 1.try-catch块异常处理

注意

2.Throws异常处理

 使用场景

注意

三、异常产生的方式


引言 

Java异常处理是Java语言用于处理程序在执行过程中出现的错误或者异常的机制。通过异常处理,程序可以更加健壮,能够在遇到问题时进行适当处理,而不是直接崩溃。Java异常处理主要依赖于try、catch、finally和 throw/throws 关键字。

 一、Java异常体系结构

Thorwable类是所有异常和错误的父类(超类),有两个字类Error和Exception,分别表示错误和异常(错误一般是程序员无法解决的问题)。

其中,异常类Exception又分为运行时异常(RuntimeException)和非运行时异常。(也可以分类为不检查异常Unchecked Exception 和检查异常Checked Exception)。

Error 

Error表示严重的问题,通常是程序无法恢复的问题。

这些问题通常是虚拟机自身的问题或者其他系统问题,如内存不足,类加载,OutOfMemoryError,ThreadDeath等问题。这些异常发生时,Java虚拟机一般会选择线程终止。

Exception

Exception是程序中可能会遇到的可捕获处理的非致命性问题。Exception分为受检查异常(Checked Exception)和未受检查异常(Unchecked Exception)。

受检查异常

需要在代码中明确声明和处理,如IOException、FileNotFoundException等。编译器会强制要求程序员处理这类异常,要么使用try-catch块捕获,要么在方法签名中使用throws关键字声明抛出。

未受检查异常

通常是运行时异常,继承自RuntimeException类,如NullPointerException、IndexOutOfBoundsException等。这类异常不需要显式捕获和处理,因为它们通常表示程序逻辑错误,应该通过改进程序逻辑来避免。

二、异常处理的方式

 Java异常处理涉及到五个关键字,分别是:try、catch、finally、throw、throws。

 try:用于包裹可能会抛出异常的代码块。

catch:用于捕获try代码块中抛出的异常,并进行处理。

finally:无论是否发生异常,finally代码块中的代码都会被执行。通常用于释放资源,如关闭文件,数据库连接等等。

throw:用于显示的抛出一个异常。

throws:在方法签名中使用,声明该方法可能会抛出的异常。

 1.try-catch块异常处理

示例:

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


public class ExceptionTest {
    public static void main(String[] args) {
        Scanner scanner=new Scanner(System.in);
        try {
            int a=scanner.nextInt();//输入!发生异常,异常后代码不执行,跳转到catch块。
            System.out.println(a);
        }catch (InputMismatchException i){//如果没有异常发生,则顺序执行try块,不会进入catch。
            System.out.println("异常:"+i.getMessage());
        }finally {//如果希望不管是否发生异常,都执行某段代码。
            System.out.println("finally 代码块执行");
        }

    }
}

运行结果:

!
异常:null
finally 代码块执行
注意

1.当有多个catch块用于捕获不同的异常(进行不同的业务),要求父类在后,子类在前,同级别随意。

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

public class ExceptionTest {
    public static void main(String[] args) {
        Scanner scanner=new Scanner(System.in);
        try {
            int[] array={1,2,3,4};
            for (int i = 0; i <=array.length ; i++) {
                System.out.println(array[i]);
            }
        }catch (ArrayIndexOutOfBoundsException a){
            System.out.println("ArrayIndexOutOfBoundsException:"+a.getMessage());
        }
        catch (NullPointerException n){
            System.out.println("NullPointerException:"+n.getMessage());
        }catch (Exception e){
            System.out.println("Exception:"+e.getMessage());
        }finally {
            System.out.println("finally 代码块执行");
        }

    }
}

运行结果:

Java 异常处理_第1张图片

2.如果catch块没有捕获到异常,如果这些异常没有被捕获,它们将会一直传递到程序的顶层,并且通常会导致程序终止,同时在控制台输出异常的堆栈跟踪信息。

public class ExceptionTest {
    public static void main(String[] args) {
        try {
            int[] array={1,2,3,4};
            for (int i = 0; i <=array.length ; i++) {
                System.out.println(array[i]);
            }
        }catch (NullPointerException a){
            System.out.println("ArrayIndexOutOfBoundsException:"+a.getMessage());
        }finally {
            System.out.println("finally 代码块执行");
        }

    }
}

运行结果:

Java 异常处理_第2张图片

3.try - finally 可以配合使用,这种用法相当于没有捕获异常。应用场景:执行一段代码,不管是否发生异常,都必须执行某个业务逻辑。

 4.如果catch块中和finally中都有return代码,该返回那个呢?

在Java中,如果catch块和finally块中都有return语句,那么finally块中的return语句将会被执行,并且它的返回值将会覆盖catch块中的返回值。

这意味着,即使catch块中有一个return语句,如果在finally块中也存在一个return语句,那么最终返回给调用者的值将是finally块中return语句所指定的值。

public class ReturnInCatchFinally {
    public static void main(String[] args) {
        System.out.println(testMethod());
    }

    public static int testMethod() {
        try {
            throw new Exception("Test Exception");
        } catch (Exception e) {
            System.out.println("Caught an exception");
            return 1; // 这个return值会被finally块中的return覆盖
        } finally {
            System.out.println("Inside finally");
            return 2; // 这个return值会最终被返回
        }
    }
}

2.Throws异常处理

如果一个方法中的语句执行时,可能会产生某种异常,但是不能确定如何处理这种异常,则此方法应该显示地声明抛出异常,该方法不对其进行处理,而由该方法的调用者负责处理。如果所有方法都层层上抛获取的代码,最终JVM会进行处理,处理也很简单,就是打印异常消息和堆栈消息。

 使用场景

1.方法内可能抛出的受检异常(在编译时就需要处理的异常)。如果方法内部可能会抛出受检异常,但该方法又不希望或无法自行处理这些异常,那么可以在方法签名中使用throws关键字声明这些异常。

2.自定义异常。当用户自定义了自己的异常,如果某个方法可能会抛出这些自定义异常(throw),也可以使用throws关键字在方法中签名。

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


public class ExceptionTest {
    public static void main(String[] args){
        try {
            a();
        }catch (Exception e){
            e.printStackTrace();
        }
        System.out.println(111);
    }
    public static void a()throws RuntimeException,Exception{
        Scanner scanner=new Scanner(System.in);
        int a=scanner.nextInt();
    }
}

运行结果: 

Java 异常处理_第3张图片

注意

子类重写的方法抛出的异常类型不大于(<=)父类被重写方法抛出的异常类型 。

子类重写的方法不能:

  • 声明抛出新的、与父类方法抛出异常无关的异常类型。
  • 声明抛出比父类方法更宽泛的异常类型(即父类异常类型的超类)。

三、异常产生的方式

1.系统自动生成的异常对象

2.手动生成异常对象并抛出(throw) 

class StudentTest {
    public static void main(String[] args) {
        try {
            Student s = new Student();
            //数据非法,需要处理异常对象
            //调用此方法进入到catch代码块中
            s.regist(-1001);
        } catch (Exception e) {
            //控制台输出:您输入的数据非法
            System.out.println(e.getMessage());
        }
    }
}

class Student{
    private int id;
    public void regist(int id) throws Exception {
        if (id > 0){
            this.id = id;
        }else {
            //手动抛出异常对象
            throw new Exception("您输入的数据非法!");
        }
    }
}

面试题:throw和throws区别? 

throw表示抛出一个异常对象,生成异常对象的过程。声明在方法体内

throws属于异常处理的一种方式,声明在方法的声明处

一个是生成异常,一个是处理异常。 

你可能感兴趣的:(Java进阶,java,开发语言)