一.什么是异常?
在 Java 中,异常是在程序运行期间发生的不正常情况或错误。
二.常见的异常情况
1.算法异常
、 因为0不能作为被除数,所以报出了算法异常。
Java虚拟机处理了异常,这个ArithmeticException就表示的是算法的异常,出现异常之后,异常后面的代码都不会被执行。
2.空指针异常
因为arr数组指向null是一个空指针,没有指向任何对象,所以不能赋值。
这个NullPointerException就表示的是空指针异常。
3.数组越界异常
指定的数组大小是5,此时你在输出语句中访问到下标为10的元素,此时数组就越界了。
这个ArrayIndexOutOfBoundsException就表示的是数组越界异常。
4.编译时异常
这种是在编译中就出现的异常,必须立刻处理,否则代码无法运行。
三.异常的体系
以上是Java的异常体系结构图。
前三个表示Throwable父类派生出了两个异常的子类
1.异常的分类
异常可以分为两类:受检异常(Checked Exception)和非受检异常(Unchecked Exception)。
受检异常是在编译阶段必须进行处理的异常,比如 IOException
、SQLException
等,如果程序中可能抛出受检异常,那么必须在方法声明中用 throws
关键字声明或者在方法内部使用 try-catch
语句块来捕获和处理异常。
非受检异常是在运行时可能发生的异常,例如 NullPointerException
、ArrayIndexOutOfBoundsException
等,程序可以选择处理也可以不处理,会交给Java虚拟机处理。
当异常发生时,如果没有被捕获和处理,程序将会非正常终止。通过使用异常处理机制,能够增强程序的健壮性和容错性,使程序在遇到错误时能够以一种可控的方式做出响应,而不是直接崩溃。例如,可以记录错误信息、进行错误恢复或者向用户给出友好的提示。
四.异常的处理
1.try-catch语句
通过try-catch语句来处理异常,此时在try语句中发现了异常,此时程序并不会立即停止而是通过catch语句处理和打印出来异常,此时后面的语句hahaha还会被执行。
2.try-catch-finally语句
和上面的try-catch语句的区别接收多了个finally语句,它相当于一个程序结束语句,一定会执行。
上面这个代码,是算法异常,当在你的catch语句中并没有捕捉算法异常的语句,但是finally中的语句还是会执行。
finally语句的主要作用是:
-
释放资源:比如关闭文件、释放数据库连接、关闭网络连接等。确保这些资源在使用后能够被正确释放,以避免资源泄漏。
-
执行必要的清理操作:无论程序执行情况如何,都需要执行的一些收尾工作,例如清除临时数据、重置某些状态等。 下面是一个finally不同于其他的方面。
-
请问a的结果是多少? 根据我们以前的认为,先执行try代码,返回了10,sum就结束了,所以a是10,但是这是错误的,它不同于以前传统的,它返回的应该是20.
3.throws关键字
-
声明方法可能抛出的异常类型:当一个方法内部的代码可能会抛出某些类型的异常,而这个方法本身又不打算处理这些异常时,可以在方法的声明处使用
throws
关键字来列出这些异常类型。这向方法的调用者表明,调用这个方法时需要准备处理这些可能抛出的异常。 -
明确方法的责任边界:通过
throws
声明异常,明确了方法的实现者不负责处理这些异常,而将处理异常的责任转移给了方法的调用者。这有助于在代码的不同层次之间划分异常处理的职责。 throws在什么情况必须使用呢? -
方法内部调用了会抛出受检异常(Checked Exception)的方法,并且没有在当前方法内部通过
try-catch
语句块来捕获和处理这些异常。 -
方法实现的逻辑本身可能会产生受检异常,并且决定不在当前方法内处理这些异常。
此时test抛出的是一个受检异常,如果想要调用test方法,就必须在那个调用函数中也声明受检异常。
或者这样处理。
4.throw关键字
throw抛出异常:
通过throw关键字抛出异常,此时就很明确,你的异常就是算法异常,即使不加throw语句也会通过Java虚拟机来抛出异常,为什么还要加throw语句呢?
使用 throw
语句有以下几个重要原因:
-
主动抛出异常以控制程序流程:在某些特定的条件下,根据程序的逻辑判断,您可能希望主动抛出一个异常来中断当前的执行流程,并将异常传递给上层调用者进行处理。这使得您可以更精确地控制程序在特定情况下的行为。
-
自定义异常信息:通过
throw
语句,您可以创建一个新的异常对象,并为其提供自定义的错误消息,这有助于更清晰地描述异常发生的具体情况,方便后续的调试和错误处理。 -
封装和隐藏底层细节:在复杂的系统中,可能会有多个层次的方法调用。通过在适当的中间层方法中使用
throw
抛出特定的自定义异常,可以将底层的复杂错误情况以更易于理解和处理的方式呈现给上层的业务逻辑。 -
遵循异常处理的设计原则:在一些设计良好的代码结构中,明确地抛出异常有助于提高代码的可读性和可维护性,使得异常处理的逻辑更加清晰和可预测。
例如,如果您正在编写一个验证输入数据的方法,当输入不符合特定规则时,您可以使用 throw
抛出一个有意义的异常,而不是依赖于底层可能自然产生的异常。
综上所述,虽然 Java 虚拟机在某些情况下会自动抛出异常,但主动使用 throw
语句可以让您更好地管理和控制程序中的异常情况,提高代码的质量和可维护性。
此时throw关键字抛完异常之后,代码就停止,后面不能有其他的语句,否则就会报错。
throw和throws的区别
-
作用不同:
throw
用于在方法体内主动抛出一个异常对象。throws
用于在方法声明处声明该方法可能抛出的异常类型,它是把异常交给调用那个方法的人处理。
-
语法位置不同:
throw
出现在方法内部,后跟要抛出的异常对象。throws
出现在方法声明的后面,后跟异常类型列表。
-
数量不同:
throw
每次只能抛出一个异常对象。throws
可以声明抛出多个异常类型。
-
处理方式不同:
- 使用
throw
抛出异常后,后续代码通常不会继续执行(除非在try-catch
块中)。 - 声明
throws
只是告知调用者该方法可能抛出异常,调用者需要处理,但方法本身不负责处理。
- 使用
5.自定义异常
就是自己定义的异常。
第二张图片就是我自己写的一个自定义异常,里面的方法,你可以直接使用父类的,按着Ctrl点击那个RuntimeException
出现了这个,根据需求选择可以直接使用的。
我使用的是上面这两个,改一下名字就可以直接使用。
Exception是RuntimeException的父类,为什么会报错呢?
因为根据体系图我们可以知道,Exception包括运行时异常和非运行时的异常,非运行时的异常必须在运行之前就声明异常。
这样就不报错了,或者通过try-catch语句处理那个非运行的异常也可以。
这样处理也不会报错。
五.结束语
感谢大家的查看,希望可以帮助到大家,做的不是太好还请见谅,其中有什么不懂的可以留言询问,我都会一一回答。
感谢大家的一键三连。