在 servlet 中使用断言

using assert in servlet

我遇到以下问题:在 servlet 中,我需要处理来自已实施的供应商(仅接口已知)的不同输入(在以下列表中)。这种处理只有在列表具有相同大小的情况下才有意义(几乎可以肯定是这种情况,除非供应商功能搞砸了),因此我想在大小上使用 assert (否则它会抛出和索引出 Bound Exception 或类似的东西,这对后来的开发人员来说很难调试)。这里的问题是,我的程序将在没有 -ea 参数的服务器上 运行。我的问题是:是否仍然可以 assert 正确的方式:

try{
    List listA = supplier.getListA();
    List listB = supplier.getListB();
    assert listA.size()==listB.size();

    List listC = supplier.getListC();
    assert listA.size()==listC.size();
}
catch(AssertionError error){
   //error handling
}

或者我是否被抛回异常:

try{
    List listA = supplier.getListA();
    List listB = supplier.getListB();
    if(listA.size()!=listB.size())
        throw new RuntimeException();

    List listC = supplier.getListC();
    if(listA.size()!=listC.size())
        throw new RuntimeException();
}
catch(RuntimeException exception){
   //error handling
}

为了可读性,强烈推荐前一种方式,但不一定能在服务器上运行。

有些语言设计不同,但在 Java 中,使用异常进行流量控制是搬起石头砸自己脚的好方法。

你为什么不做一个 if 声明并检查条件?

List listA = supplier.getListA();
List listB = supplier.getListB();
List listC = supplier.getListC();
if(listA.size()==listB.size() && listA.size()==listC.size()) {
    //happy path :)
} else {
    //sad path :(
}

我将扩展我的评论:

您可以使用包含 Assert class 的外部库,也可以使用自己的库,例如像这样:

class AssertionException extends Exception {
  //content goes here
}

class Assert {
  public void sameSize( Collection<?> a, Collection<?> b ) {
    //TODO: handle null as well
    if( a.size() != b.size() ) {
      throw new AssertionException("some message"); 
    }
  }
}

那么你的代码就变成了:

try{
  List listA = supplier.getListA();
  List listB = supplier.getListB();
  Assert.sameSize( listA, listB );

  List listC = supplier.getListC();
  Assert.sameSize( listA, listC );
 }
catch(AssertionException ex){
  //error handling
}

它与语言级别的断言基本相同(错误和异常无论如何都是可抛出的,但错误更常用于表达致命情况,而这里不是这种情况)。

我想重申一下 CptBartender 所说的:错误和异常是表达意外行为的一种方式,即是否使用它们取决于您的错误处理代码将执行的操作以及错误情况是否应该发生是否在正常执行期间。