异常处理的设计(三)

       这个月完了我得宣布停刊,暂时的,一来快没素材了,二来下个月工作比较忙。我一定会回来的...
       异常类这东西,说它是标准的Java类吧总觉得差那么点意思,像是发育不完全那种。我在其他的项目里也很少见到有异常施展面向对象或者继承结构的舞台。反正,在我的编程实践中,我确实是能用正常的就不会用它。不过,确实因为这个原因我还翻了个强到局域网外面找了找,结果还真找到了异常带来的惊喜。
       初级的Java开发者知道异常能抛能接,中高级的可能知道定义getters来获得更多的异常信息,有一撮牛人现在玩出来一些新花样给它们加上setters。乍一看觉得给异常这样短命的对象加上“状态”没有啥意思,我们现在来慢慢品味一番。
       这个例子涉及到这样一个场景,一些I/O的处理必须在用户的干预下才能继续进行,比如请用户确人路径或者权限之类的。扩展异常IOException给我们提供了一个解决方案:
 /** Specialized I/O exception to request some kind of user confirmation.
 * A code that needs to ask user shall not attempt to open a dialog itself,
 * rather it shall emit this exception and let its callers show the dialog
 * at appropriate time.
 */
public abstract class UserQuestionException extends IOException {
    /** Description of the dialog to show to the user. Whoever catches
     * this exception shall use 
     * {@link #getQuestionPane()}.
     * {@link JOptionPane#createDialog(java.lang.String)}
     * to construct and display the dialog.
     * 
     * @return the pane to display to user
     */
    public abstract JOptionPane getQuestionPane();
    /** When the user confirms (or rejects) message presented by the
     * {@link #getQuestionPane()} dialog, the exception shall be notified
     * by calling this method with {@link JOptionPane#getValue()} option.
     *
     * @param option the option selected by the user
     */
    public abstract void confirm(Object option);
}
confirm就是我说的setters
接上篇讲异常的扩展性我们可以整出两个版本
V1:
  try {
            OutputStream os = where.openConnection().getOutputStream();
            os.write(what.toString().getBytes());
            os.close();
        } catch (IOException ex) {
            JOptionPane.showMessageDialog(null, ex);
        }
和V2
 try {
                OutputStream os = where.openConnection().getOutputStream();
                os.write(what.toString().getBytes());
                os.close();
            } catch (UserQuestionException ex) {
                JOptionPane p = ex.getQuestionPane();
                JDialog d = p.createDialog(ex.getLocalizedMessage());
                setVisible(d, p);
                ex.confirm(p.getValue());
                if (
                    !p.getValue().equals(JOptionPane.CANCEL_OPTION) &&
                    !p.getValue().equals(JOptionPane.CLOSED_OPTION)
                ) {
                    continue;
                }
            } catch (IOException ex) {
                JOptionPane.showMessageDialog(null, ex);
            }
最后:
public final class QueryStream extends OutputStream {
    private ByteArrayOutputStream arr = new ByteArrayOutputStream();
    /** this field can be manipulated by the QueryException */
    Boolean reverse;

    @Override
    public synchronized void write(byte[] b, int off, int len)
    throws IOException {
        if (reverse == null) {
            throw new QueryException();
        }
        arr.write(b, off, len);
    }

    @Override
    public synchronized void write(int b) throws IOException {
        if (reverse == null) {
            throw new QueryException();
        }
        arr.write(b);
    }

    @Override
    public String toString() {
        if (reverse == null) {
            return "Reverse question was not answered yet!";
        }
        if (reverse) {
            StringBuilder sb = new StringBuilder();
            sb.append(arr.toString());
            sb.reverse();
            return sb.toString();
        }
        return arr.toString();
    }

    private class QueryException extends UserQuestionException {

        @Override
        public JOptionPane getQuestionPane() {
            JOptionPane p = new JOptionPane("Store in reverse way?");
            p.setOptionType(JOptionPane.YES_NO_CANCEL_OPTION);
            return p;
        }

        @Override
        public void confirm(Object option) {
            if (option.equals(JOptionPane.YES_OPTION)) {
                reverse = Boolean.TRUE;
                return;
            }
            if (option.equals(JOptionPane.NO_OPTION)) {
                reverse = Boolean.FALSE;
                return;
            }
        }
    }
}

解释一下:我们自定义的Exception起到了一个控制方向(reverse)的回调的作用。在收到正确的确认后,我们才可以接着走下去。

       这个例子到底对我们有啥子意义呢?没有啥意义,只是个演示只是一个欣赏这些高人代码的机会。因为异常之所以叫这个名字,他肯定使用的频率有限,我们可以姑且设定这个门限为1%吧。刚刚这种几乎涵盖了50%的代码路径显然是不合适的,并且代码结构和调用顺序也很复杂,把原本简单的事情搞得很麻烦。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值