0

假设我们有一个类 Graph 和另一个名为 GraphWrapper 的类。Graph 类有一个名为 returnAdjVertices 的方法。

public List returnAdjVertices(int vertex) {
    if (vertex < 0 || vertex >= maxVertexCount) {
        throw exception
    }
}

现在我们在 GraphWrapper 中有一个包装函数,它可以计算顶点的度数

public static int getDegree(Graph graph, int vertex) {
    if (graph == null) throw new NullPointerException();
    if (vertext < 0 || vertex >= graph.maxVertexCount) throw exception // REDUNDANT

    return graph.returnAdjVertices(vertex).size();
}

现在查找度数的调用正在检查顶点绑定条件两次。

这意味着我们正在进行冗余检查。在这种情况下,为异常处理推荐的最佳实践是什么?

4

3 回答 3

2

您可以重新抛出异常(如果您没有在包装器中捕获它,它将自动完成)

public static int getDegree(Graph graph, int vertex) throws VertexOutOfBoundsException {
    return graph.returnAdjVertices(vertex).size();
}

或将其捕获在您的包装器中并重新翻译为另一个

public static int getDegree(Graph graph, int vertex) throws WrapperException {
    int result;
    try {
        result = graph.returnAdjVertices(vertex).size();
    } catch (VertexOutOfBoundsException e) {
        throw new WrapperException();
    }
    return result;
}

甚至抓住它并尝试修复它

public static int getDegree(Graph graph, int vertex) {
    int result;
    try {
        result = graph.returnAdjVertices(vertex).size();
    } catch (VertexOutOfBoundsException e) {
        result = fixGraphAndReturnAdjVertices(graph, vertex);
    }
    return result;
}

您不应该再次进行检查,因为它可能真的很难维护。
变体的选择始终是情境性的。
当您的包装器与包装对象处于同一抽象级别时,第一个变体(自动重新抛出)很好。
当包装器和包装对象处于不同的抽象级别时,第二个变体很好,例如,我可以建议使用 HDD 的对象的“FileNotFoundException”可以转换为尝试加载的对象的“CannotLoadDataException”之类的东西,如果它对于调用者来说,究竟出了什么问题。
当您的包装器可以修复问题时,第三个变体很好:)
所以这完全取决于您。希望我的回答有帮助。

于 2013-08-15T13:27:41.007 回答
0

如您所述,检查是多余的。所以你可以简单地从包装器中删除它。异常将向上移动调用堆栈。

我会在这两种方法的文档中明确指出,当顶点不在接受的边界之间时会引发异常。或者至少在包装方法的文档中明确说明它在内部调用包装的方法,从而引发相同的异常。

于 2013-08-15T13:06:27.357 回答
0

在这种特殊情况下?它是多余的,应该被消除——至少如果你要抛出相同的异常,并且代码中没有其他可能的副作用。

一般情况下?这完全取决于您的需求、代码等。

一个问题是,如果您的明确意图是执行完全相同的检查,则需要监视包装类以确保保护子句没有更改,或者将保护逻辑提取到可以独立调用的单独方法中。不过,这是泄漏封装。

另外,我会抛出一个IllegalArgumentException带有消息而不是 NPE 的消息。

于 2013-08-15T13:07:24.500 回答