异常从名字上看就不正常,Java中为我们提供了异常类来供我们在编译时和运行时可能出现的异常现象进行处理.
Java中的异常类的根类是Throwable,它两个子类: Error 和Exciption两个, Error 指错误,一般是JVM产生的问题,不需要我们自己解决. Exciption就是我们所说的异常,一般分为两种: 一种是运行时异常(RuntimeExciption),另一种则是非运行时异常. 根据是否受检查可以分为受检查异常和不受检查异常.
运行时异常的使用:
* Java 中针对异常处理有两套机制:
* 1.try-catch-finally
* try :尝试 .可能会产生异常的代码需要尝试去运行
* catch:捕捉 .捕捉try中可能会产生的异常
* finally:最终执行.
* 无论try是否产生异常,还是catch是否捕捉到异常.finally都会被执行.
* 2.throw 和 throws
下面来看示例代码:
所要倒入的包: import java.util.InputMismatchException;
public class ExceptionDemo01 { public static void main(String [] args){ //-- 在做输入的时候会限制用户只输入数字,如果输入字符给与提示,输入错误 Scanner scan = new Scanner(System.in); System.out.println("请输入一个数字:"); int num = 0; A:for (;true;){ try{ num = scan.nextInt(); break; //-- e 代表所捕捉到的异常对象. 名字是可以随便写的.但一般习惯都用e }catch (InputMismatchException e){ System.out.println("输入有误,请重新输入"); //-- 把缓存区中保留的错误的值取出来的. scan.next(); // continue A; e.printStackTrace(); } } System.out.println("num:" + num); } }
再看另一个例子:
NumberFormatException * * 当应用程序试图将字符串转换成一种数值类型, * 但该字符串不能转换为适当格式时,抛出该异常。 * * 1.产生该异常的条件 : 把字符串转变成数值时可能会触发的 * 字符串中有非数字部分.或者直接就是空字符串. 把这样的 * 字符串转变成数值.会产生该异常. * * 2.如何在遇到时,代码不结束,可以继续运行,又看不到异常信息. * @author Administrator */ public class ExceptionDemo02 { public static void main(String [] args){ String str = "a"; Scanner scan = new Scanner(System.in); System.out.println("Enter:"); str = scan.next(); //str = ""; int num = 0; for ( ; true ;){ try{ //-- 把数字变成字符串 //String.valueOf(); //-- 把字符串变成数字 num = Integer.parseInt(str); break; }catch (NumberFormatException e){ /** * 如果异常不产生Catch不会执行. */ System.out.println("转换失败,重新录入"); //-- 这里的next就是重新录入,不是清理. str = scan.next(); } } System.out.println(num); } }
例子:
public class ExceptionDemo03 { public static void main(String [] args){ /* 空指针异常:NullPointerException 是因为引用变量没有指向实际的对象(null除外).却通过引用变量 来操作对象的属性或者方法时,会产生空指针.空指针一旦产生一定是 点号前面为空. 引用变量.属性 引用变量.方法() X.Y.Z. 引用数据类型默认值就是null */ String str = ""; try { System.out.println(1); //-- 下面产生了空指针,就直接进入catch中.输出语句2是不会被执行的. //-- try中在产生异常时,产生异常下面的代码是不会被执行的. System.out.println(str.length()); System.out.println(2); }catch (NullPointerException e){ System.out.println(3); }finally { //- 无论try中是否产生异常,无论catch是否捕捉到异常.finally一定会被执行. System.out.println(4); } } }
public class ExceptionDemo04 { public static void main(String [] args){ /* 空指针异常:NullPointerException 是因为引用变量没有指向实际的对象(null除外).却通过引用变量 来操作对象的属性或者方法时,会产生空指针.空指针一旦产生一定是 点号前面为空. 引用变量.属性 引用变量.方法() X.Y.Z. 引用数据类型默认值就是null */ String str = null; try { //-- 问题? try中是否可能会产生不一样的异常. System.out.println(1); //System.out.println(str.length()); //System.out.println(Integer.parseInt(str)); System.out.println(Integer.parseInt(str.length()+"")); System.out.println(2); }catch (NullPointerException e){ System.out.println(3); }catch (NumberFormatException e){ System.out.println(4); }catch (InputMismatchException e){
public class ExceptionDemo06 { public static void main(String [] args){ ExceptionDemo06 ed = new ExceptionDemo06(); System.out.println(ed.method(null)); } public int method(String str){ try{ System.out.println("A"); System.out.println(str.length()); return 1; }catch (NullPointerException e){ System.out.println("B"); return 2; }catch (Exception e){ System.out.println("C"); return 3; }finally { //-- catch中return执行了,但是方法没有结束.而是选择性的把return的结果保存 //-- 在临时的缓存中 System.out.println("D"); //-- 这个时候的return 把上面return的结果进行覆盖. return 4; } } }
public class ExceptionDemo07 { public static void main(String [] args){ ExceptionDemo07 ed = new ExceptionDemo07(); ed.method2(null); } public void method(String str) { try { System.out.println(str.length()); } catch (NullPointerException e) { System.out.println("参数为空"); } finally { //finally中的代码有可能也出产生异常 try{ System.out.println("从新获取"); str = null; }catch (Exception e) { }finally{//-- 这个finally可以选择不加 } } } /** * 当在finally中也需要些try-catch的时候改写成下面样式. * @param str */ public void method2(String str){ try{ System.out.println(1); try{ System.out.println(2); System.out.println(str.length()); System.out.println(3); }finally { System.out.println(4); } }catch (NullPointerException e){ System.out.println(5); } } }
接下来看throw 和throws:
* 受查和非受查,被编译器检查.
* 在编写代码期间能够被编译器检查出来的异常被叫做受查异常.
* 除了RuntimeException和其子类之外的所以异常都是受查的
*
* 非运行时异常 == 受查异常
* 运行时异常 == 非抽查异常
*
* throw和throws是消极的异常处理方式.
* throws 用于方法声明.表明该方法可能会产生某个或多个异常.且当前方法
* 不处理该异常,交个JVM处理.JVM强制交给调用人处理.
*
* throw 在当前位置定义一个异常对象.(有实际的异常产生)
下面来看示例代码:
public class ThrowDemo01 { public static void main(String [] args){ ThrowDemo01 td = new ThrowDemo01(); td.method(null); } /** * */ public boolean method(){ //throw + 异常对象 /* 在有返回值的方法中,希望当前方法结束,又不想给返回值 这种情况下就可以选择throw一个异常出来. */ throw new NullPointerException("密码不对"); //-- 当代码执行到上面一行时,该方法已经结束了,下面的语句是不会被执行的.所以 //-- 写了也没用. } /** * throw + catch组合式写法 * @param str */ public void method(String str){ try{ System.out.println(str.length()); }catch (NullPointerException e){ throw e; } } }
throws:
public class ThrowsDemo01 { public static void main(String [] args){ ThrowsDemo01 td = new ThrowsDemo01(); td.method(); } /** * throws 只能用于方法声明处. * @throws NullPointerException */ public void method() throws NullPointerException{ String str = null; /* 如果是运行时异常(非受查异常) 是把异常交给JVM来处理 如果是非运行时异常(受查异常) 调用该方法的地方必须要使用try-catch来对异常做处理. */ System.out.println(str.length()); } }
下面再来看一个实例: 自定义异常:
用户登录系统中,需要对登录的用户名和密码进行验证,下面来直接看代码:
先定义三个类来继承Exciption类:
自定义y异常:传入的参数异常. * 自定义异常流程: * 1.提供一个类继承已有异常类.(Exception或其它子类) * 2.提供有参,无参构造方法 * 有参的类型基本是String. * 3.重写getMessage方法. * * * 直接继承Exception就是抽查异常,非运行时异常. * @author Administrator */ public class ArgumentException extends Exception{ public ArgumentException(){ } public ArgumentException(String msg){ super(msg); } /** * 返回希望用户看到的内容. * @return */ @Override public String getMessage() { return "参数异常"; } }
密码异常类:
public class PwdErrorException extends Exception{ public PwdErrorException(){ } public PwdErrorException(String msg){ super(msg); } /** * 返回希望用户看到的内容. * @return */ @Override public String getMessage() { return "密码不正确"; } }
用户名异常类:
public class UnKnownNameException extends Exception{ public UnKnownNameException(){ } public UnKnownNameException(String msg){ super(msg); } /** * 返回希望用户看到的内容. * @return */ @Override public String getMessage() { return "用户名不存在"; } }
用户业务类:
public class UserBizImpl { public void userLogin(String name,String pwd) throws ArgumentException,UnKnownNameException,PwdErrorException{ if (name == null || pwd == null || name.length() == 0 || pwd.length() == 0){ //- 因为这里所throw的是非运行时.所以必须要配合写throws throw new ArgumentException(); } if ("admin".equalsIgnoreCase(name) && "123".equalsIgnoreCase(pwd)){ System.out.println("登录成功"); }else if(!"admin".equalsIgnoreCase(name) && "123".equalsIgnoreCase(pwd)){ throw new UnKnownNameException(); }else{ throw new PwdErrorException(); } } }
测试类:
public class Test { public static void main(String [] args){ UserBizImpl userBiz = new UserBizImpl(); try { userBiz.userLogin("admin","123"); } catch (ArgumentException e) { System.out.println(e.getMessage()); } catch (UnKnownNameException e) { System.out.println(e.getMessage()); //e.printStackTrace(); } catch (PwdErrorException e) { System.out.println(e.getMessage()); }catch (Exception e){ System.out.println("防止遗漏了异常!"); } } }