JAVA——异常
异常概念
在java中,程序执行过程中发生的不正常行为称为异常。如计算数的时候分母赋个零来计算,会发生算数异常(ArithmeticException);数组越界时也会异常(ArraylndexOutOfBoundsException),
还有访问空指针也会有异常(NullPointerException),那发生异常后该怎么办?
用于异常处理的有五个关键字:throw,throws,try,cath,finally,throws
异常体系结构
如图:
Throwable是异常体系的顶层类,也是所有异常的父类,派生出俩个重要的异常子类:Error和Exception。
Error:指的是连java虚拟机都无法解决的严重问题,如java内部错误,资源耗尽等。
Exception:可以由程序员通过代码解决的异常,可以使程序继续运行。
Exception也分为运行时异常(非受查异常)和编译时异常(受查异常),编译时异常指的是在编译期间就发生的异常,需要程序员通过抛出并处理;运行时异常指的是程序在编译通过后运行时发生的异常,抛出后通常由jvm来处理。
异常抛出
throw抛出异常
格式:throw new ~~Exception(“异常产生的原因”);【()括号内是String类】
在编写程序时,如果程序中有错误,就需要使用throw关键字来抛出一个异常,将错误信息告诉调用者,如:
注意事项:
throw必须写在方法体内部
抛出的对象必须为Exception或它的子类对象
抛出的是运行时异常,可以不用处理,交给JVM来处理
抛出的是编译时异常,用户必须处理
异常一旦抛出,后续代码不会执行
异常捕获
throws异常声明
格式:修饰符 返回值类型 方法名(参数列表) throws 异常类型1,异常类型2...{}
throws关键字是用来声明异常的,相当于可以借助throws将异常抛出给调用者,由调用者进行处理,若是调用者不进行处理,则可以继续使用throws抛出,则会继续返回给上一层调用关系,若是都不处理,则会给JVM来进行处理,程序就会异常停止。
throws通常跟在方法的参数列表后面声明异常
注意事项:
throws必须跟在方法的参数列表之后
声明的异常必须是Exception或它的子类
方法内部若是抛出了多个异常,throws后面可以跟多个异常类型,用逗号隔开,若是抛出的多个异常具有继承关系,声明父类即可。
try-catch捕获并处理
格式:try{
可能出现异常的代码
}catch(需要捕获的异常类型 e){
try中代码发生异常且和需要捕获的异常类型一致或是该异常类型的基类(父类),则会执行catch
}catch(需要捕获的类型2 e2){}....
相比于throws只能声明异常,try—catch不仅能声明异常还能处理异常,可以捕获一个或多个异常。
由上面俩幅图我们得出一些结论:
try块内抛出异常位置之后的代码将不会执行,但是处理完异常后续的代码能正常运行。
try中可能会抛出多哥不同的异常,必须用catch来一一捕获。
还有一些注意事项:
如果抛出的异常类型与这些catch不匹配,则异常不会被成功捕获,也就不会被处理,会继续抛出,最后由JVM来检测并中断程序。
如果多个异常的处理方式相同,则可以这样(中间加上 | ):
如果异常具有父子类关系,则子类异常必须在父类异常前面,否则报错
可以通过一个父类(如RuntimeException)来捕获所有运行时异常类,但是不推荐。
finally关键字
格式:try{}catch(){}finally{}
一般跟在try—catch后面,用于做一些清扫资源,资源回收的工作。当在try里面若是执行完代码就直接return来返回的话,try-catch-finally后的代码根本就不会执行,如在try里面执行输入流操作:
我们可以看到,finally之后的代码不会被执行,输入流没有被回收。但是finally中的代码无论如何都会被执行,我们可以把回收输入流的方法放入finally中来执行该操作。
异常处理流程
谁调用谁来处理,若是没人处理则交给JVM来处理,程序会终止.
总结:
程序先执行try中代码
try中代码如果出现异常,看看是否与catch捕获类型匹配
要是匹配,执行catch内代码
要是不匹配,会将异常传递给上层调用者
无论匹不匹配,finally都会被执行到
上层调用者如果不匹配会一直传递给上上层,直到main方法也没有处理,则会给JVM进行处理,程序回异常终止
自定义异常(实现登录操作)
先来看异常的内部是如何实现的:
可以看到,一路调用父类来执行抛出异常的操作,而形参为String类(填写错误信息)
我们可以模仿使用继承来选择异常为运行时异常还是编译时异常,然后内部调用super,传入一个形参,则如下实现:
//登录
public class Login {
private String name = "lux";
private String password = "123789";
public String getName() {
return name;
}
public String getPassword() {
return password;
}
}
//用户名异常
public class NameException extends Exception{
public NameException(String name){
super(name);
}
}
//密码异常
public class PasswordException extends Exception{
public PasswordException(String Password){
super(Password);
}
}
public class Test {
//自定义异常实现登录
public void Loginfo(String name,String Password)
throws NameException,PasswordException{
Login lo = new Login();
//抛出异常错误
if(!lo.getName().equals(name)){
throw new NameException("用户名错误!");
}
if(!lo.getPassword().equals(Password)){
throw new PasswordException("用户密码错误!");
}
System.out.println("登录成功!");
}
public static void main(String[] args) {
Test test = new Test();
Scanner can = new Scanner(System.in);
System.out.println("请输入用户名:");
String name = can.nextLine();
System.out.println("请输入密码:");
String Password = can.nextLine();
//处理异常
try{
test.Loginfo(name,Password);
}
catch (NameException e){
e.printStackTrace();
}
catch (PasswordException e){
e.printStackTrace();
}
}
}