assert使用场景



Assert use cases


常用的用assert场景:
先决条件(private方法中) - 方法调用者必须满足这些需求
后置条件 - 检查结果
类不变式class invariant - 检查对象状态
运行时不可达代码 - 某些分支预期不可达,但无法在编译器做检查(常见在else分支或switch的default分支)


下面是例子
import java.util.Random;


public final class Flower {


  public static void main(String... arguments) {
    final Flower tulip = new Flower("Tulip", 1);
    tulip.grow();
    tulip.grow();
    System.out.println(tulip);


    tulip.randomGrowOrWither();
    System.out.println(tulip);


    tulip.wither();
    tulip.wither();
    System.out.println(tulip);
  }


  /**
  * @param aSpecies must have content.
  * @param aInitialLength must be greater than 0.
  */
  public Flower(final String aSpecies, final int aInitialLength) {
    // 不要用assert来检查public方法的参数
    if (!isValidSpecies(aSpecies)) {
      throw new IllegalArgumentException("Species must have content.");
    }
    if (!isValidLength(aInitialLength)) {
      throw new IllegalArgumentException("Initial length must be positive.");
    }


    fSpecies = aSpecies;
    fLength = aInitialLength;


    // 检查类不变式
    assert hasValidState(): "Construction failed - not valid state.";
  }


  public boolean isMature() {
    return fLength > 5 ;
    // 无需assert, 因为对象状态没有改变
  }


  /**
  * Increase the length by at least one unit.
  */
  public void grow(){
    // 由于fLength总是被copy了一次,不管是否打开了assert
    // 这种风格的后置条件检查是不推荐的。后面的wither有一个改良版本的。
    final int oldLength = fLength;
    fLength += getLengthIncrease(fLength);
    //post-condition: length has increased
    assert fLength > oldLength;


    // 检查类不变式
    assert hasValidState(): this;
  }


  /**
  * Decrease the length by one unit, but only if the resulting length
  * will still be greater than 0.
  */
  public void wither(){
    // 这个局部类的存在是为了获取当时状态的一个快照,尽管有些笨重,但这种风格能作任意复杂的
    // 后置条件检查
    class OriginalState {
      OriginalState() {
        fOriginalLength = fLength;
      }
      int getLength() {
        return fOriginalLength;
      }
      private final int fOriginalLength;
    }
    OriginalState originalState = null;


    // 在assert函数里面构造对象,可以用于确保assert被关闭后不会有构造发生。
    // 这个assert有一点不一样的地方是他总是成功,并且有负作用,它构造了一个对象并保留了他的引用.
    assert (originalState = new OriginalState()) != null;


    if (fLength > 1) {
      --fLength;
    }


    // 后置条件检查: 长度减少1或保持不变
    assert fLength <= originalState.getLength();


    // 检查类不变式
    assert hasValidState(): this;
  }


  /**
  * Randomly select one of three actions
  * <ul>
  * <li>do nothing
  * <li>grow
  * <li>wither
  * </ul>
  */
  public void randomGrowOrWither() {
    //(magic numbers are used here instead of symbolic constants
    //to slightly clarify the example)
    Random generator = new Random();
    int action = generator.nextInt(3);
    //according to the documentation for the Random class, action
    //should take one of the values 0,1,2.
    if (action == 0) {
      //do nothing
    }
    else if (action == 1) {
      grow();
    }
    else if (action == 2) {
      wither();
    }
    else {
      // assert被禁止,仍有可能运行到这里
      throw new AssertionError("Unexpected value for action: " + action);
    }
    // 检查类不变式
    assert hasValidState(): this;
  }


  /** Use for debugging only.  */
  public String toString(){
    final StringBuilder result = new StringBuilder();
    result.append(this.getClass().getName());
    result.append(": Species=");
    result.append(fSpecies);
    result.append(" Length=");
    result.append(fLength);
    return result.toString();
  }


  // PRIVATE 
  private final String fSpecies;
  private int fLength;


  /**
  * Implements the class invariant.
  *
  * Perform all checks on the state of the object.
  * One may assert that this method returns true at the end
  * of every public method.
  */
  private boolean hasValidState(){
    return isValidSpecies(fSpecies) && isValidLength(fLength);
  }


  /** Species must have content.  */
  private boolean isValidSpecies(final String aSpecies) {
    return aSpecies != null && aSpecies.trim().length()>0;
  }


  /** Length must be greater than 0.  */
  private boolean isValidLength(final int aLength) {
    return aLength > 0;
  }


  /** Length increase depends on current length. */
  private int getLengthIncrease(int aOriginalLength) {
    // 由于这是一个私有方法,这里用assert来检验参数的合法性
    assert aOriginalLength > 0: this;
    int result = 0;
    if (aOriginalLength > 10) {
      result = 2;
    }
    else {
      result = 1;
    }
    assert result > 0 : result;
    return result;
  }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值