0

这是来自 Effective java 的引用。

“在可能的情况下,处理来自较低层的异常的最佳方法是避免它们,通过确保较低级别的方法成功。有时您可以通过在将较高级别方法的参数传递给较低级别​​之前检查较高级别方法的参数的有效性来做到这一点层。”

考虑一个名为“AccessControlContext actx”的对象,它从处理程序传播到较低级别。我们可以对“actx!= null”进行更高级别的检查,但是否需要再次在较低级别进行检查?

例如在伪代码中:

class RestServlet {
   void verify Servlet(AccessControlContext actx) {
        // check made at higher level according to effective java
        if (actx == null) { throw exception; }  
        // do something
        Verify.checkAccessControl(actx); // calling lower leve
        // do something
    }
}

class Verify {
   static checkAccessControl(actx) {
        // DO I NEED NULL POINTER CHECK HERE AGAIN ?
   }
} 

尽管问题嵌套在评论中,但要反复阐述。较低级别的冗余检查可确保防御性编码,但是 - 它是冗余的。它可能在 javadocs 中清楚地说明它不接受 null,但这并不能解决拥有无错误代码的目的。我们应该重复异常检查吗?

注意:这是一个随机示例。我的问题并不特定于这个例子。这是一个更广泛的问题,旨在了解复制异常的程度。

4

2 回答 2

1

在验证参数方面,我认为您不能经常这样做。我习惯的工作方式是在代码的所有层中验证参数。如果一个方法不能处理一个空值(例如它会导致一个空指针),它应该由方法本身来确保传递的参数不为空。这同样适用于错误的参数值会在层中进一步导致异常的方法。

在我看来,如果一个错误的参数会导致异常,无论是高级别的参数验证还是低级别的参数验证抛出的异常都没有关系,总之比如果根本没有验证会导致异常(或者更糟糕的是,没有异常和错误执行。)

通过让每个方法负责验证其输入,即使它只是一个传递方法,也可以确保阻止任何调用现有方法的新方法传递错误的参数,因为它会导致验证异常,无论被调用的方法是高级方法还是低级方法。

因此,在您的示例中,我将验证两种方法中的输入,并附带测试来验证验证是否正常运行。输入验证也可以像单行一样简单,查看 Apache commons lang 的 Validate 类:http: //commons.apache.org/proper/commons-lang/javadocs/api-2.6/org/apache/commons /lang/Validate.html

例如:

import org.apache.commons.lang.Validate;
import org.apache.commons.lang.StringUtils;

public class Something {
   public void doSomething(final Integer someInt, final String someString) {
       Validate.notNull(someInt, "Can't proceed when someInt is null!");
       Validate.isTrue(!StringUtils.isEmpty(someString, "Can't proceed when someString is null or empty!");
       //do stuff
   }
}

如果验证失败,IllegalArgumentException将抛出一个定义为第二个参数的消息。测试可能如下所示:

public class SomethingTest {

    private Something something;

    @Rule
    public ExpectedException expectedException = ExpectedException.none();

    @Before
    public void setup() {        
        something = new Something();
    }

    @Test
    public void doSomethingShouldFailIfSomeIntIsNull() {
        expectedException.expect(IllegalArgumentException.class);
        expectedException.expectMessage("someInt is null");

        something.doSomething(null, "hello");
   }

   @Test
   public void doSomethingShouldFailIfSomeStringIsEmpty() {
        expectedException.expect(IllegalArgumentException.class);
        expectedException.expectMessage("someString is null or empty");

        something.doSomething(123, "");
   }

   //more tests..
}
于 2013-08-15T20:59:32.757 回答
0

我不确定我是否会对这种方法感到满意,如果checkAccessControl从很多地方调用怎么办?您必须依靠每个调用者进行空值检查 - 这不是一种安全的方法。我会将空值检查放入该checkAccessControl方法中,如果检测到空值,可能会抛出 IllegalArgumentException。

因此,我的广泛方法是,如果您的方法依赖于呈现给它的特定值(例如,参数不能为 null ),我会让方法负责验证它。

您当然仍然可以要求调用者为您验证参数(例如通过 javadocs),但您不能强制执行它。

于 2013-08-15T20:54:23.273 回答