目录
什么是异常?
在日常生活中,一个人看起来心情十分不好,这相比于他平常活泼开朗的状态算是一个不正常状态,这相当于是一个异常状态,在Java中,执行程序过程中发生的不正常行为就称为异常.
异常的体系结构
异常的种类非常多,为了对不同的异常或者错误进行很好的分类管理,Java内部维护了一个异常的体系结构:
Throwable:它是异常体系的顶层类,其派生出两个子类:Error和Exception类;
Error:指的是Java虚拟机无法解决的严重问题,比如:JVM错误、资源耗尽等,例如:StackOverFlowError和OutOfMemoryError.
Exception:异常出现后程序员可以通过代码进行处理,可以使程序继续运行.
异常的分类
异常的发生可能是在程序运行时,也可能发生在编译时,根据发生的时机不同,我们将异常分为编译时异常和运行时异常.
编译时异常
在程序编译时发生的异常称为编译时异常,也称为受查异常.
例如下列代码:
public class TestDemo {
private String test;
@Override
public TestDemo clone(){
return (TestDemo)super.clone();
}
}
该异常称为即为编译时异常.
运行时异常
在程序执行期间发生的异常称为运行时异常.RunTimeException以及其子类对应的异常都称为运行时异常.
常见的几种运行时异常:
①算术异常
public static void main(String[] args) {
System.out.println(10 / 0);
}
上述代码在运行时会抛出如下异常,该异常称之为算术异常.
②数组越界异常
public static void main(String[] args) {
int[] arr = {1, 2, 3, 4, 5};
System.out.println(arr[10]);
}
上述代码在运行时会抛出如下异常,该异常称之为数组越界异常.
③空指针异常
public static void main(String[] args) {
int[] arr = null;
System.out.println(arr.length);
}
上述代码在运行时会抛出如下异常,该异常称之为空指针异常.
通过上述代码,可以观察到在Java中不同类型的异常,都有与其对应的类来描述。
如何处理异常?
在Java中,异常处理主要的5个关键字:throw、try、catch、final、throws.
防御式编程
LBYL(事前防御型):在操作前就做好充足的准备.
例如:
boolean ret = false;
ret = 游戏登录();
if(!ret){
处理登录游戏错误异常;
return;
}
ret = 开始匹配
if(!ret){
处理开始匹配错误;
return;
}
……
EAFP(事后认错型) :在遇到异常后再进行处理.
例如:
try{
登录游戏();
开始匹配();
……
}catch(登录游戏异常){
处理登录游戏异常;
}catch(开始匹配异常){
处理开始匹配异常;
}
……
异常的抛出和捕获
异常的抛出
在编写程序时,如果程序中出现错误,需要将错误的信息告知调用者,在Java中,可以借助throw关键字抛出一个指定的异常对象,将错误信息告知给调用者.语法如下:
throw new XXXException("这里发现了一个异常");
注意事项:
1.throw必须写在方法体内部;
2.抛出的异常必须是Exception或Exception的子类对象;
3.如果抛出的是RunTImeException或其子类,则可以直接交给JVM来处理;
4.如果抛出的是编译时异常,则必须先处理;
5.异常一旦抛出,该异常后面的代码将不会继续执行.
异常的捕获
异常的捕获有两种方式:异常声明throws和try-catch捕获处理.
方式①:异常声明throws
处在方法声明时参数列表之后,当方法中抛出异常且用户不想处理时,此时就可以借助throws将异常抛给方法调用者来处理.
语法格式:
修饰符 返回值类型 方法名(参数列表) throws 异常类型1, 异常类型2...{
}
方式②:try-catch捕获并处理
throws对异常并没有真正处理,而是仅将异常报告抛出给方法调用者,由调用者处理.如果要对异常进行真正处理,就需要用到 try-catch语句.
finally
在写程序时,有些特定的代码,无论是否发生异常,都需要被执行,比如程序中打开资源:网络连接、数据库连接、IO流等,在程序正常或者异常退出时,必须对资源进行回收.另外,因为异常会引发程序的跳转,可能导致有些语句执行不到,finally就是用来解决这个问题的.
语法格式:
try{
……
}catch(异常类型 e){
对捕获到的异常进行处理
}finally{
该处语句一定会被执行
}
finally有什么作用?
finally中的代码一定会被执行,一般在finally中进行一些资源的清扫工作.
finally执行的时机是在方法返回之前(try或catch中如果有return,则会在这个return之前执行finally),但是如果finally中有return语句,那么就会执行finally中的return,从而不会执行到try中原有的return.
自定义异常“用户登录”
Java中虽然内置了很多的异常类,但是并不能完全表示实际开发中所遇到的异常,此时就需要我们来定义出自定义异常类.
import java.util.Scanner;
class UserNameError extends Exception{
public UserNameError(String message){
super(message);
}
}
class PasswordError extends Exception{
public PasswordError(String message){
super(message);
}
}
public class Login {
private static final String name = "admin";
private static final String password = "123456";
public static void loginInfo(String userName, String passWord) throws UserNameError,
PasswordError{
if(!userName.equals(name)){
throw new UserNameError("用户名错误");
} else if(!passWord.equals(password)){
throw new PasswordError("密码错误");
} else{
System.out.println("登陆成功");
}
}
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.print("请输入用户名:>");
String userName = scanner.nextLine();
System.out.print("请输入密码:>");
String passWord = scanner.nextLine();
try{
loginInfo(userName, passWord);
}catch(UserNameError | PasswordError e){
System.out.println(e.getMessage());
}
}
}