文章目录
异常与异常处理
异常或异常事件指的是程序在执行中出现的问题。当异常发生时程序正常执行流程就会被打断,程序或应用非正常终止。这种情况不是我们想要的,因此,程序中处理异常非常有必要。
异常可以由很多原因引起,下面列出了几种会出现异常的场景:
- 用户输入了无效的数据
- 打开文件时却找不到文件
- 网络连接断开或JVM内存溢出。
异常分类
异常有些是由用户错误的行为引起的,有些是因为程序员失误,甚至有些是因为物理故障导致的。
基于此,我们可以将异常分为三类,掌握它们可以帮助我们理解Java是如何处理异常的。
- 检查型异常(Checked exceptions)
- 非检查型异常(Unchecked exceptions)
- 错误(Error)
检查型异常
检查异常指的是编译器在编译代码时提示的异常,其也被称为编译时异常。这类异常不能被简单地忽视,程序员应该在程序编译后处理完这些异常。
举个例子,如果你在程序里使用FileReader类来从一个文件中读取数据时,如果构造器中传入的文件在对应路径中不存在,那么就发生了文件找不到异常(FileNotFoundException),编译器就会提示程序员去处理这个异常。
程序实例
import java.io.File;
import java.io.FileReader;
public class FilenotFound_Demo {
public static void main(String args[]) {
File file = new File("E://file.txt");
FileReader fr = new FileReader(file);
}
}
当我们运行上面的程序时,会提示出现异常:
C:\>javac FilenotFound_Demo.java
FilenotFound_Demo.java:8: error: unreported exception FileNotFoundException; must be caught or declared to be thrown
FileReader fr = new FileReader(file);
^
1 error
需要注意:由于FileReader类中的read()和close()方法会抛出IOException,因此我们会看到,编译器在抛出FileNotFoundException的同时也会抛出IOException。
非检查型异常
非检查异常指的是在执行程序时出现的异常,也被称为运行时异常。其中包括编程错误,例如逻辑错误或API使用不当。在编译时,运行时异常是被忽略的。
举个例子,如果你在程序中声明了大小为5的数组,并尝试读取数组中第6个元素,那么就会产生一个ArrayIndexOutOfBoundsException异常。
程序实例
public class Unchecked_Demo {
public static void main(String args[]) {
int num[] = {
1, 2, 3, 4};
System.out.println(num[5]);
}
}
当我们运行上面的程序时,会提示出现异常:
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 5
at Exceptions.Unchecked_Demo.main(Unchecked_Demo.java:8)
错误
错误(Errors)不是异常,而是超出用户或程序员可控范围的问题。错误通常不会在代码中进行处理,因为我们几乎没法对错误做不了什么。比如说,当出现栈溢出的时候,错误就发生了。程序在编译的时候也会忽略错误。
异常层次
所有的异常类都是java.lang.Exception类的子类。而Exception类是Throwable类的子类。除了异常类之外,还有另一个名为Error的子类,它是从Throwable类派生的。
错误是发生严重故障时发生的异常情况,不会由Java程序处理。运行环境产生错误时生成错误信息。例如,JVM内存溢出。一般来说,程序无法从错误中恢复。
Exception类有两个比较重要的子类:IOException类和RuntimeException类。
– 下面是最常见的检查型(checked)和非检查型(unchecked)的Java内置异常列表。
异常类中的方法
下表列出的是Throwable类中比较重要的几个方法。
序号 | 方法&描述 |
---|---|
1 | public String getMessage() 返回异常的详细信息。 |
2 | public Throwable getCause() 返回异常的异常的起因。 |
3 | public String toString() 返回异常类和getMessage()方法返回的内容。 |
4 | public void printStackTrace() 打印toString()方法的内容以及跟踪到堆栈的错误输出流。 |
5 | public StackTraceElement [] getStackTrace() 返回一个包含堆栈跟踪的每个元素的数组。 |
6 | public Throwable fillInStackTrace() 用当前堆栈跟踪填充此Throwable对象的堆栈跟踪,并添加到堆栈跟踪中的所有先前信息。 |
捕获异常
一种捕获异常的方式是结合使用try和catch关键字。try/catch语句将可能产生异常的代码包围起来。try/catch语句中包含的代码可以认为是被保护的代码,使用try/catch语句的语法如下:
try {
//被保护的代码块
} catch (ExceptionName e1) {
//catch块
}
容易出异常的代码放在try语句块中,当发生异常时,异常由catch语句块来进行处理。每个try语句块后面应该马上跟上catch语句块或finally语句块。
catch语句块包含声明需要捕获的异常的类型。如果在被保护的代码中发生异常时,程序就会检查catch语句块中指定的异常的类型是否和出现的异常一致。如果一致,那么就会执行catch语句块中的代码,相应的异常对象就和方法中的参数一样被传入catch语句块中。
程序实例
下面程序声明了大小为2的数组,而后面的代码尝试访问数组的第3个元素,这会导致出现异常。
// File Name : ExcepTest.java
import java.io.*;
public class ExcepTest {
public static void main(String args[]) {
try {
int a[