[JAVA]异常

目录

1.概念

2.异常的体系结构

3.异常的分类

3.1编译时异常

3.2运行时异常

4.异常的处理

4.1防御式编程

5.异常的抛出

6.异常的捕获

1.异常声明throw

2.try-catch捕获处理

7.finally

8.异常处理的流程

9.自定义异常类


1.概念

在JAVA中,将程序执行过程中发生的不正常的行为称为‘异常’。

而关于异常,也有多种多样的。像是,算术异常,数组越界异常,空指针异常。

2.异常的体系结构

因为异常的种类繁多,为了对于不同的异常或者错误进行了很好的分类。

[JAVA]异常_第1张图片

 他们直接是父类与子类,继承的关系。

可以看到Thorwable是异常体系的顶端,派生出了Errow和Exception两个子类

Errow,指的是Java虚拟机无法解决的严重问题,比如:JVM的内部错误、资源耗尽等。

Exception,异常产生后程序员可以通过代码进行处理,使程序继续执行。

而在这两个子类下又还有许多的子类。

3.异常的分类

异常可能会在编译的时候发生错误,也可能是在运行时发生错误。根据这一情况,异常可以分为‘编译时异常’和‘运行时异常’。

3.1编译时异常

在程序编译期间发生的异常,称为编译时异常,也称为受检查异常(Checked Exception)

3.2运行时异常

在程序执行期间发生的异常,称为运行时异常,也称为非受检查异常(Unchecked Exception)
RunTimeException以及其子类对应的异常,都称为运行时异常。比如:NullPointerException、
ArrayIndexOutOfBoundsException、ArithmeticException

4.异常的处理

4.1防御式编程

LBYL:Look Before You Leap.(事前防御型)

即在每一次的操作之后都对其检查,查看是否发生异常。

EAFP:It's Easier to Ask Forgiveness than Permission.(事后认错型)

即是先把代码运行,当在运行过程种发生错误再捕获异常。

5.异常的抛出

在java中,可以通过throw关键字,抛出一个指定的异常对象,将错误信息更直白的告知

throw new 异常对象("异常的原因")

public class Test {
    public static void Printf(int[] arr){
        if(arr == null){
            throw new NullPointerException("传递的数组为空");
        }
        for (int a:arr
             ) {
            System.out.print(a + " ");
        }
    }
    public static void main(String[] args) {
        int[] arr = {1,2,3,4,5,6,7};
        Printf(null);
    }
}

[JAVA]异常_第2张图片

  •  throw必须放在方法的内部
  • throw抛出的异常对象必须是Exception或者Exception的子类对象
  • 如果抛出的是 RunTimeException 或者 RunTimeException 的子类,则可以不用处理,直接交给JVM来处理
  • 异常一旦抛出,其后的代码就不会执行 

6.异常的捕获

 异常的捕获就是异常的助理方式:

1.异常声明throw

在方法的声明中使用throws关键字抛出,标明此方法有这个异常,但并没有处理此异常,让方法的调用者负责处理。在遇到异常后的代码不会运行

当方法的实现者没能力或不想解决的时候,可以使用throws抛出此异常给调用者解决。

public static void main(String[] args) throws IOException 

当方法调用者遇到这种情况,可以选择处理或继续throws抛出异常 

2.try-catch捕获处理

语法格式:

        try{
            //可能会有异常的代码
            //遇到异常后的代码不会执行
        }catch(要捕获的异常类型 e){
            //如果try的类型与此处的catch匹配
            //则会执行此catch下的代码
        }catch (){
            //catch可以有多个
        }
        //如果catch成功捕获try处的异常,try-catch体系后的代码可以继续正常执行

如果try中出现了异常,且被catch捕获了,则try-catch的后续代码可以继续运行。如果try中出现了异常且没有被catch捕获,则编译器会报错,且后续的代码不会运行。

如果要捕获的异常之间存在子类与父类的关系,那么子类异常的catch一定要写在父类catch的前面。不然会捕获不到,子类的异常。

7.finally

在写程序时,有些特定的代码,不论程序是否发生异常,都需要执行,比如程序中打开的资源:网络连接、数据库连接、IO流等,在程序正常或者异常退出时,必须要对资源进进行回收。另外,因为异常会引发程序的跳转,可能导致有些语句执行不到,finally就是用来解决这个问题的。

语法格式:

        try{
        // 可能会发生异常的代码
        }catch(异常类型 e){
        // 对捕获到的异常进行处理
        }finally{
        // 此处的语句无论是否发生异常,都会被执行到
        }
        //后续的代码看try处的异常是否被catch捕获来决定是否执行

8.异常处理的流程

[JAVA]异常_第3张图片

9.自定义异常类

 示例:

继承RuntimeException表示为运行时异常

如果继承了Exception,默认为受查异常,则要在编译时进行处理,可以在方法中通过关键字throws抛出

import java.security.PrivateKey;
import java.util.Scanner;

class UserNameException extends RuntimeException{//自定义一个类,继承RuntimeException
    public UserNameException(String message) {//带参数的构造方法,
        super(message);
    }
}

class PasswordException extends RuntimeException{//自定义一个类,继承RuntimeException
    public PasswordException(String message) {
        super(message);
    }
}
public class Test {
    public static void Login() {

        String userName = "helloworld";
        String userPassword = "123456789";
        Scanner scanner = new Scanner(System.in);
        System.out.println("请输入用户名:");
        String name = scanner.nextLine();
        System.out.println("请输入密码:");
        String password = scanner.nextLine();
        if(!name.equals(userName)){
            throw new UserNameException("用户名错误");
        }
        if(!password.equals(userPassword)){
            throw new PasswordException("密码错误");
        }
        System.out.println("登录成功");
    }
    public static void main(String[] args){
        try{
            Login();
        }catch (UserNameException e){
            e.printStackTrace();//printStackTrace()方法的意思是:在命令行打印异常信息在程序中出错的位置及原因
        }catch (PasswordException e){
            e.printStackTrace();
        }
    }
}

printStackTrace()方法的意思是:在命令行打印异常信息在程序中出错的位置及原因

你可能感兴趣的:(jvm)