java基础面试题三异常处理
目录
1. Java的异常体系简单介绍下
2. Java异常处理机制
3. 异常的两种类型,Error和Exception的区别
4. 运行时异常与一般异常有何异同?
5. 说几个你常见到的异常
6. 说说final、finally、finalize的区别
7. 如果不使用try-catch,程序出现异常会如何?
8. try ... catch捕捉的是什么异常?
9. 如果执行finally代码块之前方法返回了结果或者jvm退出了,这时finally块中的代码还会执行吗?
10. 在try语句中有return语句,最后写finally语句,finally语句中的code会不会执行?何时执行?如果执行是在return前还是后
11. 捕获异常在catch块里一定会进入finally吗?catch里能return吗?catch里return还会进finally吗?在try里return是什么情况?
12. throw和throws的区别?
13. 子类重写父类抛出异常的方法,能否抛出比父类更高级别的异常类
13. 如何自定义一个异常?
1. Java的异常体系简单介绍下
1. 异常的分类
Java中的异常主要分为两类:
1.1. 检查异常(Checked Exceptions)
- 定义:检查异常是在编译时被检查的异常,必须在代码中显式处理(通过
try-catch
块或throws
声明)。 - 示例:常见的检查异常包括:
IOException
:处理输入输出时可能发生的异常。SQLException
:处理数据库操作时可能发生的异常。
1.2. 运行时异常(Unchecked Exceptions)
- 定义:运行时异常是在运行时发生的异常,不需要在编译时进行检查,可以选择性地处理。
- 示例:常见的运行时异常包括:
NullPointerException
:尝试访问空对象时抛出。ArrayIndexOutOfBoundsException
:访问数组的非法索引时抛出。ArithmeticException
:发生算术错误(如除以零)时抛出。
2. 异常的层次结构
Java的异常类体系主要由以下几个重要的类组成:
Throwable
:所有错误和异常的超类,包含两种主要子类:Error
:表示严重的错误,通常不应由应用程序捕获(如OutOfMemoryError
)。Exception
:表示程序可以处理的异常。
3. 异常处理机制
Java提供了以下几种方式来处理异常:
-
try-catch
块:用于捕获和处理异常。 -
throws
关键字:用于方法声明中,指示该方法可能抛出某种异常,调用该方法时必须处理这些异常。 -
finally
块:无论是否发生异常,finally
块中的代码都会执行,通常用于释放资源。
4. 自定义异常
开发者可以创建自己的异常类,通过继承Exception
或RuntimeException
来实现。自定义异常可以帮助更清晰地表达特定的错误条件。
2. Java异常处理机制
两种处理方案:try-catch-finally ;throws
3. 异常的两种类型,Error和Exception的区别
1. 定义
- Error:
- 表示严重的错误,通常是指程序无法处理的情况。
- 通常由JVM抛出,表示系统级的错误。
- Exception:
- 表示程序可以处理的异常情况,通常是由应用程序代码引发的。
- 设计为可以捕获和处理,以便程序可以继续执行。
2. 处理
-
Error:
- 通常不应由应用程序捕获,因为它们表示更深层次的系统问题。例如,
OutOfMemoryError
表示JVM没有足够的内存来继续运行。 - 开发者通常不能采取措施来恢复或处理这些错误。
- 通常不应由应用程序捕获,因为它们表示更深层次的系统问题。例如,
-
Exception:
- 应用程序可以捕获和处理异常,允许程序在发生异常时采取相应的措施(例如,重试、记录日志、显示错误消息等)。
- 开发者可以根据需要创建自定义异常并在代码中进行处理。
3. 类型
-
Error:
- 常见的
Error
类包括:OutOfMemoryError
:JVM内存耗尽。StackOverflowError
:栈空间耗尽。NoClassDefFoundError
:类文件未找到。
- 常见的
-
Exception:
- 可进一步分为检查异常和运行时异常:
- 检查异常(Checked Exceptions):编译时检查,必须处理。例如:
IOException
、SQLException
。 - 运行时异常(Unchecked Exceptions):运行时检查,可以选择性处理。例如:
NullPointerException
、ArrayIndexOutOfBoundsException
。
- 检查异常(Checked Exceptions):编译时检查,必须处理。例如:
- 可进一步分为检查异常和运行时异常:
4. 运行时异常与一般异常有何异同?
运行时异常:RuntimeException
-
编译可以通过。在运行时可能抛出。出现的概率高一些;一般针对于运行时异常,都不处理。
一般异常:Exception
-
编译不能通过。要求必须在编译之前,考虑异常的处理。不处理编译不通过。
5. 说几个你常见到的异常
1. NullPointerException
- 描述:当程序尝试访问或操作一个为
null
的对象引用时抛出。 - 示例:
String str = null;
int length = str.length(); // 会抛出NullPointerException
2. ArrayIndexOutOfBoundsException
- 描述:当程序尝试访问数组中不存在的索引时抛出。
- 示例:
int[] arr = {1, 2, 3};
int value = arr[5]; // 会抛出ArrayIndexOutOfBoundsException
3. ArithmeticException
- 描述:当出现算术错误,例如除以零时抛出。
- 示例:
int result = 10 / 0; // 会抛出ArithmeticException
4. ClassNotFoundException
- 描述:当应用程序尝试通过字符串名称加载类,但找不到该类时抛出。
- 示例:
Class.forName("com.example.NonExistentClass"); // 会抛出ClassNotFoundException
6. 说说final、finally、finalize的区别
final
是一种修饰符,控制变量、方法和类的不可变性和继承行为。finally
是一个代码块,始终执行,用于资源清理。finalize
是对象垃圾回收前调用的方法,但现在已过时。
7. 如果不使用try-catch,程序出现异常会如何?
对于当前方法来讲,如果不使用try-catch,则在出现异常对象以后会抛出此对象。如果没有处理方案,就会终止程序的执行。
8. try ... catch捕捉的是什么异常?
Exception。非Error
9. 如果执行finally代码块之前方法返回了结果或者jvm退出了,这时finally块中的代码还会执行吗?
- 如果方法在
finally
前return
,finally
会执行后再返回结果。 - 如果 JVM 在
finally
执行前退出,则finally
不会执行。
10. 在try语句中有return语句,最后写finally语句,finally语句中的code会不会执行?何时执行?如果执行是在return前还是后
具体执行流程如下:
- 执行
try
块,遇到return
时会保存返回值,但不会立刻返回到调用方法。 - 执行
finally
块中的代码。 - 完成
finally
块后,方法才真正返回到调用点,返回之前保存的值。
特别说明
finally
中的代码会在return
前执行,无论try
中是否有return
。- 如果
finally
中有新的return
语句,则它会覆盖try
中的return
。
11. 捕获异常在catch块里一定会进入finally吗?catch里能return吗?catch里return还会进finally吗?在try里return是什么情况?
1. 捕获异常后是否一定会进入 finally
- 是的,无论异常是否被捕获(在
catch
中处理),finally
块都会执行,确保在异常处理后进行必要的清理或资源释放。
2. catch
中是否可以 return
- 可以,
catch
块中可以包含return
语句。 - 即使
catch
中执行了return
,finally
块仍会执行,然后方法才会真正返回。
3. catch
中 return
,finally
是否会执行?
- 是的,
catch
中执行return
后,finally
仍会执行,然后方法才会返回catch
中的return
值。 finally
块中发生的代码总是在try
和catch
块之后执行。
4. 在 try
中 return
,finally
块是否会执行?
- 会执行。如果
try
中包含return
语句,方法会先暂存返回值,再执行finally
块。只有在finally
完成后,方法才会真正返回。 - 如果
finally
中也有return
,则会覆盖try
或catch
中的return
,并返回finally
中的值。
12. throw和throws的区别?
角度1:"形",即使用的格式
throw:使用在方法内部,“throw 异常类的对象”
throws:使用在方法的声明处,"throws 异常类1,异常类2,..."
角度2:"角色"或作用不同。
上游排污,下游治污。
过程1:“抛”
>throw
过程2:“抓”
> try-catch ; throws
13. 子类重写父类抛出异常的方法,能否抛出比父类更高级别的异常类
在 Java 中,子类重写父类方法时,不能抛出比父类方法更高级别的异常。这是因为重写(override)时子类方法必须符合父类方法的契约,以确保在父类引用调用子类方法时不会抛出超出预期的异常。
规则:
- 检查型异常(Checked Exception):
- 子类方法只能抛出与父类方法相同或更低级别的检查型异常,或完全不抛出异常。
- 不能抛出比父类方法更高级别的检查型异常。
- 非检查型异常(Unchecked Exception):
- 子类方法可以自由地抛出非检查型异常(
RuntimeException
及其子类),因为非检查型异常不在方法签名中强制声明。
- 子类方法可以自由地抛出非检查型异常(
13. 如何自定义一个异常?
自定义异常步骤
-
继承
Exception
或RuntimeException
:根据需要选择基类:- 继承
Exception
:用于检查型异常,必须在方法签名中声明或捕获。 - 继承
RuntimeException
:用于非检查型异常,不需要显式声明或捕获。
- 继承
-
构造方法:为自定义异常添加构造方法,通常包括以下几种:
- 默认构造方法。
- 接受错误消息的构造方法。
- 接受错误消息和原因的构造方法。
-
添加自定义逻辑(可选):可以添加额外的属性或方法,以提供更详细的信息。