七、异常处理——4-使用throw抛出异常

4-使用throw抛出异常

1.抛出异常

(1)如果需要在程序中自行抛出异常,则应该使用throw语句,throw语句可以单独使用,throw语句抛出的不是异常类,而是一个异常实例,而且每次只能抛出一个异常实例;

(2)throw语句如果抛出的异常是Checked异常,则该throw语句要么处于try块中,显式捕获该异常,要么放在一个带throws声明抛出的方法中,即把该异常交给方法的调用者处理;如果throw语句抛出的异常是Runtime异常,则该语句无须放在try块里,也无须放在throws声明的方法中;程序可以显式使用try..catch来捕获并处理该异常,也可以完全不理会异常,把异常交给调用者处理;

public class Test7 {
    public static void main(String[] args) {
        try{
            //调用声明抛出Checked异常的方法,要么显式捕获该异常
            //要么在main方法中再次声明抛出
            throwChecked(-3);
        }catch(Exception e){
            System.out.println(e.getMessage());
        }
        //调用声明抛出Runtime异常的方法既可以显式捕获该异常
        //也可以不理会该异常
        throwRuntime(3);
    }
    public static void throwChecked(int a) throws Exception{
        if(a>0){
            //自行抛出Exception异常
            //该代码必须处于try...catch块中,或处于带throws声明的方法中
            throw new Exception("a的值大于0,不符合要求");
        }
    }
    public static void throwRuntime(int a){
        if(a>0){
            //自行抛出RuntimeException异常,既可以显式捕获该异常
            //也可完全不理会该异常,把该异常交给该方法的调用者处理
            throw new RuntimeException("a的值大于0,不符合要求");
        }
    }
}

 

2.自定义异常类

(1)用户自定义异常都应该继承Exception基类,如果希望自定义Runtime异常,则应该继承RuntimeException异常基类。

(2)定义异常类时通常需要提供两个构造器,一个无参构造器,一个带有字符串参数的构造器,这个字符串将作为该异常对象的描述信息,即getMessage()方法的返回值;

public class MyException extends Exception{
    //无参数构造器
    public MyException(){
        
    }
    //带一个字符串参数的构造器
    public MyException(String msg){
        super(msg);
    }
}

 

3.catch和throw同时使用

(1)多个方法协同处理同一个异常的情形,可以在catch块中结合throw语句来完成:

public class AuctionTest {
    private double initPrice = 30.0;
    //因为该方法中显式抛出了AuctionException异常
    //所以此处需要声明抛出AuctionException异常
    public void bid(String bidPrice)throws MyException{
        double d = 0.0;
        try{
            d = Double.parseDouble(bidPrice);
        }catch(Exception e){
            //此处完成本方法中可以对异常执行的修复处理
            //此处仅仅是在控制台打印异常的跟踪栈信息
            e.printStackTrace();
            //再次抛出自定义异常
            throw new MyException("竞拍价格必须是数值,不能包含其他字符");
        }
        if(initPrice > d){
            throw new MyException("竞拍价比起拍价低,不允许竞拍");
        }
        initPrice = d;
    }
    public static void main(String[] args) {
        AuctionTest at = new AuctionTest();
        try{
            at.bid("df");
        }catch(MyException e){
            //再次捕获到bid()方法中的异常,并对该异常进行处理
            System.out.println(e.getMessage());
        }
    }
}

 

4.throw语句增强

  有如下代码:

  try{

    new FileInputStream("a.txt");

  }catch(Exception e){

    e.printStackTrace();

    throw e;  //再次抛出捕获到的异常

  }

  Java7以前,因为捕获到异常时声明的异常类型为Exception,所以在再次抛出异常时抛出的异常同样为Exception异常:

  public staic void main(String args[])

    throws Exception  //Java6认为可能抛出Exception异常

  {

    try{

      new FileInputStream("a.txt");

    }catch(Exception e){  //声明捕获到的异常为Exception异常

      e.printStackTrace();

      throw e;  //声明捕获的异常是Exception 再次抛出的异常同样为Exception

    }

  }

  从java7开始,编译器会自行检查throw语句抛出异常的实际类型:

  public staic void main(String args[])

    throws FileNotFoundException  //Java7编译器检查后,只需抛出FileNotFoundException异常

  {

    try{

      new FileInputStream("a.txt");

    }catch(Exception e){  //声明捕获到的异常为Exception异常

      e.printStackTrace();

      throw e;//声明捕获的异常是Exception 编译器检查后实际上的异常为FileNotFoundException异常

    }

  }

 

5.异常链

(1)把底层原始异常直接传给用户是一种不好的表现,通常做法为:程序先捕获原始异常,然后抛出一个新的业务异常,新的业务异常包含对用户的提示信息,这种处理方式被称为异常转译;

(2)把原始异常隐藏起来,仅仅向上提供必要的提示信息的处理方式,可以保证底层异常不会扩散到表现层。

posted @ 2017-08-02 20:18  丶theDawn  阅读(1309)  评论(0编辑  收藏  举报