异常的处理
什么是异常
java中不正常的行为称为异常,不同类型的异常都有对应的类描述。
异常的种类
异常体系结构

运行异常(非受查异常)
RuntimeException及其子类表示运行异常,表示在程序运行期间发生的异常。
编译异常(受查异常)
Exception的子类除了RuntimeException及其子类都是编译异常的类, 表示在编译期间发生的异常
异常的关键字
抛出异常
throw
//一个获取数组中任意位置元素的方法
public static int getElement(int[] array, int index){
if(null == array){
throw new NullPointerException("传递的数组为null");
}
if(index < 0 || index >= array.length){
throw new ArrayIndexOutOfBoundsException("传递的数组下标越界");
}
return array[index];
}
public static void main(String[] args) {
int[] array = {1,2,3};
getElement(array, 3);
}
1.抛出的只能是Exception类及其子类的异常(Error的异常会导致计算机程序崩溃,jvm也处理不了,不用抛给他);
2.如果是编译时异常,得及时处理,如果是运行时异常不用处理,交给JVM处理;
3.throw只能写在方法体内部;
4.发生异常,异常后面的代码无法执行。
捕获异常
捕获异常,对异常的具体处理;
thows
作用:
声明异常, 处在方法参数列表之后,当方法中抛出编译时异常,但不想立马处理该异常,就可以借助throws提醒方法的调用者来处理 。即当前不处理异常,让方法调用者处理。
编译异常:
这类异常要么在方法中使用 try-catch
块捕获处理,要么通过 throws
关键字声明抛出。它们通常是外部因素引起的异常,比如文件未找到、网络连接失败等。
运行异常:
继承自 RuntimeException
的异常属于运行时异常。虽然也可以使用 throws
来声明,但不是必需的。常见的例子包括 NullPointerException
。
thow和thows区别
特性 | throw | throws |
---|---|---|
用途 | 主动抛出一个具体的异常对象 | 声明方法可能抛出的异常类型 |
位置 | 方法体内使用 | 方法签名部分使用 |
语法 | throw 异常对象; | throws 对象1,对象2... |
数量 | 一次只能抛出一个异常 | 可以声明多个异常类型 |
处理 | 必须立即处理或向上传递 | 只是声明,不实际抛出异常 |
try catch
//读取配置文件,如果配置文件名字不是指定名字,抛出异常,调用者进行异常处理
public class Config {
File file;
public void openConfig(String filename) throws FileNotFoundException{
if(!filename.equals("config.ini")){
throw new FileNotFoundException("配置文件名字不对");
}
// 打开文件
}
public void readConfig(){
}
public static void main(String[] args) {
Config config = new Config();
try {
config.openConfig("config.txt");
System.out.println("文件打开成功");
} catch (IOException e) {
// 异常的处理方式
//System.out.println(e.getMessage()); // 只打印异常信息
//System.out.println(e); // 打印异常类型:异常信息
e.printStackTrace(); // 打印信息最全面
}
// 一旦异常被捕获处理了,后面的代码继续执行
System.out.println("异常如果被处理了,这里的代码也可以执行");
}
}
finally
finally{} 代码块里的代码一定会被执行。写程序时有些代码不论是否发生异常,都需要执行,如程序中打开的资源:网络连接,数据库连接,IO流等。在程序正常或者异常退出时,都要对资源进行回收。异常会引发程序的跳转,可能有些语句执行不到,就需要用到finally。
流的自动关闭机制
在 Java 7 引入的 try-with-resources 语句中,当在try() 中开启的流(或其他实现了AutoCloseable接口 的资源,如InputStream,OutputStream等)出现异常时,系统会自动关闭资源。
try (InputStream is = new FileInputStream("file.txt")) {// 使用流
}catch(){//异常处理};
-------------------------------------// 编译器生成的等效代码,也是在finally中关闭资源
InputStream is = new FileInputStream("file.txt");
try {// 使用流
} finally {if (is != null) {is.close(); // 自动调用close()}
}
自定义异常
java中虽然定义的异常类型很多,但没有与实际情况符合的异常时,可以自定义异常类,让其继承Exception或RuntimeException 。
继承Exception默认是编译时异常,继承RuntimeException默认是运行时异常。
//实现一个用户登陆功能
public class LogIn {
private String userName = "admin";
private String password = "123456";
public static void loginInfo(String userName, String password) {
if (!userName.equals(userName)) {
}
if (!password.equals(password)) {
}
System.out.println("登陆成功");
}
public static void main(String[] args) {
loginInfo("admin", "123456");
}
}
//此时我们在处理用户名密码错误的时候可能就需要抛出两种异常.
我们可以基于已有的异常类进行扩展(继承), 创建
和我们业务相关的异常类.
//具体方式:
1. 自定义异常类,然后继承自Exception 或者 RunTimeException
2. 实现一个带有String类型参数的构造方法,参数含义:出现异常的原因
class UserNameException extends Exception {
public UserNameException(String message) {
super(message);
}
}
class PasswordException extends Exception {
public PasswordException(String message) {
super(message);
}
}
//将代码改成
public class LogIn {
private String userName = "admin";
private String password = "123456";
public static void loginInfo(String userName, String password)
throws UserNameException,PasswordException{
if (!userName.equals(userName)) {
throw new UserNameException("用户名错误!");
}
if (!password.equals(password)) {
throw new PasswordException("用户名错误!");
}
System.out.println("登陆成功");
}
public static void main(String[] args) {
try {
loginInfo("admin", "123456");
} catch (UserNameException e) {
e.printStackTrace();
} catch (PasswordException e) {
e.printStackTrace();
}
}
}