异常
什么是异常:
程序运行过程中所发生的不正常事件,他会中断程序运行。
常见的异常类型:
异常层次结构父类 Execption
算数异常类:ArithmeticExecption
数组下标越界异常:ArrayIndexOutOfBoundsException
空指针异常类型:NullPointerException
不能加载所需类:ClassNotFoundException
方法接收到非法参数:IllegalArgumentException
类型强制转换类型:ClassCastException
字符串转换为数字异常:NumberFormatException(如把abc转换为数字)
Throwable又派生出Error类和Exception类:
错误:Error类以及他的子类的实例,代表了JVM本身的错误。错误不能被程序员通过代码处理,Error很少出现。因此,程序员应该关注Exception为父类的分支下的各种异常类。
异常:Exception以及他的子类,代表程序运行时发送的各种不期望发生的事件。可以被Java异常处理机制使用,是异常处理的核心。
异常处理的基本语法
在编写代码处理异常时,对于检查异常,有2种不同的处理方式:使用try…catch…finally语句块处理它。或者,在函数签名中使用throws 声明交给函数调用者caller去解决。
try…catch…finally语句块
try{
//try块中放可能发生异常的代码。
//如果执行完try且不发生异常,则接着去执行finally块和finally后面的代码(如果有的话)。
//如果发生异常,则尝试去匹配catch块。
}catch(Exception e){
//在程序发生异常的情况下执行的代码
//每一个catch块用于捕获并处理一个特定的异常,或者这异常类型的子类。Java7中可以将多个异常声明在一个catch中。
//catch后面的括号定义了异常类型和异常参数。如果异常与之匹配且是最先匹配到的,则虚拟机将使用这个catch块来处理异常。
//在catch块中可以使用这个块的异常参数来获取异常的相关信息。异常参数是这个catch块中的局部变量,其它块不能访问。
//如果当前try块中发生的异常在后续的所有catch中都没捕获到,则先去执行finally,然后到这个函数的外部caller中去匹配异常处理器。
//如果try中没有发生异常,则所有的catch块将被忽略。
//e.printStackTrace();//打印跟踪异常的堆栈信息
//System.exit(1);参数类型为int 如果为1 退出Java虚拟机
}finally{
//finally块通常是可选的。
//无论异常是否发生,异常是否匹配被处理,finally都会执行。(前面存在 System.exit(1)的时候例外)
//一个try至少要有一个catch块,否则, 至少要有1个finally块。但是finally不是用来处理异常的,finally不会捕获异常。
//finally主要做一些清理工作,如流的关闭,数据库连接的关闭等。
}
try-catch,try-finally 不能省略try块,且不能单独存在
catch块中异常的类型:多个
多重catch块:程序中异常的类型多种多样,仅仅只凭一个catch块不能满足我们的需求
约束条件: 越具体的子异常类卸载catch首位,越抽象的父异常类越往后写
try块中的代码一旦出现异常,程序的执行逻辑就会向catch块转移(在try块中异常引发的代码后的其他内容都不执行)
throws:声明异常,通知调用方。方法内部可能会存在异常。请调用方处理 方法名末尾(在该方法中根本没有对该类异常的捕获)
throw:抛出的是具体的某个异常对象
public void cal(Num num) throws ArithmeticExecption
{
int num1=2;
int num2=0
int num3=num1/num2;
if(num2 == 0)
throw new ArithmeticExecption("算术异常");
}
---------------------
声明自定义异常:
在 Java 中你可以自定义异常。编写自己的异常类时需要记住下面的几点。
- 所有异常都必须是 Throwable 的子类。
- 如果希望写一个检查性异常类,则需要继承 Exception 类。
- 如果你想写一个运行时异常类,那么需要继承 RuntimeException 类。
异常的链化—异常链:
**异常链化 **
以一个异常对象为参数构造新的异常对象。新的异对象将包含先前异常的信息。这项技术主要是异常类的一个带Throwable参数的函数来实现的。这个当做参数的异常,我们叫他根源异常(cause)。
//创建注册失败类
public class RegisterFaildException extends Exception{
public RegisterFaildException() {
super();
// TODO Auto-generated constructor stub
}
public RegisterFaildException(String message, Throwable cause) {
super(message, cause);
// TODO Auto-generated constructor stub
}
public RegisterFaildException(String message) {
super(message);
// TODO Auto-generated constructor stub
}
public RegisterFaildException(Throwable cause) {
super(cause);
// TODO Auto-generated constructor stub
}
}
//创建登录失败类
public class LoginFaildException extends Exception{
public LoginFaildException() {
super();
// TODO Auto-generated constructor stub
}
public LoginFaildException(String message, Throwable cause) {
super(message, cause);
// TODO Auto-generated constructor stub
}
public LoginFaildException(String message) {
super(message);
// TODO Auto-generated constructor stub
}
public LoginFaildException(Throwable cause) {
super(cause);
// TODO Auto-generated constructor stub
}
}
//User类
package entity;
public class User {
private String username;
private String password;
private int age;
private String birthday;
private String cardId;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getBirthday() {
return birthday;
}
public void setBirthday(String birthday) {
this.birthday = birthday;
}
public String getCardId() {
return cardId;
}
public void setCardId(String cardId) {
this.cardId = cardId;
}
}
public class Test {
public static void main(String[] args){
User user=new User();
try {
login(user);
} catch (LoginFaildException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static boolean resgiter(User user) throws RegisterFaildException{
boolean flag=false;
if(user.getUsername()==null){
if(!flag){
throw new RegisterFaildException("身份信息有误");
}else{
return true;
}
}else if(user.getPassword()==null){
return false;
}
return true;
}
public static void login(User user) throws LoginFaildException{
try {
boolean resgiter = resgiter(user);
} catch (RegisterFaildException e) {
e.printStackTrace();
throw new LoginFaildException("登录失败", e); //核心的代码
}
}
}
输出结果
exception.RegisterFaildException: 身份信息有误
at demo.Test.resgiter(Test.java:81)
at demo.Test.login(Test.java:94)
at demo.Test.main(Test.java:58)
exception.LoginFaildException: 登录失败
at demo.Test.login(Test.java:97)
at demo.Test.main(Test.java:58)
Caused by: exception.RegisterFaildException: 身份信息有误
at demo.Test.resgiter(Test.java:81)
at demo.Test.login(Test.java:94)
... 1 more