违例差错控制

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

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

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

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

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)

**

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值