初识Java异常
何为异常
在Java中,异常是一个不需要的或意外的事件,它发生在程序执行期间,即在运行时,破坏了程序指令的正常流程。异常可以被程序捕获(catch)和处理(handle)。
方法中发生异常时,它会创建一个对象,称为异常对象(Exception Object)。它包含有关异常的信息,例如异常的名称和描述以及异常发生时程序的状态。
导致异常的原因
- 无效用户输入
- 设备故障
- 网络连接丢失
- 物理限制(磁盘内存不足) JVM内存溢出
- 数组角标越界
- 代码错误
- 打开不可用的文件
- 空指针访问
Error(错误) 与 Exception(异常)
异常是程序中的一些错误,但并不是所有的错误都是异常,并且错误有时候是可以避免的。
比如代码少了一个分号,那么运行出来结果是提示是错误 java.lang.Error
如果用System.out.println(11/0),由于用0做了除数,会抛出 java.lang.ArithmeticException
的异常。
Error
Error类及其子类:程序中无法处理的错误,表示程序出现了严重的错误不可恢复的情况,如 Java虚拟机(JVM)内存耗尽、内存泄漏、堆栈溢出错误、库不兼容、无限递归等。
Virtual MachineError(虚拟机运行错误)、NoClassDefFoundError(类定义错误)等。比如 OutOfMemoryError
:内存不足错误;StackOverflowError
:栈溢出错误。此类错误发生时,JVM 将终止线程。
错误通常超出了程序员的控制范围,当此类错误发生时,应用程序不应该去处理此类错误。
Error 和 Exception的区别
错误不是异常
Error
表示一个严重的问题,一个合理的应用程序不应该试图捕捉它
Exception
表示程序本身可以捕获并且可以处理的异常
异常的层次结构
Java 通过 AP I中 Throwable
类的众多子类描述各种不同的异常。因而,Java异常都是对象,是Throwable子类的实例,描述了出现在一段编码中的 错误条件。当条件生成时,错误将引发异常。
所有异常和错误类型都是Throwable类的子类,二者都是 Java 异常处理的重要子类,各自都包含大量子类。Throwable
是层次结构的基类。
一个分支由 Exception
领导。这个类用于用户程序应该捕获的异常情况。
Java运行时系统(JVM)使用另一个分支 Error
来指示与运行时环境本身(JRE)有关的错误。
异常的种类
Exception 分为两类:
-
Build-in Exception(内置异常):
- 运行时异常(Unchecked Exception)
- *编译时异常(Checked Exception)
-
User-Defined Exceptions(用户自定义异常)
Build-in Exception
内置异常是Java库中可用的异常
运行时异常
RuntimeException
类及其子类异常,如 NullPointerException
(空指针异常)、IndexOutOfBoundsException
(下标越界异常) 表示 JVM在运行期间可能出现的异常。
这些异常是不受检异常(Unchecked),程序中可以选择捕获处理,也可以不处理。若不进行处理,JVM会默认处理:把异常的名称,原因,位置等信息输出在控制台,但是程序就不能继续执行了。
这类异常很普遍,若全处理可能会对程序的可读性和运行效率产生影响。
运行时异常的特点是 Java 编译器不会检查它,当程序中可能出现这类异常,即使没有用 try-catch
语句捕获它,也没有用 throws
子句声明抛出它,也会编译通过。
-
若这些异常一般是由程序逻辑错误引起的,程序应该从逻辑角度尽可能避免这类异常的发生。
-
如果产生运行时异常,需要通过修改代码来进行避免。例如,若会发生除数为零的情况,则需要通过代码避免该情况的发生!
-
RuntimeException 异常会由JVM自动抛出并自动捕获(就算我们没写异常捕获语句运行时也会抛出错误),此类异常的出现绝大多数情况是代码本身有问题,应该从逻辑上去解决并改进代码。
非运行时异常(编译时异常)
RuntimeException
以外的异常(包括Error),类型上都属于 Exception
类及其子类。必须手动在代码里添加捕获语句来处理该异常。
要么使用 try-catch
捕获,要么使用方法签名中用 throws
关键字抛出。如果不处理,程序就不能编译通过。
如 IOException
、SQLException
等以及 用户自定义的Exception异常
,一般情况下不自定义检查异常。
User-Defined Exceptions
有时,Java 中的内置异常无法描述特定情况。在这种情况下,用户还可以创建异常。
Java 中异常处理的优点如下:
-
完成程序执行的规定
-
易于识别的程序代码和错误处理代码
-
错误的传播
错误传播是指错误或异常在程序中从一层代码传递到另一层代码的过程。当代码块或函数中出现错误时,可以通过捕获错误在该级别进行处理,也可以将错误传播到程序的更高级别进行进一步处理
通过传播错误,可以在不同的抽象层次上控制和管理程序的执行。例如,某些错误可能会在函数内部局部处理,而其他错误可能会传播到主函数甚至应用程序的用户界面。
错误传播允许更好的错误处理和恢复策略。它支持关注点分离和在适当级别处理错误的能力,从而改进代码的模块化和可维护性。它还提供了对错误原因的更好的可见性,并有助于识别和修复问题
-
准确的错误报告
-
更准确地识别错误类型
Java 常见异常
在 Java 中提供了一些异常用来描述经常发生的错误,对于这些异常,有的需要程序员进行捕获处理或声明抛出,有的是由 Java 虚拟机自动进行捕获处理。Java 中常见的异常类:
RuntimeException
-
java.lang.
ArrayIndexOutOfBoundsException
数组索引越界异常。当对数组的索引值为负数或大于等于数组大小时抛出。 -
java.lang.
ArithmeticException
算术条件异常。譬如:整数除零等。 -
java.lang.
NullPointerException
空指针异常。当应用试图在要求使用对象的地方使用了null时,抛出该异常。
譬如:调用null对象的实例方法、访问null对象的属性、计算null对象的长度、使用throw语句抛出null等等 -
java.lang.
ClassNotFoundException
找不到类异常。当应用试图根据字符串形式的类名构造类,而在遍历CLASSPATH
之后找不到对应名称的 class 文件时,抛出该异常。 -
java.lang.
NegativeArraySizeException
数组长度为负异常 -
java.lang.
ArrayStoreException
数组中包含不兼容的值抛出的异常 -
java.lang.
SecurityException
安全性异常 -
java.lang.
IllegalArgumentException
非法参数异常
IOException
-
IOException
:操作输入流和输出流时可能出现的异常。 -
EOFException
文件已结束异常 -
FileNotFoundException
文件未找到异常
其他
-
ClassCastException
类型转换异常类 -
ArrayStoreException
数组中包含不兼容的值抛出的异常 -
SQLException
操作数据库异常类 -
NoSuchFieldException
字段未找到异常 -
NoSuchMethodException
方法未找到抛出的异常 -
NumberFormatException
字符串转换为数字抛出的异常 -
StringIndexOutOfBoundsException
字符串索引超出范围抛出的异常 -
IllegalAccessException
不允许访问某类异常 -
InstantiationException
当应用程序试图使用 Class 类中的newInstance()
方法创建一个类的实例,而指定的类对象无法被实例化时,抛出该异常
打印异常信息的方法
printStackTrace()
该方法以以下格式打印异常信息:异常名称,异常描述,堆栈跟踪。
import java.io.*
class Demo{
public static void main(String []args){
int a=5 , b=0;
try{
System.out.print(a/b);
}
catch(ArithmeticException e){
e.printStackTrace();
}
}
}
//打印结果:
java.lang.ArithmeticException: / by zero
at GFG.main(File.java:10)
toString()
该方法以 “异常名称:异常描述” 的格式打印异常信息
import java.io.*
class Demo{
public static void main(String []args){
int a=5 , b=0;
try{
System.out.print(a/b);
}
catch(ArithmeticException e){
System.out.print(e.toString());
}
}
}
//打印结果:
java.lang.ArithmeticException: / by zero
getMessage()
该方法只打印异常的描述
import java.io.*
class Demo{
public static void main(String []args){
int a=5 , b=0;
try{
System.out.print(a/b);
}
catch(ArithmeticException e){
System.out.print(e.getMessage());
}
}
}
//打印结果:
// by zero