Java后端高频面试知识点汇总:异常

一、异常概念

异常,就是不正常的意思。在生活中:医生说,你的身体某个部位有异常,该部位和正常相比有点不同,该部 位的功能将受影响.在程序中的意思就是: 异常 :指的是程序在执行过程中,出现的非正常的情况,最终会导致JVM的非正常停止。 注意: 在Java等面向对象的编程语言中,异常本身是一个类,产生异常就是创建异常对象并抛出了一个 异常对象。Java处理异常的方式是中断处理。

异常指的并不是语法错误,语法错了,编译不通过,不会产生字节码文件,根本不能运行.

二、异常体系

异常机制其实是帮助我们找到程序中的问题,异常的根类是 java.lang.Throwable ,其下有两个子 类:

(1)java.lang.Error

(2)java.lang.Exception ,平常所说的异常指 java.lang.Exception 


三、异常分类

我们平常说的异常就是指Exception,因为这类异常一旦出现,我们就要对代码进行更正,修复程序。 异常(Exception)的分类:根据在编译时期还是运行时期去检查异常?

3.1编译时期异常:checked异常

在编译时期,就会检查,如果没有处理异常,则编译失败。(如日期格式化异常)

3.2运行时期异常:runtime异常

在运行时期,检查异常.在编译时期,运行异常不会编译器检测(不报错)。(如数学异常)

四、 异常的产生

throw关键字的作用

在java中,提供了一个throw关键字,它用来抛出一个指定的异常对象。throw用在方法内,用来抛出 一个异常对象,将这个异常对象传递到调用者处,并结束当前方法的执行。

throws关键字的作用

声明处理异常:使用throws关键字将问题标识出来, 表示当前方法不处理异常,而是提醒给调用者, 让调 用者来处理....最终会到虚拟机,虚拟机直接结束程序,打印异常信息。

五、异常的处理

5.1 声明处理异常

概述:使用throws关键字将问题标识出来, 表示当前方法不处理异常,而是提醒给调用者, 让调用者来处理....最终会到虚拟机,虚拟机直接结束程序,打印异常信息。

声明处理异常格式

修饰符 返回值类型 方法名(参数) throws 异常类名1,异常类名2…{ // 可以抛出一个,也可以多个
}

使用场景: 声明处理异常一般处理运行的时候不会出现异常的编译异常 

5.2 捕获处理异常try…catch

捕获处理异常的概述

捕获处理异常:对异常进行捕获处理 , 处理完后程序可以正常向下执行。

捕获处理异常格式:

try{ 

        编写可能会出现异常的代码 

}catch(异常类型 e){

         处理异常的代码 

        //记录日志/打印异常信息 } 

执行步骤: 

1.首先执行try中的代码,如果try中的代码出现了异常,那么就直接执行catch()里面的代码,执行完 后,程序继续往下执行 

2.如果try中的代码没有出现异常,那么就不会执行catch()里面的代码,而是继续往下执行

注意:

1. try和catch都不能单独使用,必须连用。

2. try中的代码出现了异常,那么出现异常位置后面的代码就不会再执行了

3. 捕获处理异常,如果程序出现了异常,程序会继续往下执行 声明处理异常,如果程序出现了异常,程序就不会继续往下执行

5.3 finally 代码块

finally代码块的概述

finally:有一些特定的代码无论异常是否发生,都需要执行。另外,因为异常会引发程序跳转,导致有 些语句执行不到。而finally就是解决这个问题的,在finally代码块中存放的代码都是一定会被执行的。

finally代码块的语法格式:

try{
    可能会出现异常的代码
}catch(异常的类型 变量名){
    处理异常的代码或者打印异常的信息
}finally{
    无论异常是否发生,都会执行这里的代码(正常情况,都会执行finally中的代码,一般用来释放资源)
}

执行步骤:

1.首先执行try中的代码,如果try中的代码出现了异常,那么就直接执行catch()里面的代码,执行完后会执 行finally中的代码,然后程序继续往下执行

2.如果try中的代码没有出现异常,那么就不会执行catch()里面的代码,但是还是会执行finally中的代 码,然后程序继续往下执行

扩展--finally经典面试题

public class Test {
    public static void main(String[] args) {
        System.out.println(method1());// 30
        System.out.println(method2());// 20
    }

    public static int method1() {
        int num = 10;
        try {
            System.out.println(1 / 0);
        } catch (ArithmeticException e) {
            num = 20;
            return num;
        } finally {
            num = 30;
            return num;
        }
    }

    public static int method2() {
        int num = 10;
        try {
            System.out.println(1 / 0);
        } catch (ArithmeticException e) {
            num = 20;
            // catch中的return会做2件事:1.先记录要返回的值,然后执行finally中的代码,2.最后把记录的值返回
            return num;// 记录要返回的值:20
        } finally {
            num = 30;
        }
        return num;
    }
}

六、Java异常常见面试题

6.1 Error 和 Exception 区别是什么?

Error 类型的错误通常为虚拟机相关错误,如系统崩溃,内存不足,堆栈溢出等,编译器不会对这 类错误进行检测,JAVA 应用程序也不应对这类错误进行捕获,一旦这类错误发生,通常应用程序 会被终止,仅靠应用程序本身无法恢复; Exception 类的错误是可以在应用程序中进行捕获并处理的,通常遇到这种错误,应对其进行处 理,使应用程序可以继续正常运行。

6.2 运行时异常和一般异常(受检异常)区别是什么?

运行时异常包括 RuntimeException 类及其子类,表示 JVM 在运行期间可能出现的异常。 Java 编 译器不会检查运行时异常。 受检异常是Exception 中除 RuntimeException 及其子类之外的异常。 Java 编译器会检查受检异 常。 RuntimeException异常和受检异常之间的区别:是否强制要求调用者必须处理此异常,如果强 制要求调用者必须进行处理,那么就使用受检异常,否则就选择非受检异常 (RuntimeException)。一般来讲,如果没有特殊的要求,我们建议使用RuntimeException异常。

6.3 JVM 是如何处理异常的?

在一个方法中如果发生异常,这个方法会创建一个异常对象,并转交给 JVM,该异常对象包含异 常名称,异常描述以及异常发生时应用程序的状态。创建异常对象并转交给 JVM 的过程称为抛出 异常。可能有一系列的方法调用,最终才进入抛出异常的方法,这一系列方法调用的有序列表叫做 调用栈。 readFile method catch block. readFile method finally block. private static void tryWithResourceTest(){ try (Scanner scanner = new Scanner(new FileInputStream("c:/abc"),"UTF-8")){ // code } catch (IOException e){ // handle exception } } JVM 会顺着调用栈去查找看是否有可以处理异常的代码,如果有,则调用异常处理代码。当 JVM 发现可以处理异常的代码时,会把发生的异常传递给它。如果 JVM 没有找到可以处理该异常的代 码块,JVM 就会将该异常转交给默认的异常处理器(默认处理器为 JVM 的一部分),默认异常处 理器打印出异常信息并终止应用程序。

6.4 throw 和 throws 的区别是什么?

Java 中的异常处理除了包括捕获异常和处理异常之外,还包括声明异常和拋出异常,可以通过 throws 关键字在方法上声明该方法要拋出的异常,或者在方法内部通过 throw 拋出异常对象。 throws 关键字和 throw 关键字在使用上的几点区别如下: throw 关键字用在方法内部,只能用于抛出一种异常,用来抛出方法或代码块中的异常,受查异常 和非受查异常都可以被抛出。 throws 关键字用在方法声明上,可以抛出多个异常,用来标识该方法可能抛出的异常列表。一个 方法用 throws 标识了可能抛出的异常列表,调用该方法的方法中必须包含可处理异常的代码,否 则也要在方法签名中用 throws 关键字声明相应的异常。

6.5 final、finally、finalize 有什么区别?

final可以修饰类、变量、方法,修饰类表示该类不能被继承、修饰方法表示该方法不能被重写、 修饰变量表示该变量是一个常量不能被重新赋值。 finally一般作用在try-catch代码块中,在处理异常的时候,通常我们将一定要执行的代码方法 finally代码块中,表示不管是否出现异常,该代码块都会执行,一般用来存放一些关闭资源的代 码。 finalize是一个方法,属于Object类的一个方法,而Object类是所有类的父类,Java 中允许使用 finalize()方法在垃圾收集器将对象从内存中清除出去之前做必要的清理工作。

6.6 NoClassDefFoundError 和 ClassNotFoundException 区别?

NoClassDefFoundError 是一个 Error 类型的异常,是由 JVM 引起的,不应该尝试捕获这个异 常。 引起该异常的原因是 JVM 或 ClassLoader 尝试加载某类时在内存中找不到该类的定义,该动作发 生在运行期间,即编译时该类存在,但是在运行时却找不到了,可能是变异后被删除了等原因导 致; ClassNotFoundException 是一个受查异常,需要显式地使用 try-catch 对其进行捕获和处理,或 在方法签名中用 throws 关键字进行声明。当使用 Class.forName, ClassLoader.loadClass 或 ClassLoader.findSystemClass 动态加载类到内存的时候,通过传入的类路径参数没有找到该类, 就会抛出该异常;另一种抛出该异常的可能原因是某个类已经由一个类加载器加载至内存中,另一 个加载器又尝试去加载它。

6.7 try-catch-finally 中,如果 catch 中 return 了,finally 还会执 行吗? (见经典面试题)

答:会执行,在 return 前执行。 注意:在 finally 中改变返回值的做法是不好的,因为如果存在 finally 代码块,try中的 return 语 句不会立马返回调用者,而是记录下返回值待 finally 代码块执行完毕之后再向调用者返回其值, 然后如果在 finally 中修改了返回值,就会返回修改后的值。显然,在 finally 中返回或者修改返回 值会对程序造成很大的困扰。

C#中直接用编译错误的方式来阻止程序员干这种龌龊的事情,Java 中也可以通过提升编译器的语法检查级别来产生警告或错误。

6.8 常见的 RuntimeException 有哪些?

  • ClassCastException(类转换异常)
  • IndexOutOfBoundsException(数组越界)
  • NullPointerException(空指针) ArrayStoreException(数据存储异常,操作数组时类型不一致)
  • 还有IO操作的BufferOverflowException异常

6.9 Java常见异常有哪些

  • java.lang.IllegalAccessError:违法访问错误。当一个应用试图访问、修改某个类的域(Field)或 者调用其方法,但是又违反域或方法的可见性声明,则抛出该异常。
  • java.lang.InstantiationError:实例化错误。当一个应用试图通过Java的new操作符构造一个抽象 类或者接口时抛出该异常.
  • java.lang.OutOfMemoryError:内存不足错误。当可用内存不足以让Java虚拟机分配给一个对象 时抛出该错误。
  • java.lang.StackOverflowError:堆栈溢出错误。当一个应用递归调用的层次太深而导致堆栈溢出 或者陷入死循环时抛出该错误。
  • java.lang.ClassCastException:类造型异常。假设有类A和B(A不是B的父类或子类),O是A的 实例,那么当强制将O构造为类B的实例时抛出该异常。该异常经常被称为强制类型转换异常。
  • java.lang.ClassNotFoundException:找不到类异常。当应用试图根据字符串形式的类名构造类, 而在遍历CLASSPAH之后找不到对应名称的class文件时,抛出该异常。
  • java.lang.ArithmeticException:算术条件异常。譬如:整数除零等。
  • java.lang.ArrayIndexOutOfBoundsException:数组索引越界异常。当对数组的索引值为负数或 大于等于数组大小时抛出。
  • java.lang.IndexOutOfBoundsException:索引越界异常。当访问某个序列的索引值小于0或大于 等于序列大小时,抛出该异常。
  • java.lang.InstantiationException:实例化异常。当试图通过newInstance()方法创建某个类的实 例,而该类是一个抽象类或接口时,抛出该异常。
  • java.lang.NoSuchFieldException:属性不存在异常。当访问某个类的不存在的属性时抛出该异 常。
  • java.lang.NoSuchMethodException:方法不存在异常。当访问某个类的不存在的方法时抛出该 异常。
  • java.lang.NullPointerException:空指针异常。当应用试图在要求使用对象的地方使用了null时, 抛出该异常。譬如:调用null对象的实例方法、访问null对象的属性、计算null对象的长度、使用 throw语句抛出null等等。
  • java.lang.NumberFormatException:数字格式异常。当试图将一个String转换为指定的数字类 型,而该字符串确不满足数字类型要求的格式时,抛出该异常。
  • java.lang.StringIndexOutOfBoundsException:字符串索引越界异常。当使用索引值访问某个字 符串中的字符,而该索引值小于0或大于等于序列大小时,抛出该异常。
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值