Java编程核心基础(四)—异常

#top 写在最前面
水滴石穿,稳固基础,基础永远是最需要注重的
文章仅作为JAVA编程复习使用
文章参考博主:<遇见狂神说>、<生命是有光的>、

8、异常

定义:程序运行时,发生的不被期望的事件,它阻止了程序按照程序员的预期正常执行,这就是异常。

8-1、异常的分类和产生原因

  • JAVA常把异常当做对象来处理,并定义一个基类java.lang.Throwable作为所有异常的超类。
  • 在 Java 中,所有的异常都有一个共同的祖先 java.lang 包中的 Throwable 类。Throwable 类有两个重要的子类 Exception(异常)和 Error(错误)。Exception 能被程序本身处理(try-catch), Error 是无法处理的(只能尽量避免)。
    • 错误 Error :无法预见,指的是JVM错误,这时的程序无法处理,我们也没办法通过 catch 来进行捕获 。
    • 异常 Exception :可以预见,指的是程序运行中产生的异常,可以通过 catch 来进行捕获。且 Exception 又可以分为 受检查异常(必须处理) 和 不受检查异常(可以不处理)。

在这里插入图片描述
在这里插入图片描述

产生异常的原因

  • 用户输入了非法数据。
  • 要打开的文件不存在。
  • 网络通信时连接中断,或者JVM内存溢出。

这些异常有的是因为用户错误引起,有的是程序错误引起的,还有其它一些是因为物理错误引起的。

异常的执行流程
在这里插入图片描述

8-2、Throwable类常用方法

  • public string getMessage():返回异常发生时的简要描述
  • public string toString():返回异常发生时的详细信息
  • public string getLocalizedMessage():返回异常对象的本地化信息。使用 Throwable 的子类覆盖这个方法,可以生成本地化信息。如果子类没有覆盖该方法,则该方法返回的信息与 getMessage()返回的结果相同
  • public void printStackTrace():在控制台上打印 Throwable 对象封装的异常信息

8-3、Exception异常

8-3-1、分类

  1. 受检查异常:Java 代码在编译过程中,如果受检查异常没有被 catch/throw 处理的话,就没办法通过编译 。

    除了RuntimeException及其子类以外,其他的Exception类及其子类都属于检查异常 。常见的受检查异常有: IO 相关的异常、ClassNotFoundExceptionSQLException…。

  2. 不受检查异常:Java 代码在编译过程中 ,我们即使不处理不受检查异常也可以正常通过编译。

    RuntimeException 及其子类都统称为非受检查异常,例如:NullPointerExceptionNumberFormatException(字符串转换为数字)、ArrayIndexOutOfBoundsException(数组越界)、ClassCastException(类型转换错误)、ArithmeticException(算术错误)等。

    (主要是上面两种)

  3. 编译时异常:继承自Exception的异常或者其子类,编译阶段就会报错

  4. 运行时异常:继承自RuntimeException的异常或者其子类,编译阶段不报错,但是运行阶段报错

8-3-2、常见的运行时异常(面试常问)

  • 数组索引越界异常ArrayIndexOutOfBoundsException
  • 空指针异常NullPointerExceptio
    • 直接输出没有问题,但是调用空指针的变量的功能就会报错!
  • 类型转换异常ClassCastException
  • 迭代器遍历没有此元素异常NoSuchElementException
  • 数学操作异常ArithmeticException
  • 数学转换异常NumberFormatException
public class ExceptionDemo {
    public static void main(String[] args) {
        System.out.println("程序开始。。。。。。");
        /** 1.数组索引越界异常: ArrayIndexOutOfBoundsException。*/
        int[] arrs = {10 ,20 ,30};
        System.out.println(arrs[2]);
        // System.out.println(arrs[3]); // 此处出现了数组索引越界异常。代码在此处直接执行死亡!

        /** 2.空指针异常 : NullPointerException。直接输出没有问题。但是调用空指针的变量的功能就会报错!! */
        String name = null ;
        System.out.println(name); // 直接输出没有问题
        // System.out.println(name.length());  // 此处出现了空指针异常。代码在此处直接执行死亡!

        /** 3.类型转换异常:ClassCastException。 */
        Object o = "齐天大圣";
        //Integer s = (Integer) o;  // 此处出现了类型转换异常。代码在此处直接执行死亡!


        /** 5.数学操作异常:ArithmeticException。 */
        // int c = 10 / 0 ; // 此处出现了数学操作异常。代码在此处直接执行死亡!


        /** 6.数字转换异常: NumberFormatException。 */
        String num = "23aa";
        Integer it = Integer.valueOf(num); // 此处出现了数字转换异常。代码在此处直接执行死亡!
        System.out.println(it+1);

        System.out.println("程序结束。。。。。。");
    }
}

8-4、异常关键字

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 – 用在方法签名中,用于声明该方法可能抛出的异常。**主方法上也可以使用throws抛出。**如果在主方法上使用了throws抛出,就表示在主方法里面可以不用强制性进行异常处理,如果出现了异常,就交给JVM进行默认处理,则此时会导致程序中断执行。

编译时异常的处理方式

  • 方式一:抛出异常
方法 throws Exception{
    
}
//在出现编译时异常的地方层层把异常抛出去给调用者,调用者最终抛出给JVM虚拟机,JVM虚拟机输出异常信息,直接干掉程序,这种方式与默认方式是一样的。虽然可以解决代码编译时的错误,但是一旦运行时真的出现异常,程序还是会立即死亡,这种方式并不好
  • 方式二:捕获处理:在出现异常的地方自己处理,谁出现谁处理

    try{
        // 监视可能出现异常的代码
    }catch{异常类型1 变量}{
        // 处理异常
    }catch{异常类型2 变量}{
        // 处理异常
    }
    //第二种方式,可以处理异常,并且出现异常后代码也不会死亡
    //但是从理论上来说,这种方式不是最好的,上层调用者不能直接知道底层的执行情况!
    
  • 方式三:在出现异常的地方把异常一层一层的抛出给最外层调用者,最外层调用者集中捕获处理

try{
    // 可能出现异常的代码
}catch(Exception e){
    e.printStackTrae(); //直接打印异常栈信息
}
//这种方案最外层调用者可以知道底层执行的情况,同时程序在出现异常后也不会立即死亡,这是理论上最好的方案。

8-5、finally关键字

  • 用在捕获处理的异常格式中,放在最后面
  • finally的作用:可以在代码执行完毕后进行资源的释放操作
try{
    //可能出现异常的代码!
}catch{Exception e}{
    e.printStackTrace();
}finally{
    // 无论代码是出现异常还是正常执行,最终一定要执行这里的代码!!
}
  • 资源都是实现了Closeable接口的,都自带close()关闭方法
  • try : 出现1次
  • catch:出现0 - N 次(如果有finally那么 catch 可以没有)
  • finally:出现0 - 1 次

在以下 3 种特殊情况下,finally 块不会被执行:

  1. tryfinally块中用了 System.exit(int)退出程序。但是,如果 System.exit(int) 在异常语句之后,finally 还是会被执行
  2. 程序所在的线程死亡。
  3. 关闭 CPU。

8-6、面试检查点

throw和throws的区别是什么?

throw和throws都是在异常处理中使用的关键字,区别如下:

  • throw:指的是在方法中人为抛出一个异常对象(这个异常对象可能是自己实例化或者抛出已存在的);
  • throws:在方法的声明上使用,表示此方法在调用时必须处理异常。

检查型异常(Checked Exception)与非检查型异常(Unchecked Exception)区别?

  • 所有的检查性异常都继承自java.lang.Exception;所有的非检查性异常都继承自java.lang.RuntimeException。
  • 检查性异常和非检查性异常最主要的区别在于其处理异常的方式:检查性异常必须使用try catch或者throws等关键字进行处理,否则编译器会报错; 非检查性异常一般是程序代码写的不够严谨而导致的问题,可以通过修改代码来规避。
  • 常见的运行时异常:空指针异常(NullPointerException)、除零异常(ArithmeticException)、数组越界异常(ArrayIndexOutOfBoundsException)等;
  • 常见的检查性异常:输入输出异常(IOException)、文件不存在异常(FileNotFoundException)、SQL语句异常(SQLException)等。

assert关键字(了解)

在Java中,assert关键字是从JAVA SE 1.4 引入的,为了避免和老版本的Java代码中使用了assert关键字导致错误,Java在执行的时候默认是不启动断言检查的(这个时候,所有的断言语句都 将忽略!),如果要开启断言检查,则需要用开关-enableassertions或-ea来开启。

assert关键字语法很简单,有两种用法:

  1. assert <boolean表达式>
    如果<boolean表达式>为true,则程序继续执行。
    如果为false,则程序抛出AssertionError,并终止执行。
  2. assert <boolean表达式> : <错误信息表达式>
    如果<boolean表达式>为true,则程序继续执行。
    如果为false,则程序抛出java.lang.AssertionError,并输入<错误信息表达式>。
public class Test {
	public static void main(String[] args) {
		int a = 10;
		int b = 2;
		assert a == 10:"a不等于10";
		System.out.println("a="+a);
	}
}
//得到 a=10

public class Test {
	public static void main(String[] args) {
		int a = 10;
		int b = 2;
		assert a == 20:"a不等于20";
		System.out.println("a="+a);
	}
}
//得到 Exception in Thread “main” java.lang.AssertionError:a不等于20   at Test.main<Test.java:5>

8-7、自定义异常(了解)

Java已经为开发中可能出现的异常都设计了一个类来代表,但是在实际开发中,异常可能有无数中情况,Java无法为这个世界上所有的异常都定义了一个类。假如一个企业如果想为自己认为的某种业务问题定义成一个异常,就需要自己来自定义异常类。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值