7.Practical Java_实践 16-27:异常处理

版权声明:转载的文章,如果不同意请联系告知,谢谢。 https://blog.csdn.net/qq_20398345/article/details/81912206

实践 16:认识「异常控制流」 ( exception controlflow)机制

 

实践 17:绝对不可轻忽异常(Never ignoreanexception)
 

1. 提供LogException(),将异常信息写入文件,进行分析

2. 使用printStaticTrace()获取异常信息,进行分析

实践 18:千万不要遮掩异常( Never hide anexception)

实践 19:明察 throws子句的缺点
throws子句用来向函数调用者发出预警,告知将会产生哪些异常。
 

实践 20:细致而全面地理解throws子句
 

实践 21:使用finally 避免资源泄露( resourceleaks)
 

实践 22:不要从 try区段中返回
 

public class FinalTest {
    public int method1() {
        try{
            return 2;
        }
        catch (Exception e) {
            return 3;
        }
    }
    public int method2() {
        try{
            return 3;
        }
        finally {
            return 4;
        }
    }

    public static void main(String[] args) {
        FinalTest ft = new FinalTest();
        System.out.println("method1 returns " + ft.method1());
        System.out.println("method2 returns " + ft.method2());
    }
}
method1 returns 2
method2 returns 4

实践 23:将 try/catch区段置于循环之外


在[启用JTM编译器]的情形下执行上述代码,两个函数的执行时间并没有什么不同。可是一旦你将JVM的JIT关闭再执行之, method2()大约比methodl()慢21%。
 

public class Excpef {
    public void method1(int size) {
        int[] ia = new int[size];
        try {
            for (int i = 0; i < size; i++) {
                ia[i] = i;
            }
        }
        catch (Exception e) {
            
        }
    }
    
    public void method2(int size) {
        int[] ia = new int[size];
        for (int i = 0; i < size; i++) {
            try {
                ia[i] = i;
            }
            catch (Exception e) {
                
            }
        }
    }
}

实践 24:不要将异常用于流程控制
 

实践25:不要每逢出错就使用异常( exceptions)
 

实践26:在构造函数(constructors)中抛出异常
尽管构造函数不是一般的函数,但他们仍然可以引发异常,并支持 throws语句。以这方式来构建失
败,是最强固、最高效的选择,从 class用户角度来看他要求的手工干预最小。
 

实践 27:抛出异常之前先将对象恢复为有效状态(valid state)
 

抛出异常是为了什么?明显的目的是将已发生的问题通知系统的其他部分。 隐含的目的则是让软件捕获异常,使系统有可能从问题中抽身回复(recover)而维持正常运行状态。
每当你撰写可能引发异常的代码时,都必须问自己: (1)异常发生之时(2)异常处理过后(3)复入(reentered)这段代码时,会发生什么事情?代码运转还能够正常吗?
 

import java.io.IOException;

class MutualFound1 {
    public void buyMoreShares(double money) {}
}
class Customer1 {
    private MutualFound1[] fundArray;
    public Customer1(){}
    public MutualFound1[] funds() {
        return fundArray;
    }
    public void updateMutualFund(MutualFound1 fund) throws DatabaseException1 {}
    public void writePortfolioChange() throws IOException {}
}
class DatabaseException1 extends Exception {}
public class ServiceClass1 {
    public void invest(Customer1 cust, double money) throws DatabaseException1, IOException {
        MutualFound1[] array = cust.funds();         //1
        int size = array.length;
        for (int i = 0; i < size; i++) {
            array[i].buyMoreShares(money);
            cust.updateMutualFund(array[i]);         //2
            cust.writePortfolioChange();
        }
    }
}
/*
 * 问题:
假设某位客户在三个互惠基金中都拥有股票(shares), 并打算为每个基金各自再买进$1,000//l
取得了所有基金构成的 array,/ / 2 为 array 的第一笔基金购买$1,000,的股票,并通过
updateMutualFund()成功地将更新后的基金写入数据库。然后调用writePortfolioChange(),将某些信息写入文件。这时候这个函数失败了,因为磁盘空间不足,无法建立文件。于是在对第一
个MutualFund对象完成[完整的三个步骤]之前, 抛出一个异常, 意外而鲁莽地退出了invest ( )。
假设invest()调用者通过释放磁盘空间等于法,顺利处理了这个异常,而后再次调用invest()。
当invest()再次执行时,//l取得基金array,而后进入循环,为每支基金购买股票。但是不要
忘了,先前第一次调用invest()的时候,你已经为第一支基金购买了$1,000的股票。此时又再做
一遍。 如果这次invest () 顺利为客户的三笔基金完成了操作, 你就是为第一笔基金购买了$2,000,
而其他两支基金各购买$1,000,这是不正确的。显然不是你期望的结果。
就[首先释放磁盘空间,而后再次调用这个函数]的做法而言,你正确地处理了异常。你没有做的
是,在抛出异常之后、退出invest()之前,关注对象的状态。
*/

//===================refactor code==================================================//
/*
* 解决办法:
此问题的一个修正办法是,在MutualFund和Customer两个classes中添加函数,并在invest()
处理异常时调用它们。这些函数用来撤销未竞全功的一些事件。 Invest()必须增加catch区段,
处理任何被引发的异常。这些catch区段应该调用相应函数*重置(重新设定)对象状态,这么一
来如果这个函数下次再被调用,就可以正确执行了。
另一个需要考虑的问题是, 万一[回复函数]undoMutualFundUpdate()和sellShares()也失败了, 情况会
变得如何?如果要保持系统顺利运转,你也需要对付这些失败。的确,正如你所看到,在抛出异常的时
候保持对象处于有效状态,可能非常困难,需要采取措施。
*/
import java.io.IOException;

class MutualFound1 {
    public void buyMoreShares(double money) {}
    public void shellShares(double mondy){} //refactor part 
}
class Customer1 {
    private MutualFound1[] fundArray;
    public Customer1(){}
    public MutualFound1[] funds() {
        return fundArray;
    }
    public void updateMutualFund(MutualFound1 fund) throws DatabaseException1 {}
    public void undoMutualFundUpdate(MutualFound1 fund) {} //refactor part
    public void writePortfolioChange() throws IOException {}
}
class DatabaseException1 extends Exception {}
public class ServiceClass1 {
    public void invest(Customer1 cust, double money) throws DatabaseException1, IOException {
        MutualFound1[] array = cust.funds();         
        int size = array.length;
        for (int i = 0; i < size; i++) {
            array[i].buyMoreShares(money);
            try {                                 //refactor part
                cust.updateMutualFund(array[i]);        
            }catch (DatabaseException1 dbe) {
                array[i].shellShares(money);
                throw dbe;
            }
            try {                                //refactor part
                cust.writePortfolioChange();
            } catch (IOException ioe) {
                array[i].shellShares(money);
                cust.undoMutualFundUpdate(array[i]);
                throw ioe;
            }
        }
    }
}

猜你喜欢

转载自blog.csdn.net/qq_20398345/article/details/81912206