异常

什么是异常:
程序运行过程中所发生的不正常事件,他会中断程序运行。
常见的异常类型:
异常层次结构父类 Execption
算数异常类:ArithmeticExecption
数组下标越界异常:ArrayIndexOutOfBoundsException
空指针异常类型:NullPointerException
不能加载所需类:ClassNotFoundException
方法接收到非法参数:IllegalArgumentException
类型强制转换类型:ClassCastException
字符串转换为数字异常:NumberFormatException(如把abc转换为数字)

Java 对象转换 JAVA对象转换异常是什么_java


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 中你可以自定义异常。编写自己的异常类时需要记住下面的几点。

  1. 所有异常都必须是 Throwable 的子类。
  2. 如果希望写一个检查性异常类,则需要继承 Exception 类。
  3. 如果你想写一个运行时异常类,那么需要继承 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