1. 可以灵活的处理异常,如果当前方法有能力处理异常,就捕获并处理它,否则只需抛出异常,由方法调用者来处理它。
a) 事实上,异常还有一个非常有用的作用,可以用它来做流程控制。
2.
在Java编程语言中,用try和catch语句来处理异常。格式如下:<v:shapetype id="_x0000_t75" coordsize="21600,21600" o:spt="75" o:preferrelative="t" path="m@4@5l@4@11@9@11@9@5xe" filled="f" stroked="f"> </v:shapetype>
<v:shapetype coordsize="21600,21600" o:spt="75" o:preferrelative="t" path="m@4@5l@4@11@9@11@9@5xe" filled="f" stroked="f"><v:stroke joinstyle="miter"></v:stroke><v:formulas><v:f eqn="if lineDrawn pixelLineWidth 0"></v:f><v:f eqn="sum @0 1 0"></v:f><v:f eqn="sum 0 0 @1"></v:f><v:f eqn="prod @2 1 2"></v:f><v:f eqn="prod @3 21600 pixelWidth"></v:f><v:f eqn="prod @3 21600 pixelHeight"></v:f><v:f eqn="sum @0 0 1"></v:f><v:f eqn="prod @6 1 2"></v:f><v:f eqn="prod @7 21600 pixelWidth"></v:f><v:f eqn="sum @8 21600 0"></v:f><v:f eqn="prod @7 21600 pixelHeight"></v:f><v:f eqn="sum @10 21600 0"></v:f></v:formulas><v:path o:extrusionok="f" gradientshapeok="t" o:connecttype="rect"></v:path><o:lock v:ext="edit" aspectratio="t"></o:lock></v:shapetype>
try {
// code that might throw a particular exception
} catch (SpecialException e) {
// code to execute if a SpecialException is thrown
} catch (Exception e) {
//code to execute if a general Exception exception is thrown
}
---------------------------------------------------------------------------------------------------------------
关键字throws 指出方法有可能抛出的异常,如果方法有可能抛出多个异常,可以在throws后添加多个异常,声明抛出多个异常
例如:methodName throws Exception1,Exception2,Exception3
Throwable是所有异常类的父类,继承自Object类。Throwable又分为两种(Error,Exception,均继承自Throwable);
Error :用来表示编译时和系统错误
Exception : 可以抛出的基本类型
注意:
<1>声明异常的关键字是:throws; 抛出异常的关键字是: throw
<2>一个方法只能抛出在方法声明中声明的异常以及异常Error,RuntimeException和它们的子类。例如;如果没有在方法声明中声明IOException异常,那么在这个方法体中就不能抛出它。但是,即使方法没有声明RuntimeException或它的子类,方法也总能抛出它们。此外,java强迫程序员处理异常。如果一个方法声明了Error和RuntimeException之外的异常,则必须在调用它的地方用try语句中进行捕获和处理,以避免程序突然中止。
<3>如果try块中的某条语句抛出了一个异常,那么java就会略过其余语句,开始为该异常搜索异常处理器。如果异常的类型与某个catch子句所列的异常匹配,就会执行该catch语句子句中的代码,如果异常类型与任何一个catch子句中的异常都不匹配,那么就会跳过try块中的其它语句,执行finally子句,并退出这个方法,将异常传递给调用该方法的方法,继续重复寻找事件处理器的过程。如果在方法调用链中始终没有找到异常处理器,程序就会中止,并在控制台上打印出错误信息。
<4>如果在图形程序中出现了Exception子类的一个异常,java在控制台上打印错误,但程序回到处理用户界面的循环继续运行,忽略该异常。
<5>如果一个catch子句捕获了一个父类的异常,它就能捕获那个父类所有子类的异常对象。
<6>catch子句中指定异常的顺序非常重要。如果在父类的异常对象前没有指定这个异常对象,就会导致编译错误。
<7>通常情况下,异常处理需要更多的时间和资源。如果可能的话应该用判断语句测试简单的异常。而用异常去处理那些if语句不能解决的问题。
3.finally语句定义一个总是被执行的代码块,而不管有没有出现异常
-----------------------------
public void work() {
try{
开门
工作8个小时 //可能会抛出DiseaseException异常
}catch(DiseaseException e){
去医院看病;
}finally{
关门
}
}
finally语句不被执行的唯一情况是程序先执行了终止程序的System.exit()方法
注意:即使在函数中使用return()语句也不能禁止执行return()语句块
public static void main(String args[]){
try{
System.out.println("Begin");
return(); //在跳出本函数之前,仍然先执行finally语句块
System.exit(0);
}finally{
System.out.println("Finally");
}
System.out.println("End");
}
4.
异常处理流程
try{
code1; //可能抛出各种异常
}catch(SQLException e){
System.out.println("SQLException");
}catch(IOException e){
System.out.println("IOException");
}catch(Exception e){ //通常将异常继承关系中顶层异常放在最后
System.out.println("Exception");
}
5.
运行时异常 (不受检查异常)
java并未要求在方法中显示的声明运行时异常,这些异常异常会自动被JVM抛出
RuntimeException类及其子类都称为运行时异常,这种异常的特点是Java编译器不会检查它,也就是说,当程序中可能出现这类异常,即使没有用try-catch语句捕获它,也没有用throws子句声明抛出它,也会编译通过,只会在运行时才报错。例如当以下divide()方法的参数b为0,执行“a/b”操作时会出现ArrithmeticException异常,它属于运行时异常,Java编译器不会检查它:
原因 :RuntimeException代表的是编程异常,这些错误是无法预料。所以不可能交给编译器在编译时做检查
public int divide(int a,int b){
return a/b; //当参数b为0,抛出ArrithmeticException
}
区分运行时异常和受检查异常
运行时异常表示无法让程序恢复运行的异常,导致这种异常的原因通常是由于执行了错误操作。一旦出现了错误操作,建议终止程序(会抛出异常并终止程序),因此Java编译器不检查这种异常。
public void method(int[] array){
for(int i=0;i<=array.length;i++)
array[i]=1; //当i的取值为array.length时,将抛出ArrayIndexOutOfBoundsException
}
-------
修改为
public void method(int[] array){
for(int i=0;i array[i]=1; //不会抛出ArrayIndexOutOfBoundsException
}
-------------
受检查异常
表示程序可以处理的异常,如果抛出异常的方法本身不能处理它,那么方法调用者应该去处理它,从而使程序恢复运行,不至于终止程序。
如果一个方法可能出现受检查异常,要么用try-catch语句捕获,要么用throws子句声明将它抛出(当然也可以声明抛出它的父类异常),那么就需要在使用该方法的地方捕获异常或再一次将他抛出,否则在编译时就会导致编译错误。
void method1() throws IOException{} //合法
//编译错误,必须捕获或声明抛出IOException
void method2(){
method1();
}
//合法,声明抛出IOException
void method3()throws IOException {
method1();
}
------------------
//合法,声明抛出Exception
void method4() throws Exception {
method1();
}
//合法,捕获IOException
void method5(){
try{
method1();
}catch(IOException e){…}
}
------------------------
用户定义异常
用户定义异常是通过扩展Exception类或RuntimeException来创建的
class AnswerWrongException extends Exception {
private int result;
public AnswerWrongException (int result){
this.result=result;
}
public int getResult() {
return result;
}
}
----------------
public class ExceptionTester{
public static void test(int x,int y,int z)throws AnswerWrongException{
if(x+y!=z) throw new AnswerWrongException(z);
System.out.println(x+"+"+y+"="+z);
}
public static void main(String args[]) {
try{
test(1,2,5);
System.out.println("end");
}catch( AnswerWrongException e){
System.out.println("result is wrong:"+e.getResult());
e.printStackTrace();
}
}
}
------------------
案例分析:
public class Compute {
/**
* 方法本身处理异常,调用者就不能再处理
*/
public int work(int a,int b){
int result = 0;
try{
result = a/b;
}catch(Exception e){
e.printStackTrace();
}
return result;
}
/**
* 方法本身不做统一的异常处理
* 由调用者自己进行处理,能满足
* 调用者想进行不同处理的情况
*/
public int work1(int a,int b) throws Exception{
int result = 0;
result = a/b;
return result;
}
/**
* 方法本身进行异常的处理
* 同时调用者也进行各自的处理
* 需要在方法的catch里处理完后,再
* throw该异常对象
*/
public int work2(int a,int b) throws Exception{
int result = 0;
try{
result = a/b;
}catch(Exception e){
e.printStackTrace();
System.out.println("in work2");
throw e; //将这个异常抛给方法的调用者再进行处理
}
return result;
}
/**
* 使用返回值让调用者判断区分处理
*/
public int work3(){
///
//
int a = 12;
if(a==12){
return 1;
}
System.out.println("in work3");
return 2;
}
/**
* 使用抛出异常对象来达到让调用者区分
* 处理的目的
*/
public void work4() throws Exception{
int a = 12;
if(a==12){
throw new Exception(); //
}
System.out.println("in work4");
}
public void work5() throws RuntimeException{
int b = 12;
if(b==12){
throw new RuntimeException(); //可以起到流程控制的作用
}
System.out.println("in work5");
}
}
/**
* throws throw
* 1:使用的位置 throws 放在方法参数的后边
* throw 放在方法里面
* 2:从后面跟的内容 throws 异常的类名
* throw 异常类的对象
* 3:从功能 throws 表示该方法不处理异常,方法
* 产生的异常一定由调用者处理
* throw 主动抛出一个异常类的对象
*/