鍍金池/ 問答/Java  數(shù)據(jù)庫/ 重構(gòu):Java特別的接口修改:在throws子句中添加一個(gè)異常?

重構(gòu):Java特別的接口修改:在throws子句中添加一個(gè)異常?

《重構(gòu):改善既有代碼的設(shè)計(jì)》
P65:Java之中還有一個(gè)特別關(guān)于「修改接口」的問題:在Throws子句中增加一個(gè)異常。這并不是對(duì)簽名式(signature)的修改,所以你無法以delegation(委托手法)隱 藏它。但如果用戶代碼不做出相應(yīng)修改,編譯器不會(huì)讓它通過。這個(gè)問題很難解決。你可以為這個(gè)函數(shù)選擇一個(gè)新名字,讓舊函數(shù)調(diào)用它,并將這個(gè)新增的checked exception(可控式異常〗轉(zhuǎn)換成一個(gè)unchecked exception(不可控異常:)。你也可 以拋出一個(gè)unchecked異常,不過這樣你就會(huì)失去檢驗(yàn)?zāi)芰?。如果你那么做,你可以警告調(diào)用者:這個(gè)unchecked異常日后會(huì)變成一個(gè)checked異常。這樣他們就有時(shí)間在自己的代碼中加上對(duì)此異常的處理。出于這個(gè)原因,我總是喜歡為整個(gè)package定義一個(gè)superclass異常(就像java.sql的SQLException),并確保所有public函數(shù)只在自己的throws子句中聲明這個(gè)異常。這樣我就可以隨心所欲地定義異常,不會(huì)影響調(diào)用者,因?yàn)檎{(diào)用者永遠(yuǎn)只知道那個(gè)更具一般性的superclass異常。
請(qǐng)問這段話是什么意思?

回答
編輯回答
巫婆

我用具體的代碼來解釋下吧
接口A,有方法X

public interface A {
    public void methodX() throws IOException;
}

在用戶模塊有這樣一段調(diào)用

public class ModuleUser{
    public void methodY(A a) throws IOException
    {
        a.methodX();
    }
}

現(xiàn)在要對(duì)方法X增加一個(gè)異常,變?yōu)椋?/p>

public interface A {
    public void methodX() throws IOException,DataFormatException;
}

這樣用戶模塊ModuleUser的方法Y就要修改,不修改,編譯就不會(huì)通過。

怎么樣解決呢?
方法1,新方法調(diào)用舊方法。(接口中不能新方調(diào)用舊方法,所以我改為抽象類)

public abstract class A {
    public void methodX() throws IOException
    {
        try {
            methodNewX();
        } catch (DataFormatException e) {
            throw new RuntimeException(e);
        }
    }
    
    public abstract void methodNewX() throws IOException ,DataFormatException;
}

方法2: 以拋出一個(gè)unchecked異常,unchecked就是編譯器不檢查的運(yùn)行時(shí)異常。
如下

public interface A {
    public void methodX() throws IOException,RuntimeException;
}

這樣用戶代碼也不用改。

但這兩個(gè)方法都不好。

作者喜歡的做法是這樣的(也是推薦的方式)。
在包中定義自己的異常

public class MyException extends Exception {

}

接口一開始就寫成

public interface A {
    public void methodX() throws MyException;
}

用戶模塊就會(huì)是這樣的:

public class ModuleUser{
    public void methodY(A a) throws MyException
    {
        a.methodX();
    }
}

如果再遇到上面要加異常信息的情況
就為MyException創(chuàng)建一個(gè)子類,加接口A上,這樣用戶代碼就不用改,也能適配。

上面一段話大概就是想表達(dá)這個(gè)觀點(diǎn)。
因?yàn)檫@本書是國外人寫的,翻譯成中文,所以讀起來有點(diǎn)別扭。
英文原文是這樣的

There is one particular area with problems in changing interfaces in Java: adding an exception to the throws clause.

讀這本書,覺得不好理解的,就可試著看看英文原文。

2018年7月10日 19:49