赞
踩
生活中我们在使用一些产品的时候,经常会碰到一些异常情况。例如,使用ATM机取钱的时,机器会突然出现故障导致无法完成正常的取钱业务,甚至吞卡;在乘坐地铁时,地铁出现异常无法按时启动和运行;使用手机时,手机突然自动关机,等等。这些产品的异常情况,有些是系统硬件的问题,但更多的情况是软件出现了问题。
使用Java开发软件时,无论程序员多么小心谨慎,产品反复测试,还是会出现程序错误的现象。所以,优秀的编程语言可以为程序员提供高效、可靠的错误处理机制,便于开发高质量的软件产品。
Java语言提供了一种面向对象异常处理机制来报告和处理错误,这种异常处理机制对异常的处理都封装在异常类中完成。程序在运行过程中,如果出现异常,则会抛出一个异常类对象。
与java异常处理的相关关键字包括try、catch、throw和finally等,异常的基本样式也使用这些关键字。
methodname(){ try{ ...... //可能产生异常的语句或方法程序块 } catch(ExceptionType1 e){ ...... //对异常类型ExceptionType1对象的处理 } catch(ExceptionType2 e){ ...... //对异常类型ExceptionType2对象的处理 throw(e) //再抛出这个异常 } finally { ......//无论是否抛出异常,都需要执行的代码块 } }
在方法内:
java异常类都是由Throwable类派生而来的。派生出的两个分支分别是Error类和Exception类。
异常类是一种特殊类,表示的是一种特殊的运行错误,用于处理异常。在Java程序设计中,异常对象都是从Throwable类派生的实例。
派生于Throwable类的常用异常
被终止异常(InterruptedException) | 某个线程处于长时间的等待、休眠或其他暂停状态,其他线程通过Thread类的interrupt()方法终止该线程时抛出的异常 |
方法不存在异常(NoSuchMethodException) | 访问某个类的不存在方法时抛出的异常 |
找不到类异常(ClassNotFoundException) | ClassNotFoundException 表示在尝试加载类时找不到该类。这可能发生在运行时,通常是由于类路径不正确或缺少相应的类文件 |
不支持克隆异常(CloneNotSupportedException) | 当没有实现Cloneable接口或者不支持克隆方法时调用其clone方法抛出该异常 |
派生于RuntimeException类的常用异常
算术运算异常(ArithmeticException) | 整数除0时抛出这个异常 |
类造型异常(ClassCstException) | |
数组越界异常(ArrayIndexOutofBoundsofException) | |
数组存储异常(ArrayStoreException) | |
访问空指针(NullPointException) |
由IOException类派生的异常
文件已结束异常(EOFException) | |
文件未找到异常(FileNotFoundException) |
【例】
企业针对产品的异常,会使用一些关键字进行描述和处理。如:产品平均无故障时间、产品故障率、召回等。java的异常处理是通过5个关键词来实现的。分别是try catch throw throws finally 。
其中,try用来存放可能发生一个或多个异常的Java语句,catch语句块用来捕获try语句块抛出的异常。finally语句块用来存放释放的资源和句柄等。
为了捕获异常,需要使用catch语句块来配合try语句块。
try语句块用来指定可能发生异常的程序块,配合使用的catch语句块用来处理try语句块抛出的异常。
try语句块内部如果出现异常,那么程序将跳过try语句块中出现的异常语句之后的其它代码,直接进入catch语句块内执行代码
【例】
try-catch 语句块可以嵌套使用。当try语句块遇到异常时,Java会检查与try异常程序块相配合的catch捕获处理中是否存在能处理该异常的catch语句块。如果存在,则该异常将被改catch语句块捕获并处理,否则,该异常将被上一级的try-catch语句块捕获。
【例】
package example; public class TrynestdealException { public static void main(String[] args) { tryCatch(); //调用静态try-catch函数 } //静态tryCatch()函数 static void tryCatch() { try { //外层try块 try { //内层try块 System.out.println("执行里层try块\n"); int inte = Integer.parseInt("pencil");//字符串转化为整数 System.out.println(inte);//输出整数 } catch(ArrayIndexOutOfBoundsException e) { //捕获异常 System.out.println("执行里层catch块\n"); System.out.println("捕获ArrayIndexOutOfBoundsException异常" + e.getMessage()); } catch(ArithmeticException e) { //捕获异常 ArithmeticException //捕获异常后输出异常信息 System.out.println("执行里层catch2块\n"); System.out.println("捕获ArithmeticException异常" + e.getMessage()); } } catch(ClassCastException ie) { //捕获异常ClassCastException System.out.println("捕获外层异常ClassCastException" + ie.getMessage()); } catch(NumberFormatException ie) { System.out.println("捕获外层异常NumberFormatException" + ie.getMessage()); } } }
有时候我们要去某地,有多条交通路线,其中有一条是必须走的,也就是通常所说的交通要道。在try-catch-finally结构中,finally语句块就是交通要道。
在try-catch语句块中定义了finally语句块。这时无论try-catch语句块是否抛出和捕获异常,程序都将执行finally语句块。
【例】
package example; public class ExceptionFinally { public static void main(String[] args) { int num[] = new int[5]; try { for(int i = 0;i<5;i++) { num[i]= i+1; for(int j = 0;i<=i;j++) { num[i]+= num[j]; } } for(int i = 0;i<6;i++) { System.out.println(num[i]); } }catch(Exception e){ e.printStackTrace(); }finally { System.out.println("finally块是必经之路"); } } }
在操作文件的时候,无论操作是否成功,必须要在程序运行后关闭文件。同样,如果将释放内存的工作放到finally语句块内,那么程序不会由于未释放资源而导致内存泄漏
finally语句块通常情况下总是会被执行,但在下面这几种情况下finally语句块不会被执行
异常捕获语句块都存在于产生异常的方法中,异常抛出可以将产生的异常抛给调用它的方法。
如果某方法的try语句块中抛出的异常没有与之匹配的catch块,或者catch语句块已经不活了异常但不想立即处理,就可以将异常抛给调用它的上一级方法。
使用throw语句时必须声明一个异常对象,这个对象时Throwable派生类的对象
ThrowableInstance一定是Throwable类或Throwable子类的一个对象。简单类型(int、char)以及非Throwable类(String或Object)不能用作异常
【例】
package example; public class UseThrowExample { static void demoproc(String v1) { try { if(v1 == null) { //抛出NullPointerException异常 throw new NullPointerException("Throw Example"); } }catch(NullPointerException e){ System.out.println("输入的参数为空"); throw e; } } public static void main(String[] args) { try { String string = null; demoproc(string); //调用方法 }catch(NullPointerException e) { System.out.println("异常情况为"+ e); } } }
如果一个方法可以导致一个异常但不处理它,那么他必须在方法声明时包含一个throws子句,以使方法的调用者库保护他们自己而不发生异常。
throws子句列举了一个方法可能引发的所有异常类型,一个方法引发的所有其他类型的异常必须在throws子句中生明。如果不这样做,会导致编译错误。
package example; import java.io.IOException; public class ThrowsUsingExample { public static void main(String[] args) { try { System.out.println("请输入字符"); String s = getInput(); System.out.println("输入字符为:"); System.out.println(s); }catch(IOException e) { System.out.println("产生异常"+e.getMessage()); } } private static String getInput() throws IOException{ char[] buffer = new char[10]; int count = 0; boolean flag = true; while(flag) { buffer[count] = (char)System.in.read(); if(buffer[count]=='\n') { flag = false; }else { count++; } if(count >=10) { IOException aException = new IOException("buffer is null"); throw aException; } } return new String(buffer); } }
我们在使用手机软件时,经常会遇到出现异常、卡顿或者异常退出的情况,这主要和开发软件异常处理或者手机内存不足等情况有关。程序抛出异常,一般分为以下三个步骤:
package example; import java.sql.SQLException; public class ExceptionThreestep { //可能会抛出异常的方法 public static void throwException() throws SQLException{ try { throw new SQLException("SQLException1"); }catch(SQLException e) { System.out.println("throwException:()抛出异常"+e.getMessage()); //捕获异常暂不处理,抛出异常 throw new SQLException("SQLException1");//抛出异常SQLException } } public static void main(String[] args) { try { throwException(); } catch(SQLException e) { System.out.println("main()捕获SQLException:"+e.getMessage()); } } }
除了Java中提供的一些异常类,还可以根据自己的需求定义异常类。
package example; class UserOwnException { //声明UserOwnException无参数构造方法 public UserOwnException() { } //声明UserOwnException带有String类型参数的构造方法 public UserOwnException(String smg) { super();//调用父类的构造方法 } } public class UsingUserException { public static void main(String[] args) { try { execute(); //调用execute()方法 }catch(UserOwnException e) { System.out.println(e.getMessage()); } } static void execute() throws UserOwnException{ try { throw new Exception();//抛出异常 } //捕获Exception类 catch(Exception e) { //捕获后,直接抛出用户自定义异常类 throw new UserOwnException("自定义异常抛出"+e.getMessage()); } } }
创建自己的异常类,可以方便的处理和捕获某些运行时的异常,并重新抛出一个新的异常提供给它的调用者捕获。
运行时异常属于未检查异常,如果在方法的throws子句中声明了此异常,那么方法的调用者就可以不处理此异常。
package example; class MyArithException extends Exception{ MyArithException(){ } MyArithException(String msg){ super(msg); //调用父类的构造方法 } } public class CatchRunException { public static void main(String[] args) { try { executeRuntime(); //调用executeRuntime()方法 }catch(MyArithException e){ System.out.println("捕获运行时异常"+e.getMessage()); } } static void executeRuntime() throws MyArithException{ try { int i = 1/0; //抛出运行时异常 ArithmeticException } catch(ArithmeticException e) { //捕获异常ArithmeticException /* * 在这里捕获运行时异常ArithmeticException 不处理, * 而是抛出一个新的MyArithException 异常 * 因为运行时异常不在方法声明的throws子句中声明 * * */ throw new MyArithException(e.getMessage()); } } }
【拓展要点:ClassCastException异常】
当程序运行时,有时需要对不同的类型进行类型转换。在进行类型转换的过程中,当java虚拟机发现这两个类型不兼容而无法完成转换时,就会出现ClassCastException异常
【拓展要点:ClassNotFoundException异常】
当应用试图根据字符串形式的类名构造类,而在遍历CLASSPATH之后做不到对应名称的.class文件时,将抛出ClassNotFoundException异常。
异常是一种强大的调试手段,是因为回答了以下三个问题:
三个原则可以帮助我们在调试过程中最大限度的使用好异常:
-具体明确 - 提早抛出 -延迟捕获
(1)throw表示语句抛出一个异常。
一般用于程序出现某种逻辑时,程序员主动抛出某种特定类型的异常。
(2)throws是方法可能抛出异常的声明(在声明方法时,表示该方法可能要抛出异常)
当某个方法可能会抛出某种异常时,用throws声明可能抛出的异常,然后交给上层调用它的方法程序处理。
throw与throws关键字的比较
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。