Java 异常知识点整理

牧云@^-^@ 提交于 2019-12-19 02:04:50

1. 异常和其用法

  • 异常:当程序在正常运作的过程中,出现的阻碍程序正常执行的事件。比如说我们取一个值结果发现这个值为空,要找某个类结果这个类不存在,这些就都是异常。
  • 异常机制:Java所提供的有关异常的机制。当程序出现这种错误事件时,能够让程序以其他方式继续运作的机制。

1.1 异常机制

Java的异常机制其实就是我们熟悉的try/catch的相关内容,一般写法如下:

  1. try/catch机制
    //用法1:try/catch机制
    try{
    	//要处理的内容
    	.........
    }catch(AException e){
    	//遇到A类型错误时的备用方案
    	........
    }catch(BException e){
    	//遇到B类型错误时的备用方案
    	........
    }catch(CException e){
    	//遇到C类型错误时的备用方案
    	........
    }finally{
    	//最后要做出的处理
    	........
    }
    
    • try:尝试进行的代码块,当你或者编译器觉得某段代码会出现预料外或预料内的错误时,就用try来运行这段代码。
    • catch:代码块中捕捉到的错误,当捕捉到错误的时候就会执行相应catch段内的代码。
    • finally:任何情况下都一定会执行的代码,当用上finally语句的时候,无论代码块是否会出错都一定会执行finally段的内容,切如果try/catch中如果有return时,finally的代码会先一步return执行。
    public static void main(String[] args){
    	System.out.println(func());  //最终结果是9
    }
    
    public static int func(){
    	int a = 10;
    	try{
    		return a; 
    	}catch(Exception e){
    	}finally{
    		a = 9;
    	}
    	return 8;
    }
    
  2. throws:当你觉得某个方法可能会出现某种错误时,可以令这个方法抛出异常。
    //用法2:声明异常的方法
    public void func() throws AException, BException{
    	//要处理的逻辑
    	..........
    }
    
  3. throw:当你觉得某段代码会出现某种错误时,可以用throw抛出异常。
    //用法2:声明异常的方法
    public static void func(int id) throws Exception {
        if (id < 0)
            throw new Exception("id不能小于0");
    }
    

2. Throwable和其子类

从根本上来说,异常的根源也是一个类Throwable,我们所认识的各种异常都是从这里开始。
在这里插入图片描述

2.1 Error和Exception

异常有两个子类Error和Exception,对应了Java当中的各种类型的异常和错误。

  • Error:错误发生一般不是程序员编写的代码出现了什么问题,而是JVM本身出了错误,当发生Error的时候,程序无法解决这些问题。
  • Exception:异常代表了程序本身发生的一些意料外的状态,当出现异常的时候,程序可以通过异常机制来处理这些异常。

由于Error本身不能被解决,我们一般只注意Exception部分的内容。

2.2 检查型异常和非检查型异常

一般情况下,异常被分为检查型异常和非检查型异常,也有一种说法是非运行时异常和运行时异常,两者是同一事物。

  • 检查型异常(checked Exception) :除了RuntimeException以外的所有Exception子类。编译器会检查的异常,但编程者写下带有检查型异常的代码时,编译器会主动的报错,要求编程者在这段代码上使用异常机制(try/catch处理或者throws抛出)。
  • 非检查型异常(unchecked Exception):所有RuntimeException的子类。在程序运行中很容易会出现的错误,这种类型的错误一般是由程序本身的逻辑问题,编译器不会主动去要求编程者使用异常机制来处理这些错误,相反,当出现这些错误时,编程者应该偏向于通过修改自己的代码来保证逻辑完整而不是使用异常机制来处理。

  简单来说,检查型异常就是本身就很容易出错的代码,像是数据库的各种查找语句,很容易就出现找不到的情况,这种类型的异常编译器就会在程序正式运行之前提前要求编程者处理好这部分的问题。

  相反呢,非检查型异常就是代码本身不容易出错,如果出错了就是编程者的操作出了问题,比如说引用了不存在的对象,或者除法中被除数位0之类的这种问题,像这样的问题就不需要特地用异常机制去处理,如果出错就手动修改代码就行。

2.3 常见的Exception

检查型异常 描述(特点是必须使用异常机制)
ClassNotFoundException 不能加载所需的类,类找不到
IOException 输入输出相关的异常
FileNotFoundException 文件找不到异常
SQLException 数据库相关异常
非检查型异常 描述
ArithmeticException 当出现异常的运算条件时,抛出此异常。
ArrayIndexOutOfBoundsException 非法索引数组时抛出异常,经典下标小于0或者大于最大值。
ClassCastException 当试图将对象强制转换为不是实例的子类时,抛出该异常。
IllegalStateException 无效状态时抛出异常,当某个操作需要前置步骤但并没有执行的时候容易出现。
IllegalThreadStateException 线程无效状态时抛出异常。调用线程方法但线程状态不正确时会出现,比如说两次start一个线程。
NullPointerException 空指针时抛出异常。当需要使用一个引用但这个引用并不指向实际的变量时会出现。
NumberFormatException 当把String转换成某种类型但并不成功时抛出异常。比如说"aaa"并不能转成Integer
StringIndexOutOfBoundsException 超过索引的String版,经典下标小于0或者大于最大值

3. 如何自定义异常

  1. 新建一个类,然后继承Exception(如果要弄运行时异常,就继承RuntimeException),并且重写其中的有参构造方法和无参构造方法。
    public class TestException extends Exception {
        public TestException(){
            super("这是一个自定义的异常");
        }
    
        public TestException(String message){
            super(message);
        }
    }
    
  2. 然后在某段代码或者某个方法中抛出,最后再某处引用。
    public static void main(String[] args) {
        try {
            func(-1);
            func2(-1);
        } catch (TestException e) {
            e.printStackTrace();
        }
    }
    
    public static void func(int id) throws TestException {
        if (id < 0)
            throw new TestException("id不能小于0");
    }
    
    public static void func2(int id) throws TestException {
        if (id < 0)
            throw new TestException();
    }
    
  3. 你会发现这样子的异常和抛出普通的Exception没有区别,但是自定义异常最主要的目的还是让其他的编程者知道这部分的错误的具体类型和原因。

4. 面对异常,如何处理

  1. 空指针异常可以说是世界上最恶心的异常没有之一,当某些方法需要返回某个对象,而这个对象又可能为空的时候,可以用各种各样的方法来避免return null这个最坏的结果。比如说返回一个布尔类型,或者返回一个空对象。
    public class Test {
        String str;
    
        public String getStr() {
            return str; //不推荐
            return str == null? str : ""//用一个空对象来代替return null
        }
    }
    
  2. catch块中不要啥都不写,catch块是用来处理异常的,try块用于捕获异常,如果catch块啥都不写,那就相当于只捕获不解决。最起码的e.printStackTrace();要写,不然出错了都不知道哪里错了。如果有详细的解决方案就更好。
  3. 尽量使用检查型异常,把所有的问题都在编译阶段就解决,保证程序的安全性。
  4. finally块不要忘记使用,比如说try块用上了像是IO流,或者SQL流,那么在finally块就可以调用close()来关闭流。
  5. 不要把异常显示到前端,所有的异常在代码部分就要处理成用户看得懂的信息后再发出。

参考材料

Android面试系列文章2018之Java部分异常篇 - 编程语言是方式,而思维是创造。
https://blog.csdn.net/ClAndEllen/article/details/79389561
Java:详解Java中的异常(Error与Exception) - 王晓(Java)
https://blog.csdn.net/qq_29229567/article/details/80773970
关于Java语言异常的常见面试笔试题分享-职坐标
http://m.zhizuobiao.com/java/java-18110500176/

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!