如何避免重复复杂的catch块

时间:2010-02-16 12:06:54

标签: java

我有这段代码:

try {
    do_stuff();
    return do_more_stuff();
} catch (UnsupportedEncodingException e) {
    throw CustomException.programmer_error(e);
} catch (ProtocolException e) {
    throw CustomException.programmer_error(e);
} catch (MalformedURLException e) {
    throw CustomException.programmer_error(e);
} catch (SocketTimeoutException e) {
    throw new CustomException(e);
} catch (IOException e) {
    throw CustomException.unexpected_error(e);
}

我现在需要在另一个类似的函数中拥有所有catch块。避免重复的最佳方法是什么?

请注意,两个try块中的代码不是很相似。

此外,我无法真正把这些捕获物放得更高。

注意,我宁愿避免:

try {
    do_stuff();
    return do_more_stuff();
} catch (Exception e) {
    handle_exception_via_rtti(e);
}

5 个答案:

答案 0 :(得分:7)

就个人而言,我会尝试制作

do_stuff();
return do_more_stuff();

部分符合更通用的格式,以便应用策略(作为模式)。

然后你可以重构你调用这种块的所有地方,这样他们就可以调用一个更通用的块(捕获只被放置一次)。

答案 1 :(得分:5)

  

注意,我宁愿避免:

然后要么只是忍受它,要么等到JDK7带有Multicatch,这样你就可以重写:

try {
    do_stuff();
    return do_more_stuff();
} catch (UnsupportedEncodingException | ProtocolException | MalformedURLException e) {
    throw CustomException.programmer_error(e);
} catch (SocketTimeoutException e) {
    throw new CustomException(e);
} catch (IOException e) {
    throw CustomException.unexpected_error(e);
}

您也可以将其移动到CustomException的构造函数中并执行(讨厌的)全局捕获,但是您需要添加一堆(讨厌的)if/else块来确定异常原因的类型。总而言之,我只是喜欢坚持你已经做过的方式。

更新:另一种方法是拆分/重构行,这些行可能会将异常作为单独的任务抛出到另一个抛出CustomException的方法块中。 E.g。

try {
    do_stuff_with_encoding();
    do_stuff_with_url();
    do_stuff_with_ws();
    // ...
    return do_more_stuff();
} catch (SocketTimeoutException e) {
    throw new CustomException(e);
} catch (IOException e) {
    throw CustomException.unexpected_error(e);
}

...

public SomeObject do_stuff_with_encoding() throws CustomException {
    try {
        do_stuff();
    } catch (UnsupportedEncodingException e) {
        throw CustomException.programmer_error(e);
    }
}  

public SomeObject do_stuff_with_url() throws CustomException {
    try {
        do_stuff();
    } catch (MalformedURLException e) {
        throw CustomException.programmer_error(e);
    }
}  

public SomeObject do_stuff_with_ws() throws CustomException {
    try {
        do_stuff();
    } catch (ProtocolException e) {
        throw CustomException.programmer_error(e);
    }
}  

答案 2 :(得分:2)

这取决于do_stuffdo_more_stuff抛出已检查异常的原因。他们这样做是为了强迫用户处理异常吗?如果是,那么你试图避免:

try {
    do_stuff();
    return do_more_stuff();
} catch (Exception e) {
    handle_exception_via_rtti(e);
}

是一件好事。

如果您的代码只是抓住了Exception,而do_stuffdo_more_stuff稍后会添加额外的异常,那么您可能永远都不会知道这些变化以及您的代码现在可能是错。

因此,您可能必须处理throwing the kitchen sink并处理所有这些异常,除非方法可以切换到未经检查的异常。

另一方面,如果方法抛出检查异常只是因为程序员在处理它们时懒得而只是想推卸责任,也许你是从错误的角度看这个。

答案 3 :(得分:1)

如何引入可以进行子类化的通用Action类:

public class Action {
    public void runWithHandlers() throws Exception {
        try {
           run();
        } catch (UnsupportedEncodingException e) {
            throw CustomException.programmer_error(e);
        } catch (ProtocolException e) {
            throw CustomException.programmer_error(e);
        } catch (MalformedURLException e) {
            throw CustomException.programmer_error(e);
        } catch (SocketTimeoutException e) {
            throw new CustomException(e);
        } catch (IOException e) {
            throw CustomException.unexpected_error(e);
        }
    }
    public void run() throws Exception {
        // TODO subclasses of Action must implement this
    }
}

然后在代码中的其他地方实例化Action的一个子类并调用runWithHandlers():

new MyAction().runWithHandlers();

答案 4 :(得分:0)

如果您能负担得起Scala,请查看它:您可以在catch块中模式匹配异常。请参阅Scala for Java Refugees Part 4: Pattern Matching and Exceptions