开发者社区> 问答> 正文

重构:Java特别的接口修改:在throws子句中添加一个异常?报错

《重构:改善既有代码的设计》
P65:Java之中还有一个特别关于「修改接口」的问题:在Throws子句中增加一个异常。这并不是对签名式(signature)的修改,所以你无法以delegation(委托手法)隐 藏它。但如果用户代码不做出相应修改,编译器不会让它通过。这个问题很难解决。你可以为这个函数选择一个新名字,让旧函数调用它,并将这个新增的checked exception(可控式异常〗转换成一个unchecked exception(不可控异常:)。你也可 以拋出一个unchecked异常,不过这样你就会失去检验能力。如果你那么做,你可以警告调用者:这个unchecked异常日后会变成一个checked异常。这样他们就有时间在自己的代码中加上对此异常的处理。出于这个原因,我总是喜欢为整个package定义一个superclass异常(就像java.sql的SQLException),并确保所有public函数只在自己的throws子句中声明这个异常。这样我就可以随心所欲地定义异常,不会影响调用者,因为调用者永远只知道那个更具一般性的superclass异常。
请问这段话是什么意思?

展开
收起
因为相信,所以看见。 2020-05-27 10:00:04 975 0
1 条回答
写回答
取消 提交回答
  • 阿里,我所有的向往

    "

    我用具体的代码来解释下吧
    接口A,有方法X

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

    在用户模块有这样一段调用

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

    现在要对方法X增加一个异常,变为:

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

    这样用户模块ModuleUser的方法Y就要修改,不修改,编译就不会通过。

    怎么样解决呢?
    方法1,新方法调用旧方法。(接口中不能新方调用旧方法,所以我改为抽象类)

    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: 以拋出一个unchecked异常,unchecked就是编译器不检查的运行时异常。
    如下

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

    这样用户代码也不用改。

    但这两个方法都不好。

    作者喜欢的做法是这样的(也是推荐的方式)。
    在包中定义自己的异常

    public class MyException extends Exception {
    
    }
    

    接口一开始就写成

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

    用户模块就会是这样的:

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

    如果再遇到上面要加异常信息的情况
    就为MyException创建一个子类,加接口A上,这样用户代码就不用改,也能适配。

    上面一段话大概就是想表达这个观点。
    因为这本书是国外人写的,翻译成中文,所以读起来有点别扭。
    英文原文是这样的

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

    读这本书,觉得不好理解的,就可试着看看英文原文。

    "
    2020-05-27 16:47:16
    赞同 展开评论 打赏
问答分类:
问答地址:
问答排行榜
最热
最新

相关电子书

更多
Spring Cloud Alibaba - 重新定义 Java Cloud-Native 立即下载
The Reactive Cloud Native Arch 立即下载
JAVA开发手册1.5.0 立即下载