您的位置:首页 > 其它

assert使用场景

2015-06-02 14:30 561 查看
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;

  }

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: