异常相关问题
1、什么是异常
异常是指程序在运行过程中出现的非正常情况。
2、运行时异常、设计时异常
运行时异常(Runtime Exception
):
运行时异常指的是在程序运行过程中可能会发生的异常情况。这些异常通常是由于程序逻辑错误、输入数据问题、资源不足等原因引起的。在大多数编程语言中,运行时异常不需要在代码中显式处理,但如果不加以处理,会导致程序崩溃或产生不稳定的行为。
例如,在Java中,运行时异常是继承自RuntimeException
类的异常,比如NullPointerException
(空指针异常)、IndexOutOfBoundsException
(下标越界异常)、ArithmeticException
(算术异常)等。这些异常通常表示程序中的逻辑错误,需要通过改进代码逻辑来避免它们的发生。
设计时异常(Compile-time Exception
):
设计时异常指的是在编译代码时可能会发生的异常情况。这些异常通常是由于语法错误、类型不匹配等问题引起的,无法通过代码逻辑的改变来解决。编译器会在编译过程中捕获并报告这些异常,阻止代码成功编译。
例如,在Java中,如果你在代码中使用了一个未定义的变量,或者将类型不匹配的值赋给变量,编译器就会报告错误,阻止代码编译通过。
总结:
- 运行时异常是在程序运行过程中可能出现的异常情况,通常由程序逻辑错误、输入问题等引起,可以通过改进代码逻辑来避免。
- 设计时异常是在编译代码时发现的异常情况,通常由于语法错误或类型不匹配等问题引起,需要在编码阶段修复。
要写出健壮且稳定的程序,需要处理可能的运行时异常,并确保在设计和编码阶段避免设计时异常。
3、如何处理异常
Java的异常处理机制依靠以下5个关键字:try
、catch
、finaly
、throw
、throws
。这些关键字提供了两种异常处理方式。
- 用try 、catch、finaly来捕获和处理异常
try
块中包含可能会抛出异常的代码。catch
块用于捕获并处理指定类型的异常。- ``finaly`块中的代码无论是否发生异常都会被执行,通常用于释放资源或清理操作。
- 使用throw、throws来抛出异常
throw
关键字用于手动抛出异常对象。- ``throws`关键字用于在方法声明中指定可能抛出的异常类型,表示该方法可能会抛出该类型的异常,由调用者来处理
4、不受检异常与受检异常
不受检异常:
也称为unchecked
异常,包括RuntimeException
及其所有子类。对这类异常并不要求强制进行处理。
受检异常:
也称为checked
异常,指除了不受检异常外,其他继承自Exception
类的异常。对这类异常要求在代码中进行显式处理
5、构造方法可以抛出异常吗?如果抛出异常,对父类、子类产生的影响有哪些?
在Java中,构造方法是可以抛出异常的。如果在子类的构造方法中抛出异常,会影响到父类和子类的实例化过程。
- 对父类的影响: 如果父类的构造方法抛出异常,子类在实例化时会调用父类的构造方法,因此子类的构造方法也会受到影响。子类的构造方法可以选择处理异常、捕获异常或继续抛出异常,但需要注意的是,如果子类的构造方法抛出异常,那么子类对象也无法被正确地创建和初始化。
- 对子类的影响: 如果子类的构造方法抛出异常,会影响到子类对象的实例化过程。子类的构造方法可以选择处理异常、捕获异常或继续抛出异常。如果子类的构造方法抛出了异常并且未被捕获,那么子类对象的创建将会失败。
需要注意的是,构造方法的异常处理在继承层次中会涉及到异常传递、异常捕获和异常处理的问题。为了保证程序的稳定性和可读性,通常建议在构造方法中避免抛出过多的异常,尽量在构造方法内部处理异常,或者在必要的情况下使用异常捕获。
总之,构造方法是可以抛出异常的,但在处理异常时需要考虑父类和子类之间的关系,以及对象的正确创建和初始化。
6、throw和throws的区别
作用不同:
throw
用于程序员自行产出并抛出异常,throws
用于声明该方法内抛出了异常。
使用位置不同:
throw
位于方法体内容,可以作为单独的语句使用;throws
必须跟在方法参数列表的后面,不能单独使用。
内容不同:
throw
抛出一个异常对象,只能是一个;throws
后面跟异常类,可以跟多个。
7、可以抛出error异常吗 ?
是的,可以在构造方法中抛出Error
异常,但是通常不推荐这么做。Error
是Throwable
类的一个子类,它表示严重的系统错误,通常是由于虚拟机(JVM
)运行环境出现问题导致的,例如内存溢出(OutOfMemoryError
)、栈溢出(StackOverflowError
)等。与Exception
不同,Error
通常不应该被捕获和处理,因为这些错误一般表示了无法恢复的情况,程序通常无法继续正常运行。
如果在构造方法中抛出Error
异常,会导致对象的实例化被中断,无法成功创建对象。这可能会影响程序的正常执行,因此在构造方法中抛出Error
异常不是一个好的做法。
相反,通常建议在构造方法中抛出更具体的Exception
子类,或者在构造方法内部处理异常情况,以确保对象的正确初始化和程序的稳定性。如果遇到了严重的系统错误(Error
),程序的通常做法是终止程序并进行修复,而不是在代码中捕获和处理这些错误。
8、为什么try中有return,catch中有return,final有,最后返回的是finally里的return
当try、catch中有return时,finally中的代码依然会继续执行。finally是在return后面的表达式运算之后执行的,此时并没有返回运算之后的值,而是把值保存起来,不管finally对该值做任何操作,都会返回该值。
所以,如果try中有return,catch中有return,finally中有return,最后返回的是finally里的return
9、为啥要自定义异常?如何自定义异常?
自定义异常原因:
自定义异常类可以使代码更加规范、统一和优雅。在Java中,不同的异常类分别表示着某一种具体的异常情况,但是在开发中总是有些异常情况是没有定义好的,此时我们可以根据自己业务的异常情况来定义异常类。
自定义异常类只需从Exception类或者它的子类派生一个子类即可。自定义异常类如果继承Exception类,则为受检查异常,必须对其进行处理;如果不想处理,可以让它们继承RuntimeException
类,这样就不需要在方法中使用try-catch块来捕获这些异常了。
步骤:
- 定义异常类,并继承
Exception
或者RuntimeException
。 - 编写异常类的构造方法,向父类构造方法传入异常描述信息,并继承父类的其他实现方法。
- 实例化自定义异常类,并在程序中使用throw抛出。