(1)什么是异常
异常机制实际上是Java中的一种消息机制,消息的传递:由下往上依次传递
(2)异常体系
错误:程序不可逆转的情况我们称为错误
如:JVM崩溃
异常:特殊情况,可以被程序进行修复处理
整个体系如下:
Throwable
|- Error(错误)
|- Exception(异常:特殊情况)
|- NoSuchMethodException
|- SAXException
|-.......
|- RunTimeException
|- NullPointerException
|-IndexOutOfBoundsException
|-......
(3)异常处理
1、声明抛出(消极处理):
只要在这个方法的范围内出现声明的异常,JVM自动向上抛出
语法:(下例说明可以抛出多个类型的异常)
public void method()throws NoSuchMethodException,IOException{
//可能出现异常的代码
}
2、捕获处理(积极处理):
(1)try-catch
try{
//可能发生异常的代码区域
}catch( 异常类型 e ){
//异常处理代码
}
注意:
1.catch块可以有多个
2.上层catch的范围不能比下层的catch的范围大
(2)try-catch-finally
1、finally一般会释放GC无法回收的资源
try{
//可能发生异常的代码区域
}catch( 异常类型 e ){
//异常处理代码
}finally{
//释放资源
}
2、finally无论如何都会被执行
如下:返回值是2
public int get(){
try{
return 1;
}finally{
return 2;
}
}
(3)举例:信息的反馈,由上层捕获,可以根据不同的情况,做出不同的处理
package exceptions; import java.io.IOException; public class C { /** * 在cc方法中设置一个异常,并让其向上抛出,不做处理 */ public void cc()throws IOException{ System.out.println( "C开始执行cc" ); throw new IOException( "cc方法出现io异常" ); } }
package exceptions; public class B { /** * bb方法中调用cc方法,会收到cc中向上抛出的异常,bb方法中也不做处理,只向上抛 */ public void bb()throws Exception{ C c = new C(); c.cc(); } }
package exceptions; public class A { /** * 捕获来自bb方法中的异常,并进行处理,这里只是简单的打印一行文字表示处理该异常 */ public void aa(){ B b = new B(); try{ //异常捕获区 b.bb(); System.out.println( "===========" ); }catch( Exception e ){ e.printStackTrace();//打印异常对象e的堆栈跟踪信息 System.out.println( "A说:我收到一条信息:" + e.getMessage() );//获得异常对象中携带的信息 System.out.println( "开始处理这个异常" ); } } }
package exceptions; public class Run { public static void main(String[] args) { A a = new A(); a.aa(); } }
(4)自定义异常及其作用
1、手动产生一个异常
关键字:throw
throw new Exception();产生一个编译时异常
throw new RuntimeException();产生一个运行时异常
2、作用
下层通过异常的传递方式来告知上层自己出现了什么样的情况,请上层处理。而不是使用返回值来告知,因为返回值不能很好的表达清楚下层出现的各种特殊情况。
完成上述功能,需要通过自定义异常和try_catch来完成。
定义一个类去继承Exception或RuntimeException从而形成自定义的异常类
作用:
通过我们使用自定义的异常体系来表示程序中各种特殊情况;从而方便下层向上传递不同信息,而上层可以根据不同情况进行不同粒度的控制和处理;从而避免了使用返回值传递消息的局限。
3、举例
(1)printStackTrace
在控制台打印异常对象的堆栈跟踪信息
(2)getMessage
获取异常对象中携带的信息
(3)getCause
获取引发当前异常的原因异常——先找Caused by:xxx
举例:以登录为例,要抛出账号错误还是密码错误
package exceptions;
public class User {
public String username;
public String password;
public User() {
}
public User(String username, String password) {
this.username = username;
this.password = password;
}
}
package exceptions;
public class LoginFailedException extends Exception {
//自定义异常,有两个子类,账号不存在异常,密码错误异常
}
package exceptions;
public class PwdErrorException extends LoginFailedException {
}
package exceptions;
public class AcctCodeNotExistException extends LoginFailedException {
}
package exceptions;
import java.util.HashMap;
import java.util.Map;
public class LoginService {
/**
* 内置系统用户
*/
private Map<String, User> allUsers = new HashMap<String, User>();
public LoginService(){
//初始化几个用户
User user1 = new User("001", "111");
User user2 = new User("002", "222");
User user3 = new User("003", "333");
allUsers.put(user1.username, user1);
allUsers.put(user2.username, user2);
allUsers.put(user3.username, user3);
}
public User login( String username, String password ) throws AcctCodeNotExistException, PwdErrorException{
if( !allUsers.containsKey(username) ){//账号不存在 --> 登录失败
throw new AcctCodeNotExistException();
}
//账号存在, 判断密码
User rightUser = allUsers.get( username );
if( !rightUser.password.equals( password ) ){//密码错误 --> 登录失败
throw new PwdErrorException();
}
//登录成功
return rightUser;
}
}
package exceptions;
public class LoginController {
private LoginService service = new LoginService();
public void run(){
try {
User user1 = service.login("001", "222");//运作服务层
System.out.println( "登录成功" );
} catch (LoginFailedException e) {
System.out.println( "账号或密码错误, 登录失败" );
}
}
public static void main(String[] args) {
LoginController login = new LoginController();
login.run();
}
}