文章目录
- 一、知识点总结
- (1)异常处理概述
- (2)异常处理的方式1:try-catch-finally
- (3)异常处理的方式2:throws
- (4)throw手动抛出异常对象
- (5)自定义异常
- 二、企业真题
- (1)异常概述
- 1、题目1
- 2、题目2
- 3、题目3
- 4、题目4
- 5、题目5
- (2) try-catch-finally
- 1、题目1
- 2、题目2
- 3、题目3
- 4、题目4
- 5、题目5
- 6、题目6
- (3)throw与throws
- 1、题目1
- 2、题目2
- (4)自定义异常
- 1、题目1
一、知识点总结
(1)异常处理概述
文章链接:https://blog.csdn.net/m0_55746113/article/details/135473445?spm=1001.2014.3001.5502
-
什么是异常?
指的是程序在执行过程中,出现的非正常情况,如果不处理最终会导致JVM的非正常停止。(逻辑上的错误不算) -
异常的抛出机制
Java中把不同的异常用不同的类表示,一旦发生某种异常,就创建该异常类型的对象
,并且抛出(throw
)。
然后程序员可以捕获(catch
)到这个异常对象,并处理;如果没有捕获(catch
)这个异常对象,那么这个异常对象将会导致程序终止。 -
如何对待异常
对于程序出现的异常,一般有两种解决方法:
一是遇到错误就终止程序的运行。另一种方法是程序员在编写程序时,就充分考虑到各种可能发生的异常和错误,极力预防和避免。实在无法避免的,要编写相应的代码进行异常的检测、以及异常的处理
,保证代码的健壮性
。 -
异常的体系结构
java.lang.Throwable
:异常体系的根父类 (它的父类是Object)
-
java.lang.Error
:错误。(基本不做处理)- Java虚拟机无法解决的严重问题。如:JVM系统内部错误、资源耗尽等严重情况。一般不编写针对性的代码进行处理。- StackOverflowError (栈内存溢出)
OutOfMemoryError (堆内存溢出,简称OOM)
- Java虚拟机无法解决的严重问题。如:JVM系统内部错误、资源耗尽等严重情况。一般不编写针对性的代码进行处理。- StackOverflowError (栈内存溢出)
-
java.lang.Exception
:异常。-
我们可以编写针对性的代码进行处理。
-
编译时异常:(受检异常) 在执行
javac.exe
命令时,出现的异常。(这一章的异常处理针对的就是它)- ClassNotFoundException
- FileNotFoundException
- IOException
-
运行时异常:(非受检异常) 在执行
java.exe
命令时,出现的异常。(基本不做处理)-
ArrayIndexOutOfBoundsException (数组越界–用非法索引访问数组时抛出的异常)
-
NullPointerException (空指针异常)
-
ClassCastException (类转换异常)
-
NumberFormatException (数据格式化异常)
-
InputMismatchException (输入类型不一致)
-
ArithmeticException (算术异常)
-
-
(2)异常处理的方式1:try-catch-finally
文章链接:https://blog.csdn.net/m0_55746113/article/details/135547506?spm=1001.2014.3001.5502
- 方式一(抓抛模型):
try-catch-finally
- 过程1:“抛”-- 产生异常的对象
- 程序在执行的过程当中,一旦出现异常,就会在出现异常的代码处,生成对应异常类的对象,并将此对象抛出。(目前先看自动创建异常的对象并抛出)
- 一旦抛出,此程序就不执行其后的代码了。
- 过程2:“抓”-- 捕获处理
- 针对于过程1中抛出的异常对象,进行捕获处理。此捕获处理的过程,就称为抓。
- 一旦将异常进行了处理,代码就可以继续执行。
- 基本结构:
try{...... //可能产生异常的代码
}
catch( 异常类型1 e ){...... //当产生异常类型1型异常时的处置措施
}
catch( 异常类型2 e ){...... //当产生异常类型2型异常时的处置措施
}
finally{...... //无论是否发生异常,都无条件执行的语句
}
- 使用细节:
- 将可能出现异常的代码声明在try语句中。一旦代码出现异常,就会自动生成一个对应异常类的对象。并将此对象抛出。
- 针对于try中抛出的异常类的对象,使用之后的catch语句进行匹配。一旦匹配上,就进入catch语句块进行处理。一旦处理结束,代码就可继续向下执行。
- 如果声明了多个catch结构,不同的异常类型在不存在子父类关系的情况下,谁声明在上面,谁声明在下面都可以。如果多个异常类型满足子父类的关系,则必须将子类声明在父类结构的上面。否则,报错。
catch中异常处理的方式:
① 自己编写输出的语句。
② printStackTrace():打印异常的详细信息。 (推荐)
③ getMessage():获取发生异常的原因。
try中声明的变量,出了try结构之后,就不可以进行调用了。
try-catch结构是可以嵌套使用的。
- 开发体会:
-
对于运行时异常:
开发中,通常就不进行显示的处理了。一旦在程序执行中,出现了运行时异常,那么就根据异常的提示信息修改代码即可。
-
对于编译时异常:
一定要进行处理。否则编译不通过。
- finally的使用说明:
5.1 finally的理解
- 我们将一定要被执行的代码声明在finally结构中。
- 更深刻的理解:无论try中或catch中是否存在仍未被处理的异常,无论try中或catch中是否存在return语句等,finally中声明的语句都一定要被执行。
- finally语句和catch语句是可选的,但finally不能单独使用。
5.2 什么样的代码我们一定要声明在finally中呢?
我们在开发中,有一些资源(比如:输入流、输出流,数据库连接、Socket连接等资源),在使用完以后,必须显式的进行关闭操作,否则,GC不会自动的回收这些资源。进而导致内存的泄漏。
为了保证这些资源在使用完以后,不管是否出现了未被处理的异常的情况下,这些资源能被关闭。我们必须将这些操作声明在finally中!
6.面试题
final 、 finally 、finalize 的区别
(3)异常处理的方式2:throws
文章链接:https://blog.csdn.net/m0_55746113/article/details/135618390?spm=1001.2014.3001.5502
- 格式:在方法的声明处,使用"
throws 异常类型1,异常类型2,...
" - 举例:
public void test() throws 异常类型1,异常类型2,.. {//可能存在编译时异常 (运行时异常不用管它)
}
- 是否真正处理了异常?
- 从编译是否能通过的角度看,看成是给出了异常万一要是出现时候的解决方案。此方案就是,继续向上抛出(
throws
)。 - 但是,此throws的方式,仅是将可能出现的异常抛给了此方法的调用者。此调用者仍然需要考虑如何处理相关异常。从这个角度来看,throws的方式不算是真正意义上处理了异常。
-
方法的重写的要求:(针对于编译时异常来说的)
子类重写的方法抛出的异常类型可以与父类被重写的方法抛出的异常类型相同,或是父类被重写的方法抛出的异常类型的子类。 -
开发中,如何选择异常处理的两种方式?(重要、经验之谈)
- 如果程序代码中,涉及到资源的调用(流、数据库连接、网络连接等),则必须考虑使用
try-catch-finally
来处理,保证不出现内存泄漏。 - 如果父类被重写的方法没有throws异常类型,则子类重写的方法中如果出现异常,只能考虑使用
try-catch-finally
进行处理,不能throws。(父类没有throws,子类也不能throws) - 开发中,方法a中依次调用了方法b,c,d等方法,方法b,c,d之间是递进关系。此时,如果方法b,c,d中有异常,我们通常选择使用
throws
,而方法a中通常选择使用try-catch-finally
。
(4)throw手动抛出异常对象
文章链接:https://blog.csdn.net/m0_55746113/article/details/135656358?spm=1001.2014.3001.5502
-
为什么需要手动抛出异常对象?
在实际开发中,如果出现不满足具体场景的代码问题,我们就有必要手动抛出一个指定类型的异常对象。 -
如何理解"自动 vs 手动"抛出异常对象?
过程1:“抛”
“自动抛” : 程序在执行的过程当中,一旦出现异常,就会在出现异常的代码处,自动生成对应异常类的对象,并将此对象抛出。
“手动抛” :程序在执行的过程当中,不满足指定条件的情况下,我们主动的使用"throw + 异常类的对象"方式抛出异常对象。
过程2:“抓”
狭义上讲:try-catch的方式捕获异常,并处理。
广义上讲:把“抓”理解为“处理”。则此时对应着异常处理的两种方式:① try-catch-finally ② throws -
如何实现手动抛出异常?
在方法内部,满足指定条件的情况下,使用"throw 异常类的对象
"的方式抛出。 -
注意点:throw后的代码不能被执行,编译不通过。
-
面试题:throw 和 throws 的区别? “上游排污,下游治污”
(5)自定义异常
文章链接:https://blog.csdn.net/m0_55746113/article/details/135678410?spm=1001.2014.3001.5502
-
如何自定义异常类?
① 继承于现有的异常体系。通常继承于RuntimeException
\Exception
② 通常提供几个重载的构造器
③ 提供一个全局常量,声明为:static final long serialVersionUID
-
如何使用自定义异常类?
- 在具体的代码中,满足指定条件的情况下,需要手动的使用"throw + 自定义异常类的对象"方式,将异常对象抛出。
- 如果自定义异常类是非运行时异常,则必须考虑如何处理此异常类的对象。(具体的:① try-catch-finally ② throws)
- 为什么需要自定义异常类?
我们其实更关心的是,通过异常的名称就能直接判断此异常出现的原因。
既然如此,我们就有必要在实际开发场景中,不满足我们指定的条件时,指明我们自己特有的异常类。通过此异常类的名称,就能判断出具体出现的问题。
二、企业真题
(1)异常概述
1、题目1
🌋题目描述:Java的异常体系简单介绍下(网*)
包含问题:
> 异常的顶级接口是什么(软**力) 答:Throwable类
> 异常类的继承关系,exception下都有哪些类?(上海*冉信息)
🍰答
java.lang.Throwable
:异常体系的根父类 (它的父类是Object)
-
java.lang.Error
:错误。(基本不做处理)- Java虚拟机无法解决的严重问题。如:JVM系统内部错误、资源耗尽等严重情况。一般不编写针对性的代码进行处理。- StackOverflowError (栈内存溢出)
OutOfMemoryError (堆内存溢出,简称OOM)
- Java虚拟机无法解决的严重问题。如:JVM系统内部错误、资源耗尽等严重情况。一般不编写针对性的代码进行处理。- StackOverflowError (栈内存溢出)
-
java.lang.Exception
:异常。-
我们可以编写针对性的代码进行处理。
-
编译时异常:(受检异常) 在执行
javac.exe
命令时,出现的异常。(这一章的异常处理针对的就是它)- ClassNotFoundException
- FileNotFoundException
- IOException
-
运行时异常:(非受检异常) 在执行
java.exe
命令时,出现的异常。(基本不做处理)- ArrayIndexOutOfBoundsException (数组越界–用非法索引访问数组时抛出的异常)
- NullPointerException (空指针异常)
- ClassCastException (类转换异常)
- NumberFormatException (数据格式化异常)
- InputMismatchException (输入类型不一致)
- ArithmeticException (算术异常)
-
2、题目2
🌋题目描述:Java异常处理机制(*科软)
🍰答
两种处理方案:try-catch-finally
;throws
。
3、题目3
🌋题目描述:异常的两种类型,Error和Exception的区别(上海冠*新创、北京中**译、*度)
🍰答
①Error:错误。Java虚拟机无法解决的严重问题。如:JVM系统内部错误、资源耗尽等严重情况。一般不编写针对性的代码进行处理。
②Exception:异常。我们可以编写针对性的代码进行处理。
4、题目4
🌋题目描述:运行时异常与一般异常有何异同?(华*思为)
🍰答
运行时异常:RuntimeException
- 编译可以通过。在运行时可能抛出。出现的概率高一些;一般针对于运行时异常,都不处理。
一般异常:Exception
- 编译不能通过。要求必须在编译之前,考虑异常的处理。不处理编译不通过。
5、题目5
🌋题目描述:说几个你常见到的异常(华油**普)
类似问题:
> 请列出Java中常见的几种异常?(百*园)
> 给我一个你最常见到的runtime exception。(*蝶)
🍰答
①开发1-2年:
- 编译时异常:(受检异常)在执行javac.exe命令时,出现的异常。
- ClassNotFoundException
- FileNotFoundException
- IOException
- 运行时异常:(非受检异常)在执行java.exe命令时,出现的异常。
- ArrayIndexOutOfBoundsException
- NullPointerException
- ClassCastException
- NumberFormatException
- InputMismatchException
- ArithmeticException
②开发3年以上:
OOM
(2) try-catch-finally
1、题目1
🌋题目描述:说说final、finally、finalize的区别(北京中**译、艾软件、拓思、*科软)
类似问题:
> finally和final的区别(*科软)
🍰答
-
final:最终的
-
finally:try-catch-finally中必须要被执行的代码
-
finalize:方法名,任何一个类直接或间接继承于Object,不重写的话不会用这个方法。当这个类的对象要被GC回收的时候,在回收之前的遗言写在这里面,就是当前类的对象要调用的方法。在jdk9之后被标记为过时的方法了。
🎲注
关于finalize,在这一篇博客里面:https://blog.csdn.net/m0_55746113/article/details/134389583?spm=1001.2014.3001.5502
如下:
2、题目2
🌋题目描述:如果不使用try-catch,程序出现异常会如何?(上海冠*新创科技)
🍰答
对于当前方法来讲,如果不使用try-catch
,则在出现异常对象以后会抛出此对象。
如果没有处理方案,就会终止程序的执行。(throws
不会在根本处解决问题)
3、题目3
🌋题目描述:try … catch捕捉的是什么异常?(北京亿*东方)
🍰答
Exception。非Error
4、题目4
🌋题目描述:如果执行finally代码块之前,方法返回了结果或者jvm退出了,这时finally块中的代码还会执行吗?(恒*电子)
🍰答
方法返回了结果:finally会执行。
JVM退出了:finally一般会执行;特别的,System.exit(0);
(强制结束)此时finally不会执行。
5、题目5
🌋题目描述:在try语句中有return语句,最后写finally语句,finally语句中的code会不会执行?何时执行?如果执行是在return前还是后(拓*思、华**为)
🍰答
方法是一个栈帧,放在栈里面。栈帧又分为好几个部分,有局部变量表(存放局部变量)、操作数栈(用来临时存放数据)。
比如:
public static void main(String[] args) {int result = test("a");System.out.println(result);}public static int test(String str) {try {Integer.parseInt(str);return 1;} catch (NumberFormatException e) {return -1;} finally {System.out.println("test结束");}}
当我们执行return -1
的时候,它会将-1
放入操作数栈里面,按道理说下一步应该将-1
拿出去,方法就结束了。但是此时先不能拿出去,需要先执行finally
里面的语句,执行完之后再把-1
拿出去。
所以return -1
这里有两个过程,第一个过程是将-1放入操作数栈里面,第二个过程是将-1拿出去。在这两个过程中间,插入了finally的语句。
finally中的语句会执行。整体来看,是finally先;但是细节来看,是return先,再finally,最后再return。
6、题目6
🌋题目描述:捕获异常在catch块里一定会进入finally吗?catch里能return吗?catch里return还会进finally吗?在try里return是什么情况?(*蓝)
🍰答
会;可以;会;return之前要先执行一下finally。(finally一定会被执行的)
(3)throw与throws
1、题目1
🌋题目描述:throw和throws的区别?(北京亿**方、北京新*阳光)
🍰答
角度1:“形”,即使用的格式
throw
:使用在方法内部,“throw 异常类的对象
”throws
:使用在方法的声明处,“throws 异常类1,异常类2,...
”
角度2:"角色"或作用不同
上游排污,下游治污。
- 过程1:“抛” -->排污
throw
:手动将异常抛出,相当于生成一个异常对象(所谓的自动抛,只不过不是我们自己写的代码而已,源码里面也是用throw关键字来写的)
- 过程2:“抓” -->治污
try-catch
(根本解决)throws
:对异常对象的一种处理,抛向该方法的调用方法
2、题目2
🌋题目描述:子类重写父类抛出异常的方法,能否抛出比父类更高级别的异常类(顺*)
🍰答
不能!
子类重写父类抛出异常的方法,只能和父类抛出异常一样或者这个异常的子类。
(4)自定义异常
1、题目1
🌋题目描述:如何自定义一个异常?(*软国际)
🍰答
① 继承于现有的异常体系。通常继承于RuntimeException
\ Exception
② 通常提供几个重载的构造器
③ 提供一个全局常量,声明为:static final long serialVersionUID