java异常学习

首先,我们在写代码的时候,对于一些可能会出现空指针,类型转换时会使用try catch,我们需要明白,它的作用是什么?

举例:

1:无try catch
public static void main(String[] args) {
String i = "";

int ii = Integer.ValueOf(i)
System.out.println(ii);    
System.out.println(1111111111);    

}

运行结果:不会输出111111111,因为在将i的转换为String类型时,出现了异常

2:有try catch
public static void main(String[] args) {
int ii;
try {
String i = "";

int ii = Integer.ValueOf(i)
System.out.println(i);
} catch (Exception e) {
e.printStackTrace();
}    
System.out.println(1111111111);    
}
运行结果:会输出1111111,因为在异常出现时,已经对异常进行了补获,所以会继续向下执行。下面我具体来学习下java中异常的相关知识。

 

一、异常的概述和分类


    * A:异常的概述:    异常就是Java程序在运行过程中出现的错误。
    * B:异常的分类:    Exception 和 Error
    * C:异常的继承体系
        * 异常的基类:    Throwable
        * 严重问题:    Error    不予处理,因为这种问题一般是很严重的问题,比如: 内存溢出
        * 非严重问题:    Exception
            * 编译时异常:  非RuntimeException:RuntimeException以外的异常,类型上都属于Exception类及其子类。从程序语法角度讲是必须进行处理的异常,如果不处理,程序就不能编译通过。如IOException、SQLException等以及用户自定义的Exception异常,一般情况下不自定义检查异常。[博客](https://github.com/yangchong211/YCBlogs)

            * 运行时异常:  RuntimeException,如NullPointerException(空指针异常)、IndexOutOfBoundsException(下标越界异常)等,这些异常是不检查异常,程序中可以选择捕获处理,也可以不处理。这些异常一般是由程序逻辑错误引起的,程序应该从逻辑角度尽可能避免这类异常的发生。运行时异常的特点是Java编译器不会检查它,也就是说,当程序中可能出现这类异常,即使没有用try-catch语句捕获它,也没有用throws子句声明抛出它,也会编译通过。

二、异常特点区别

- Exception
    -  1.可以是可被控制(checked) 或不可控制的(unchecked)。
    -  2.表示一个由程序员导致的错误。
    -  3.应该在应用程序级被处理。
- Error
    -  1.总是不可控制的(unchecked)。
    -  2.经常用来用于表示系统错误或低层资源的错误。
    -  3.如何可能的话,应该在系统级被捕捉。
- 概括
    - 异常和错误的区别:异常能被程序本身可以处理,错误是无法处理。

三.Throwable类常用方法


- Throwable类中的常用方法
- 注意:catch关键字后面括号中的Exception类型的参数e。Exception就是try代码块传递给catch代码块的变量类型,e就是变量名。catch代码块中语句"e.getMessage();"用于输出错误性质。通常异常处理常用3个函数来获取异常的有关信息:
    - getCause():返回抛出异常的原因。如果 cause 不存在或未知,则返回 null。
    - getMeage():返回异常的消息信息。
    - printStackTrace():对象的堆栈跟踪输出至错误输出流,作为字段 System.err 的值。

四、异常处理关键字

- Java异常机制用到的几个关键字:**try、catch、finally、throw、throws。**
    - • **try**        -- 用于监听。将要被监听的代码(可能抛出异常的代码)放在try语句块之内,当try语句块内发生异常时,异常就被抛出。
    - • **catch**   -- 用于捕获异常。catch用来捕获try语句块中发生的异常。
    - • **finally**  -- finally语句块总是会被执行。它主要用于回收在try块里打开的物理资源(如数据库连接、网络连接和磁盘文件)。只有finally块,执行完成之后,才会回来执行try或者catch块中的return或者throw语句,如果finally中使用了return或者throw等终止方法的语句,则就不会跳回执行,直接停止。
    - • **throw**   -- 用于抛出异常。
    - • **throws** -- 用在方法签名中,用于声明该方法可能抛出的异常。

、异常Exception类型

1.算术条件异常(譬如:整数除零等):java.lang.ArithmeticException
2. 数组索引越界异常。当对数组的索引值为负数或大于等于数组大小时抛出:java.lang.ArrayIndexOutOfBoundsException
3.数组存储异常。当向数组中存放非数组声明类型对象时抛出:java.lang.ArrayStoreException
4. 强制类型转换异常。假设有类A和B(A不是B的父类或子类),O是A的实例,那么当强制将O构造为类B的- 实例时抛出该异常。该异常经常被称为强制类型转换异常:java.lang.ClassCastException
5.找不到类异常。当应用试图根据字符串形式的类名构造类,而在遍历CLASSPAH之后找不到对应名称的class文件时,抛出该异常:java.lang.ClassNotFoundException

6.不支持克隆异常。当没有实现Cloneable接口或者不支持克隆方法时,调用其clone()方法则抛出该异常:java.lang.CloneNotSupportedException
7. 枚举常量不存在异常。当应用试图通过名称和枚举类型访问一个枚举对象,但该枚举对象并不包含常量时,抛出该异常:java.lang.EnumConstantNotPresentException
8.根异常。用以描述应用程序希望捕获的情况:java.lang.Exception
9.违法的访问异常。当应用试图通过反射方式创建某个类的实例、访问该类属性、调用该类方法,而当时又无法访问类的、属性的、方法的或构造方法的定义时抛出该异常:java.lang.IllegalAccessException
10.违法的监控状态异常。当某个线程试图等待一个自己并不拥有的对象(O)的监控器或者通知其他线程等待该对象(O)的监控器时,抛出该异常:java.lang.IllegalMonitorStateException

11.违法的状态异常。当在Java环境和应用尚未处于某个方法的合法调用状态,而调用了该方法时,抛出该异常:java.lang.IllegalStateException
12. 违法的线程状态异常。当线程尚未处于某个方法的合法调用状态,而调用了该方法时,抛出异常:java.lang.IllegalThreadStateException
13.索引越界异常。当访问某个序列的索引值小于0或大于等于序列大小时,抛出该异常:java.lang.IndexOutOfBoundsException
14. 实例化异常。当试图通过newInstance()方法创建某个类的实例,而该类是一个抽象类或接口时,抛出该异常:java.lang.InstantiationException
15.被中止异常。当某个线程处于长时间的等待、休眠或其他暂停状态,而此时其他的线程通过Thread的interrupt方法终止该线程时抛出该异常:java.lang.InterruptedException
16. 数组大小为负值异常。当使用负数大小值创建数组时抛出该异常:java.lang.NegativeArraySizeException
17. 属性不存在异常。当访问某个类的不存在的属性时抛出该异常:java.lang.NoSuchFieldException
18. 方法不存在异常。当访问某个类的不存在的方法时抛出该异常:java.lang.NoSuchMethodException
空指针异常。当应用试图在要求使用对象的地方使用了null时,抛出该异常。譬如:调用null对象的实例方法、访问null对象的属性、计算null对象的长度、使用throw语句抛出null等等:java.lang.NullPointerException
19.数字格式异常。当试图将一个String转换为指定的数字类型,而该字符串确不满足数字类型要求的格式时,抛出该异常:java.lang.NumberFormatException
20. 运行时异常。是所有Java虚拟机正常操作期间可以被抛出的异常的父类:java.lang.RuntimeException
21.安全异常。由安全管理器抛出,用于指示违反安全情况的异常:java.lang.SecurityException
22.符串索引越界异常。当使用索引值访问某个字符串中的字符,而该索引值小于0或大于等于序列大小时,抛出该异常:java.lang.StringIndexOutOfBoundsException
23. 类型不存在异常。当应用试图以某个类型名称的字符串表达方式访问该类型,但是根据给定的名称又找不到该类型是抛出该异常。该异常与ClassNotFoundException的区别在于该异常是unchecked(不被检查)异常,而ClassNotFoundException是checked(被检查)异常:java.lang.TypeNotPresentException
24.不支持的方法异常。指明请求的方法不被支持情况的异常:java.lang.UnsupportedOperationException 

 

六、try catch使用

1. try...catch处理异常的基本格式
    try    {
        可能出现问题的代码 ;
    }catch(异常名 变量名){
        针对问题的处理 ;
    }finally{
        释放资源;
    }
    ```
- 作用说明
    - try 块:用于捕获异常。其后可接零个或多个catch块,如果没有catch块,则必须跟一个finally块。
    - catch 块:用于处理try捕获到的异常。[博客](https://github.com/yangchong211/YCBlogs)
    - finally 块:无论是否捕获或处理异常,finally块里的语句都会被执行。有些情况则不会执行,下面会说到。

2.try...catch注意事项
- 注意事项:
    * a:try中的代码越少越好
    * b:catch中要做处理,哪怕是一条输出语句也可以.(不能将异常信息隐藏)
    * c:处理多个异常
        * 1:能明确的尽量明确,不要用大的来处理。[博客](https://github.com/yangchong211/YCBlogs)
        * 2:平级关系的异常谁前谁后无所谓,如果出现了子父关系,父必须在后面。

3.try-catch-finally规则
- try-catch-finally规则如下所示:
    - 1) 必须在 try 之后添加 catch 或 finally 块。try 块后可同时接 catch 和 finally 块,但至少有一个块。
    - 2) 必须遵循块顺序:若代码同时使用 catch 和 finally 块,则必须将 catch 块放在 try 块之后。
    - 3) catch 块与相应的异常类的类型相关。
    - 4) 一个 try 块可能有多个 catch 块。若如此,则执行第一个匹配块。即Java虚拟机会把实际抛出的异常对象依次和各个catch代码块声明的异常类型匹配,如果异常对象为某个异常类型或其子类的实例,就执行这个catch代码块,不会再执行其他的 catch代码块
    - 5) 可嵌套 try-catch-finally 结构。
    - 6) 在 try-catch-finally 结构中,可重新抛出异常。


4.try...catch语句块的执行顺序
- try-catch-finally的语句块的执行顺序:
    - 1)当try没有捕获到异常时:try语句块中的语句逐一被执行,程序将跳过catch语句块,执行finally语句块和其后的语句;
    - 2)当try捕获到异常,catch语句块里没有处理此异常的情况:当try语句块里的某条语句出现异常时,而没有处理此异常的catch语句块时,此异常将会抛给JVM处理,finally语句块里的语句还是会被执行,但finally语句块后的语句不会被执行;
    - 3)当try捕获到异常,catch语句块里有处理此异常的情况:在try语句块中是按照顺序来执行的,当执行到某一条语句出现异常时,程序将跳到catch语句块,并与catch语句块逐一匹配,找到与之对应的处理程序,其他的catch语句块将不会被执行,而try语句块中,出现异常之后的语句也不会被执行,catch语句块执行完后,执行finally语句块里的语句,最后执行finally语句块后的语句;

七、throws的用法介绍


- throws的具体使用规则
    * 用在方法声明后面,跟的是异常类名
    * 可以跟多个异常类名,用逗号隔开
    * 表示抛出异常,由该方法的调用者来处理
    * throws表示出现异常的一种可能性,并不一定会发生这些异常
    ```
    static void pop() throws NegativeArraySizeException {
        // 定义方法并抛出NegativeArraySizeException异常
        int[] arr = new int[-3]; // 创建数组
    }
    
    public static void main(String[] args) { // 主方法
        try { // try语句处理异常信息
            pop(); // 调用pop()方法
        } catch (NegativeArraySizeException e) {
            System.out.println("pop()方法抛出的异常");// 输出异常信息
        }
    }
    
    使用throws关键字将异常抛给调用者后,如果调用者不想处理该异常,可以继续向上抛出,但最终要有能够处理该异常的调用者。
    pop方法没有处理异常NegativeArraySizeException,而是由main函数来处理。

八、throw的用法介绍


- throw的一般形式如下所示
    ```
    throw ThrowableInstance
    ```
    - ThrowableInstance必须是Throwable或其子类类型的对象。throw语句之后的执行流程会立即停止,所有的后续语句都不会执行,
    然后按顺序依次检查所有的catch语句,检查是否和异常类型相匹配。如果没有找到匹配的catch语句,那么默认的异常处理程序会终止程序并输出堆栈踪迹。
    - 例如,运行以下代码,将得到输出结果:“NullPointerException”
        ```
        public class Demo {
            public static void demo(){
                throw new NullPointerException("NullPointer");
            }
        
            public static void main(String[] args) {
                try{
                    demo();
                }catch (NullPointerException e) {
                    System.out.println("NullPointerException");
                }
            }
        }

九、throws和throw区别


    * throws的方式处理异常: 定义功能方法时,需要把出现的问题暴露出来让调用者去处理。那么就通过throws在方法上标识。
    * throw的概述: 在功能方法内部出现某种情况,程序不能继续运行,需要进行跳转时,就用throw把异常对象抛出。

十、finally一定会执行吗


- finally是异常处理的统一出口,常用来实现资源释放,比如关闭文件,关于数据库连接等。不一定会被执行的。
- **在以下4种特殊情况下,finally块不会被执行:**
    - 1.在finally语句块中发生了异常。
    - 2.在前面的代码中用了System.exit()退出程序。
    - 3.程序所在的线程死亡。
    - 4.关闭CPU。

finally语句的执行与return的关系,颇为让人迷惑,不知道finally语句是在try的return之前执行还是之后执行?

查看我的下片博客介绍

博客地址:

https://blog.csdn.net/bird_tp/article/details/103358566

十一、处理异常的一些建议

- 01.尽量捕获原始的异常
- 02.不要打印堆栈后再抛出异常
- 03.不要用异常处理机制代替判断

### 01.尽量捕获原始的异常
- 尽量捕获原始的异常
    - 实际应该捕获 FileNotFoundException,却捕获了泛化的 Exception。示例如下。很多人误以为捕获泛化的 Exception 更省事,但也更容易让人“丈二和尚摸不着头脑”。相反,捕获原始的异常能够让协作者更轻松地辨识异常类型,更容易找出问题的根源。
    ```
    InputStream is = null;
    try {
        is = new FileInputStream("沉默王二.txt");
    } catch (Exception e) {
        e.printStackTrace();
    }
    ```


### 02.不要打印堆栈后再抛出异常
- 不要打印堆栈后再抛出异常
    - 当异常发生时打印它,然后重新抛出它,以便调用者能够适当地处理它。就像下面这段代码一样。但是这样做的坏处是调用者可能也打印了异常,重复的打印信息会增添排查问题的难度。[博客](https://github.com/yangchong211/YCBlogs)
    ```
    public static void main(String[] args) throws IOException {
        try  {
            InputStream is = new FileInputStream("yc.txt");
        }catch (IOException e) {
            e.printStackTrace();
            throw e;
        } 
    }
    ```


### 03.不要用异常处理机制代替判断
- 本来应该判 null 的,结果使用了异常处理机制来代替。
    ```
    public static void main(String[] args) {
        try {
            String str = null;
            String[] strs = str.split(",");
        } catch (NullPointerException e) {
            e.printStackTrace();
        }
    }
    ```

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值