违例差错控制

来源:互联网 发布:深圳龙岗大运软件小镇 编辑:程序博客网 时间:2024/04/30 01:32

说明:捕获错误最理想情况下是在编译期间捕获,但是并不是所有的错误都能够在编译期间捕获,有些错误必须等到运行期间才能发现,检测到运行期间发生的错误后该如何通知及处理?如果每次调用一个方法时都要细致地检查错误,代码可读性大大降低。

违例:一种例外情况,在问题发生的时候,我们可能不知道该如何解决,但一定知道的是程序不能就这样一直执行下去,需要将错误报告出去,并采取一定的措施。本地可能没有足够多的信息,需要将其抛出交给上一级处理。

好处:我们在一个地方处理问题,不用因为检查一个特定的错误,在多个地方进行控制。

下面介绍:正确控制违例以及如何生成自己的违例

1.基本违例:
1.1违例条件:出现什么问题时应该中止方法或作用域的继续
1.2违例过程:违例发生时,在内存堆里使用new创建了一个违例对象,停止当前执行路径,从当前环境中释放出违例对象句柄,违例控制机制接管一切,使我们从错误产生地方迁移到其他地方解决。

2.违例捕获:
若某个方法产生违例,必须保证该违例能被捕获,并获得正确对待。掷出一个违例时,违例控制器会自动搜索自变量与违例类型相符的第一个控制器,并不在搜索其他违例控制器。

try{可能产生违例的地方}生成的违例在catch中中止catch(Exception1 exception1){处理特定类型的违例}catch(Exception2 exception2){处理特定类型的违例}...}.catch(Exceptionn Exceptionn){处理特定类型的违例}抛出所有潜在的违例类型void f() throws Exception1,...Exceptionn{..}

3.重新掷出违例
掷出当前违例句柄,违例进入更高一级违例控制器中,同一try块中的catch从句仍然被忽略。使用throw掷出当前句柄e,只有在高一级catch块中捕获。

package com.zd.java.exception;/** * 将当前堆栈的信息填充到原来的违例中 * Created by ZD on 2017/10/10. */public class Rethrowing {    public static void f() throws Exception{        System.out.println("originating the exception in f()");        throw new Exception("throw from f()");    }    public static void g() throws Throwable{        try{            f();        }catch (Exception e){            System.out.println("Inside g(),e.printStackTrace()");            e.printStackTrace();            throw e;        }    }    public static void main(String[] args) throws Throwable{        try{            g();        }catch (Exception e){            System.out.println("caught in main,e.printStackTrace()");            e.printStackTrace();        }    }}打印结果:originating the exception in f()java.lang.Exception: throw from f()Inside g(),e.printStackTrace()    at com.zd.java.exception.Rethrowing.f(Rethrowing.java:11)    at com.zd.java.exception.Rethrowing.g(Rethrowing.java:16)    at com.zd.java.exception.Rethrowing.main(Rethrowing.java:26)caught in main,e.printStackTrace()java.lang.Exception: throw from f()    at com.zd.java.exception.Rethrowing.f(Rethrowing.java:11)    at com.zd.java.exception.Rethrowing.g(Rethrowing.java:16)    at com.zd.java.exception.Rethrowing.main(Rethrowing.java:26)

4.创建自己的违例
经常需要创建自己的违例,指出自己所写的库可能存在的问题,创建自己的违例类,必须从一个现有的违例类型继承,最好在含义上与新违例类似。

java.lang.Exception–>程序能捕获的基本违例,其他违例基本都是从此衍生出去的,也有程序不是从Exception衍生的,比如IO有关的都是从IOException衍生的。

package com.zd.java.exception;/** * 创建自己的违例时,可以采取更多的操作,可添加额外的构建器及成员 * Created by ZD on 2017/10/10. */public class Inheriting2 {    public static void f() throws MyException2{        System.out.println("throwing myexception2 from f()");        throw new MyException2();    }    public static void g() throws MyException2{        System.out.println("throwing myexception2 from g()");        throw new MyException2("originated in g()");    }    public static void h() throws MyException2{        System.out.println("throwing myexception2 from h()");        throw new MyException2("originated in h()");    }    public static void main(String[] args){        try{            f();        }catch (MyException2 e){            e.printStackTrace();        }        try{            g();        }catch (MyException2 e){          // e.printStackTrace();        }        try{            h();        }catch (MyException2 e){           // e.printStackTrace();            System.out.println("e.val()="+e.val());        }    }}class MyException2 extends Exception{    private int i;    public MyException2(){}    public MyException2(String msg){        super(msg);    }    public MyException2(String msg,int x){        super(msg);        i = x;    }    public int val(){        return i;    }}com.zd.java.exception.MyException2    at com.zd.java.exception.Inheriting2.f(Inheriting2.java:10)    at com.zd.java.exception.Inheriting2.main(Inheriting2.java:25)throwing myexception2 from f()throwing myexception2 from g()throwing myexception2 from h()e.val()=0

5.违例的限制
覆盖一个方法时,只能产生在方法基础类版本中声明的违例,重写方法中可以不声明违例,但不能声明未在基类方法中声明的违例。

package com.zd.java.exception;/** * Created by ZD on 2017/10/11. */class BaseballException extends Exception{}class Foul extends BaseballException{}class Strike extends BaseballException{}abstract class Inning{    Inning() throws BaseballException{}    void event() throws BaseballException{}    abstract void atBat() throws Strike,Foul;    void walk(){};}class StromException extends Exception{}class RainedOut extends StromException{}class PopFoul extends Foul{}interface Storm{    void event() throws RainedOut;    void rainHard() throws RainedOut;}public class StormyInning extends Inning implements Storm {    StormyInning() throws RainedOut,BaseballException{}//    /**//     * 基类方法walk未声明抛出PopFoul异常,子类方法不可抛出//      * @throws PopFoul//     */    //void walk() throws PopFoul{}//    /**//     * 实现接口的event方法,基类中也有event方法,相当于重写了基类的event方法,//     * 在基类event方法中没有声明RainedOut异常//     * @throws RainedOut//     *///    @Override//    public void event() throws RainedOut {//    }    /**     * 实现接口方法,重写了基类中方法,接口方法声明异常与基类方法声明异常不一致,可以选择不抛出异常     */    @Override    public void event() {    }    @Override    public void rainHard() throws RainedOut {    }    /**     * 重写方法可以抛出异常的子类     * @throws PopFoul     */    @Override    void atBat() throws PopFoul{    }    public static void main(String[] args){        try{            StormyInning si = new StormyInning();            si.atBat();        }catch (PopFoul popFoul) {            popFoul.printStackTrace();        }catch (RainedOut rainedOut) {            rainedOut.printStackTrace();        } catch (BaseballException e) {            e.printStackTrace();        }        try{            Inning i = new StormyInning();            i.atBat();        }catch (RainedOut rainedOut) {            rainedOut.printStackTrace();        } catch (Strike strike) {            strike.printStackTrace();        } catch (Foul foul) {            foul.printStackTrace();        } catch (BaseballException e) {            e.printStackTrace();        }    }}

6.finally
无论一个违例是否发生,都想要执行特定的代码。

try{可能产生违例的地方}生成的违例在catch中中止catch(Exception1 exception1){处理特定类型的违例}catch(Exception2 exception2){处理特定类型的违例}...}.catch(Exceptionn Exceptionn){处理特定类型的违例}finally{无论何种情况,一定会执行的}

finally使用过程中需要注意,在构建器中使用违例控制时,比如打开文件,finally就不是关闭文件位置的好选择。

package com.zd.java.exception;

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
/**
* Created by ZD on 2017/10/11.
*/
class InputFile{
private BufferedReader in;
InputFile(String filename) throws Exception{
try{
in = new BufferedReader(new FileReader(filename));
}catch (FileNotFoundException e){
System.out.println(“could not open “+filename);
throw e;
}catch (Exception e){
try{
in.close();
System.out.println(“in.close()”);
}catch (IOException e2){
System.out.println(“in.close() unsuccessful”);
}
throw e;
}finally {
//do not close it here
}
}
String getLine() {
String s;
try{
s = in.readLine();
}catch (IOException e){
System.out.println(“readLine() unsucessful”);
s = “failed”;
}
return s;
}
void cleanuo(){
try{
in.close();
}catch (IOException e){
System.out.println(“in.close() unsucessful”);
}
}
}

public class Cleanup {
public static void main(String[] args){
try{
InputFile file = new InputFile(“Cleanup.java”);
String s;
int i = 1;
while ((s = file.getLine()) != null){
System.out.println(“”+ i++ + “: “+s);
}
file.cleanuo();
}catch (Exception e){
System.out.println(“caught in main,e.printStackTrace()”);
e.printStackTrace();
}
}
}
执行结果:
could not open Cleanup.java
caught in main,e.printStackTrace()
java.io.FileNotFoundException: Cleanup.java (系统找不到指定的文件。)
at java.io.FileInputStream.open(Native Method)
at java.io.FileInputStream.(FileInputStream.java:138)
at java.io.FileInputStream.(FileInputStream.java:93)
at java.io.FileReader.(FileReader.java:58)
at com.zd.java.exception.InputFile.(Cleanup.java:17)
at com.zd.java.exception.Cleanup.main(Cleanup.java:59)

7.违例丢失
违例可能会丢失,在使用finally从句中存在违例丢失情况
**

package com.zd.java.exception;/** * 违例可能会丢失 * VeryImportantException违例丢失 * Created by ZD on 2017/10/11. */class VeryImportantException extends Exception{    public String toString(){        return "a very important exception";    }}class HoHumException extends  Exception{    public String toString(){        return "a trivial exception";    }}public class LostMessage {    void f() throws VeryImportantException{        throw new VeryImportantException();    }    void dispose() throws HoHumException{        throw new HoHumException();    }    public static void main(String[] args) throws Exception{        LostMessage lm = new LostMessage();        try{            lm.f();        }finally {            lm.dispose();        }    }}输出结果:Exception in thread "main" a trivial exception    at com.zd.java.exception.LostMessage.dispose(LostMessage.java:29)    at com.zd.java.exception.LostMessage.main(LostMessage.java:38)

**

原创粉丝点击