栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

(9) javaSE --异常

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

(9) javaSE --异常

目录

1、Java的异常

1.1 异常的分类1.2 防御式编程 2、 异常的用法

2.1 上菜2.2 菜不够?2.3 加个蛋? 3、 声明 和 抛出异常4、RuntimeException (重点)5、自定义异常

1、Java的异常


小伙子,别跑啊。。。。

上面是Java内置异常类之间的继承关系

1.1 异常的分类

1. 粉红色的是受检查的异常(checked exceptions) — 编译时异常

其必须被 try{}catch语句块所捕获,或者在方法签名里通过throws子句声明.
受检查的异常必须在编译时被捕捉处理,命名为 Checked Exception
是因为Java编译器要进行检查,Java虚拟机也要进行检查,以确保这个规则得到遵守.

编译时异常强制进行异常处理,否则就无法编译通过

2. 绿色的异常是 非受检查异常 — 运行时异常 (runtime exceptions)

运行时才会发生异常,需要程序员自己分析代码决定是否捕获和处理,比如 空指针,被0除...
使用RuntimeException定义的异常可以由用户选择性的来进行异常处理。

3. 声明为Error

则属于严重错误,如系统崩溃、虚拟机错误、动态链接失败等,
这些错误无法恢复或者不可能捕捉,将导致应用程序中断,Error 无需我们关心,不需要捕捉。

我们常常所说的异常,本质上是 程序在 运行时 出现错误时通知调用者的一种机制。
即 运行时异常。

运行时

运行时指的是程序已经编译通过得到 class 文件了, 再由 JVM 执行过程中出现的错误

那为啥是出错了才通知,而不是提前预防呢?

1.2 防御式编程

代码不出问题,基本上是不存在的,我们所能做的就是,防止出错

LBYL

 Look Before You Leap. 在操作之前就做充分的检查.

EAFP:

It's Easier to Ask Forgiveness than Permission. "事后获取原谅比事前获取许可更容易". 
也就是先操作, 遇到问题再处理。

所以说异常的思想是,遇到问题再解决,不然,就没万事大吉。

说的这么牛逼轰轰的,咋用呢?

2、 异常的用法 2.1 上菜

不管异常是否发生,finally块均会被执行。

import java.util.Scanner;

public class Test1 {

    private int a = 0;
    private int[] arr;
    private int input;
    public void  arithmetic(){
        Scanner scanner = new Scanner(System.in);
        try {
            // 1、try中存放可能会发生异常的代码
            input = scanner.nextInt();
            System.out.println("---1 start try ---");
            System.out.println("Step 1: 1/0 " + input / this.a);
            System.out.println("Step 2:");
            System.out.println("---1 end try ---");
        } catch (ArithmeticException e){  // catch 括号中放入可能出现的异常类型和异常对象
            // 2、catch代码块放入处理异常的代码
            //    并且只能处理对应种类的异常
            // 打印出现异常的调用栈
            e.printStackTrace();
            this.a += 1;
            System.out.println("Step catch 1: " + input / this.a);
        } finally {
            
            scanner.close();
            System.out.println("不管是否发生异常, finally块均会被执行");
        }


    }

    public void  printArr(){
        arr = new int[]{ 1, 2, 3, 4};
        arr = null;
        try {
            System.out.println("---2 start try ---");
            System.out.println("Step 1: " + arr[100]);
            System.out.println("---2 end try ---");
        } catch (NullPointerException e){
             // 3、catch 括号中放入可能出现的异常类型和异常对象,并且只能处理对应种类的异常
            // arr = null ,
            // try代码执行时,会发生 空指针异常
            e.printStackTrace();
            System.out.println("Step catch 1: NullPointerException e ");
        } catch (ArrayIndexOutOfBoundsException|ArithmeticException e) {
            // 4、如果有多个异常的处理方式相同,则可以用 | 进行连接
            e.printStackTrace();
            System.out.println("Step catch 2: ArrayIndexOutOfBoundsException e ");
        }

        //5、也可以使用一个catch Exception类 捕获所有的异常 ,因为 Exception 类是所有异常类的父类,
        catch (Exception e) {
            e.printStackTrace();
            System.out.println("使用 Exception 捕获所有异常");
        }
    }
    
}

2.2 菜不够?

那我要是 在catch 括号中放入的异常类型 不是 实际出现异常的类型,
导致catch 无法捕获, 那 finally还会执行吗?

不管异常是否发生,finally块均会被执行。

public void  arithmetic1(){
    Scanner scanner = new Scanner(System.in);
    try {
        input = scanner.nextInt();
        System.out.println("Step 1: 1/0 " + input / this.a);
    } catch (NullPointerException e){  // catch 括号中放入可能出现的异常类型和异常对象
        // 正确异常类型      
        // ArithmeticException e 
        // NullPointerException 无法捕捉
     
        e.printStackTrace();
        this.a += 1;
        System.out.println("Step catch 1: " + input / this.a);
    } finally {
        
        scanner.close();
        System.out.println("不管是否发生异常, finally块均会被执行");
    }
}

如果本方法没有对应的处理异常的方式,就无法在当前方法中捕获到异常,就会沿着调用栈向上传递
如果向上一直传递到main方法也都没有对应的异常处理方式,最终就会交给JVM处理,程序就会终止异常
2.3 加个蛋?

我直接在catch中 return, finally 还会执行吗?

不管异常是否发生,finally块均会被执行。

不敲code行不行? 行。

public int  arithmetic1(){
    Scanner scanner = new Scanner(System.in);
    try {
        input = scanner.nextInt();
        System.out.println("Step 1: 1/0 " + input / this.a);
        return input / this.a;
    } catch (NullPointerException e){  // catch 括号中放入可能出现的异常类型和异常对象
        // 正确异常类型
        // ArithmeticException e
        // NullPointerException 无法捕捉

        e.printStackTrace();
        this.a += 1;
        System.out.println("Step catch 1: " + input / this.a);
    } finally {
        
        scanner.close();
        System.out.println("不管是否发生异常, finally块均会被执行,那我要是在try中return, finally还会执行吗?");
        return 10;
    }
}
3、 声明 和 抛出异常

声明异常: throws 关键字

我是社畜

抛出异常: throw 关键字

滚犊子,你就是个社畜

捕获异常: catch

抓住这个社畜

1. throw用于方法内部,主要表示手动产生异常类对象抛出,而非JVM抛出。

2. throws主要在方法声明上使用,明确告诉用户本方法可能产生的异常,同时该方法可能不处理此异常。

在进行方法定义的时候,
如果要告诉调用者  本方法可能产生哪些异常,就可以使用throws方法进行声明。
即,如果该方法出现问题后不希望自行处理,就使用throws抛出。


如果现在调用了throws声明的方法,那么在调用时必须明确的使用try..catch..进行捕获,
因为该方法有可能产生异常,所以必须按照异常的方式来进行处理。


Main方法本身也属于一个方法,所以主方法上也可以使用throws进行异常抛出,
这个时候如果产生了异常就会交给JVM处理。

throw是直接编写在语句之中,表示人为进行异常的抛出。
如果现在异常类对象实例化不希望由JVM产生而由用户产生,就可以使用throw来完成

4、RuntimeException (重点)
public class Test {public static void main(String[] args){
    String str = "100" ;
    int num = Integer.parseInt(str) ;
    System.out.println(num * 2);
}

这个方法上已经明确抛出异常,但是在进行行调用的时候发现,即使没有进行异常处理也可以正常执行。这个就属于RuntimeException的范畴。
很多的代码上都可能出现异常,例如"10/0"都可能产生异常,如果所有可能产生异常的地方都强制性异常处理理,这个代码就太复杂了。
所以在异常设计的时候,考虑到一些异常可能是简单问题,所以将这类异常称为RuntimeException,也就是使用RuntimeException定义的异常类可以不需要强制性进行异常处理理。

5、自定义异常

在Java里,针对于可能出现的公共的程序问题都会提供有相应的异常信息,
但是很多时候这些异常信息往不不够我们使用。

例如,现在有需求:

在进行加法运算时,如果发现两个数相加内容为50,那么就应当抛出一个AddException异常。
这种异常Java不会提供,所以就必须定义一个属于自己的异常类。

自定义异常类可以继承两种父类: Exception、 RuntimeException。

class AddException extends Exception{
    public AddException(String message) {
        super(message);
    }
}

class MyNullPointerException extends  RuntimeException{
    public MyNullPointerException(String message) {
        super(message);
    }
}

public class TestException {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int excep = scanner.nextInt();
        try {
            if(excep == 1) {
                throw new MyNullPointerException("抛出自定义 MyNullPointerException!");
            } else {
                throw new AddException("抛出自定义 AddException!");
            }
        } catch (MyNullPointerException e) {
            e.printStackTrace();
        } catch (AddException e) {
            e.printStackTrace();
        }
    }
}

AddException: 抛出自定义 AddException!
	at Main.main(Main.java:22)
 
MyNullPointerException: 抛出自定义 MyNullPointerException!
	at Main.main(Main.java:28)

倘若不对继承自 Exception的异常进行捕获,最终会报错,
因为继承自Exceptionde的异常属于编译异常,受异常检查,必须捕获。

对于继承自 RuntimeException,异常若在方法栈调用中没有没有处理,最终会被JVM处理。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/778319.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号