日期:2014-05-20 浏览次数:21042 次
在前面三节的学习中,对于面向对象的编程思想已告一段落了;
从前面的学习我们都知道,Java具有安全,可靠两个优点,一部分原因是因为
Java摒弃了指针这个概念,还有垃圾回收机制;还有一个原因是因为Java提供了异常处理机制
在这一节中,我们将会对异常与断言这两个关键词进行解析!
学习路线解析:
①了解异常是什么东东,熟悉几个常见的异常,学会使用try-catch,finally,throws和throw对异常进行处理;学会自定义异常
②了解断言的好处,以及断言的启动,关闭
程序运行过程中出现的不正常现象!例如:除法运算时,除以0,这个就是算术异常
记住:异常时运行时的程序出错,编译时检查的仅仅是语法错误!不运行而来的异常?
程序运行过程中由于各种因素导致程序运行发生错误,比如用户的错误操作,代码本身错误,系统环境因素等;
在处理异常时需要对异常进行判断,针对不同的异常类型采取不同的处理措施!
ArithmeticException | 算术异常 |
ArrayIndexOutOfBoundsException | 数组下标越界异常 |
ArrayStoreException | 数组元素类型不兼容eg:为整型数组赋浮点型的数 |
ClassCastException | 类型强制转换异常(精度丢失) |
ClassNotFoundException | 找不到对应类异常 |
CloneNotSupportedException | 调用clone()方法,但没有实现Cloneable接口(ps:数组默认实现该接口) |
EOFException | 文件已结束异常 |
FileNotFoundException | 找不到对应文件异常 |
IllegalAccessException | 否问某个类被拒绝时的异常(eg:在别的类中访问private修饰的类) |
IndexOutOfBoundsException | 下标索引越界异常(eg:数组int a[5],访问a[5]);就会触发该异常,因为下标从0开始 |
InstantiationException | 使用newInstance()方法创建抽象类或借口实例抛出的异常 |
IOException | 输入输出异常 |
NullPointerException | 空指针异常,这个是比较常见的,eg:对象没有实例化直接调用属性或者方法 |
NumberFormatException | 数字格式转换异常,eg:"1+2"这个是字符串,转化为数字就报错了 |
NoSuchFieldException | 字段未找到异常 |
NoSuchMethodException | 方法为找到异常 |
NoSuchElementException | 元素未找到异常(eg:调用StringTokenizer的nextToken()方法可以出现) |
SecurityException | 安全异常问题,可能需要修改权限 |
SQLException | 数据库操作异常 |
StringIndexOutOfBoundsException | 字符串索引越界异常 |
MalformedURLException | URL配置异常(可能是URL协议,格式,或者路径错误;jar包问题,去掉gnujaxp.jar包引用即可) |
UnknowHostException | 域名解析出错异常 |
IllegArgumentException | 向方法传递了一个不合法或者不合理的参数 |
IllegalStateException | 违法的状态异常,调用了某个不处于合法调用状态的方法(eg:调用已经销毁的方法) |
Error类:表示一个程序错误,指的是底层的,低级的,不可以恢复的严重错误;此时的程序一定会退出,因为已经失去了
程序运行所需的物理环境;我们无法进行处理
Exception类:分为检验异常和非检验异常
RuntimeException及其子类都是非检验异常,其他的异常均为检验异常,需要进行捕获
检验异常:程序代码中需要进行捕获的异常,(try-catch或者throws + try - catch)
非检验异常:因为没有进行必要的检查,由于疏忽或错误引起的异常,一定属于虚拟机内部异常(eg:空指针异常)
catch块必须和try块一起使用,不能单独使用
代码示例:数组越界异常
package com.jay.example; /* * 该代码演示的使用try-catch来捕获数组越界异常 * 如果没加try和catch,那么后面的HeHe是不会打印的,因为 * 因为数组越界程序会直接终止,加了try-catch,如果发生了异常 * 那么就会执行catch里面的方法; * 如果把a[5]改成a[4]木有异常,那么catch块就不会执行了 * */ public class ExceptionTest1 { public static void main(String[] args) { int a[] = {1,2,3,4,5}; try { System.out.println(a[5]); } catch(ArrayIndexOutOfBoundsException e) { System.out.println("数组越界啦!!!!"); } System.out.println("HeHe"); } }
不能单独使用,需要与try搭配,无论什么情况,finally块中的内容一定会执行,通常在finally块中执行一些系统资源清理和释放的工作
如:文件关闭,数据库关闭等
注意:有特殊!如果在catch块中调用了System.exit(0);方法,那么finally部分的代码不会被执行,因为程序已经终止了
代码示例:算术异常
package com.jay.example; /* * 该代码演示的是finally块的使用 * 需要跟这一个try,无论异常是否发生 * 都会执行,只有在catch块中调用了System.exit(0); * 方法才能阻止finally执行; * 通常是在该方法中完成系统资源的清理释放 * */ public class ExceptionTest2 { public static void main(String[] args) { int x = 10; int y = 0; try { System.out.println(x/y); } catch(ArithmeticException e) { System.out.println("除数不能为0,算术异常!"); } //可自己删掉try中的语句,或者在前面的catch中添加System.exit(0)来测试 //finally什么时候执行! finally { System.out.println("finally无论是否异常都执行!"); } } }
就是使用多个catch块,依次捕获不同的异常;
其实只有一个catch块被执行,要把子类异常的catch需放在父类异常的catch前面哦!
package com.jay.example; /* * 该代码演示的是多重catch块的捕获 * 代码中故意犯了除0,数组下表越界,数字格式三个错误 * 当程序发生错误了,依次寻找第一个匹配的异常 * 子类的catch块要放在父类的catch块前面哦! * */ public class ExceptionTest3 { public static void main(String[] args) { try { //现在报算数异常;如果把这部分注释掉就会报数组越界异常 int a = 1; int b = 0; System.out.println(a/b); //如果把这部分注释掉,那么会报数字格式异常 int c[] = {1,2,3}; System.out.println(c[3]); //如果把这部分注释掉,就正常输出了 int d = Integer.parseInt("a"); int e = Integer.parseInt("2"); System.out.println(d + e); System.out.println("程序木有错误!"); } catch(NumberFormatException ex){System.out.println("数字格式异常!");} catch(ArithmeticException ex){System.out.println("算数异常,不能除以0!");} catch(ArrayIndexOutOfBoundsException ex){System.out.println("数组下标越界异常!");} catch(Exception ex){System.out.println("其他异常");} } }
运行截图:
就是try-catch里面又有try-catch,这个和if-else的嵌套差不多,
效果和前面的多重catch块差不多,比较简单,这里就不讲了
try { try { }catch(Exception e){} }catch(Exception e){}
当一个方法可能会引发某种异常时,但是我们又不想在该方法中对该异常进行处理;
可以用throws将异常抛出,当我们调用该异常时再对异常进行捕获
代码示例:
package com.jay.example; /* * 带代码演示的是使用throws回避方法中可能会出现的异常 * 等调用方法时再对异常进行捕获处理 * */ public class ExceptionTest4 { //再方法这里使用throws回避异常,就是说不在这里对异常进行捕获处理 //还有这里用static修饰是因为main()方法是静态方法,只能调用类中的静态成员 public static void show()throws ArrayIndexOutOfBoundsException { int a[] = {1,2,3}; System.out.println(a[3]); } public static void main(String[] args) { //对方法中的异常进行捕获! try{ show(); }catch(ArrayIndexOutOfBoundsException ex){System.out.println("数组越界异常!");} } }
部分读者可能有个问题:程序没异常不好么?吃饱饭没事做啊,为什么要自己去引发异常?
其实显式抛出异常通常用于程序的调试或者抛出用户自定义异常
自定义异常时用的比较多!
系统提供的异常类不一定能捕获所有的错误异常,
在这种情况下,用户可以根据自己的需要,自定义异常类型
自定义异常注意以下三点:
①自定义异常时,需要继承Exception类
②由于是自定义异常,所以需要使用throw手动抛出自定义异常
③同事需要使用try-catch对异常进行捕获
代码示例:
package com.jay.example; //继承Exception父类,构造方法中super()里面的 //参数,可以通过MyException对异常进行捕获 class MyException extends Exception { public MyException() { super("自定义异常:除数不合规定"); } } public class ExceptionTest5 { public static void main(String[] args) { int a = 2; int b = 1; //如果满足一下情况就throw抛出异常,同时要用try-catch进行捕获 if(b == 0 || b == 1) { try { throw new MyException(); } catch (MyException e) { System.out.println(e.getMessage()); } } } }
jdk 1.4后,引入的Assert(断言)的概念;允许在代码中添加一些合法的语句
以用于调试程序;在assert指定的布尔表达式条件不成立时会会抛出
一个AssertionError对象,直接终止程序的运行!
一种错误处理机制,在程序开发与测试阶段使用;
可以理解为代替,if..else或者try-catch,因为这些东东对程序的性能有一定影响
完成调试后还要将他们删除,如果用断言,则是最低代价
assert 条件
assert 条件:错误信息
第二种方式,如果前面的条件不成立的话,那么后面的字符串作为AssertionError错误输出信息
默认情况下断言是关闭的,要通过 enableassertions或-ea来启用断言功能
使用disableassertions或-da来关闭断言功能
代码示例
public class AssertDemo { static void test(int num) { //如果num <= 0的话,抛出AssertError,显示错误信息 assert(num >=0):"传入参数需要大于0"; System.out.println("参数为正数!"); } public static void main(String[] args) { test(-7); } }
代码解析:
判断某个参数是否为正数,通过添加assert对参数进行判断,表达式不成立的话输出后面的错误信息
然后在cmd下调用断言,-ea启动断言,-da关闭断言
在这一节中,我们对Java中的异常处理机制进行了解析,对异常处理模型和常见异常进行了了解
学会了使用try,catch,finally,throws,throw等关键字完成异常捕获,处理,抛出,回避等;
学习了自定义异常的使用;
最后还学习了一下断言的基本用法;使用断言时还有注意一下两点:
①断言失败是致命,不可恢复的
②断言检查仅仅用于程序开发测试阶段
建议还是少用!
好了,这一节就到这里,如有纰漏,错误,好的建议;
请读者指出,不胜感激!O(∩_∩)O谢谢!