Java参数检查

Validate method arguments


方法的第一行往往都是检查参数的合法性,其理念就是越早失败越好,这对于构造函数尤其重要。


对于private的方法, 跳过参数合法行检查策略是一个合理的策略, 因为private的方法只有被类自身调用,类作者应该能够保证调用private方法时参数的有效性。
如果有必要,可在private方法中可以用assert这个关键字来检查参数,用来保证类内一致性。(不推荐用assert来检查非private方法,
因为禁止assertion意味着在非private方法里的检查不再是强制的)


当检查一个参数时,如果检查失败(不符合要求),会抛出异常。 一般是下面几种unchecked exceptions:
 IllegalArgumentException
 NullPointerException
 IllegalStateException


他们都是RuntimeException的子类.


Checked exceptions也可以抛出,可以参考 Model Object validation里面的主题. 许多程序员会在方法里对应的javadoc @throws里标明这些异常,
这样就对调用者明确的声明了方法的要求(或前提). 否则, 手工标注的这些异常应该避免。


如果每一个方法中的每一个参数对象都必须不为null以避免NullPointerException,那么在类的javadoc说明一下而不是在每一个方法中说明是可以接受的。
另一种方法是在overview.html中说明,所有的参数必须不为null,除非显式的说明.


例1
本类的构造函数先检查所有的参数,然后才做其他的事,如果检查失败,则抛出IllegalArgumentException.


public final class ElementaryParticle {


  /**
   @param aName has content.
   @param aSpeed is in the range 0 (inclusive) to 1 (inclusive), and
   is expressed as a fraction of the speed of light. (The photon is
   an example of an elementary particle which travels at this speed.)
   @exception IllegalArgumentException if a param does not comply.
  */
  public ElementaryParticle (String aName, double aSpeed) {
    if (!textHasContent(aName)) {
      throw new IllegalArgumentException("Name has no content.");
    }
    if (aSpeed < 0.0 || aSpeed > 1.0) {
      throw new IllegalArgumentException("Speed not in range [0..1]: " + aSpeed);
    }
    fName = aName;
    fSpeed = aSpeed;
  }


  //..other methods elided


  // PRIVATE
  private String fName;
  private double fSpeed;


  /**
   Returns true if aText is non-null and has visible content.
  
   This is a test which is often performed, and should probably
   be placed in a general utility class.
  */
  private boolean textHasContent(String aText){
    String EMPTY_STRING = "";
    return (aText != null) && (!aText.trim().equals(EMPTY_STRING));
  }



例2
一些检查是非常常见的:
检查一些对象是否为null
检查文本是否含有可见内容
检查一个数字是否在指定的范围


提供一个类来做这些检查是十分有用的。在本例中, 如果一个对应的bool检查失败,Args类会抛出IllegalArgumentException. 用Args类来检查参数会
提高可读性,尤其在有很多检查的时候.


package hirondelle.web4j.util;


import java.util.regex.*;


/**
 Utility methods for common argument validations.


<P>Replaces <tt>if</tt> statements at the start of a method with 
 more compact method calls.
 
 <P>Example use case.
 <P>Instead of :
 <PRE>
 public void doThis(String aText){
   if (!Util.textHasContent(aText)){
     throw new IllegalArgumentException();
   }
   //..main body elided
 }
 </PRE>
 <P>One may instead write :
 <PRE>
 public void doThis(String aText){
   Args.checkForContent(aText);
   //..main body elided
 }
 </PRE>
*/
public final class Args {
  
  /**
   If <code>aText</code> does not satisfy {@link Util#textHasContent}, then 
   throw an <code>IllegalArgumentException</code>.
  
   <P>Most text used in an application is meaningful only if it has visible content.
  */
  public static void checkForContent(String aText){
    if( ! Util.textHasContent(aText) ){
      throw new IllegalArgumentException("Text has no visible content");
    }
  }


  /**
   If {@link Util#isInRange} returns <code>false</code>, then 
   throw an <code>IllegalArgumentException</code>. 
  
   @param aLow is less than or equal to <code>aHigh</code>.
  */
  public static void checkForRange(int aNumber, int aLow, int aHigh) {
    if ( ! Util.isInRange(aNumber, aLow, aHigh) ) {
      throw new IllegalArgumentException(aNumber + " not in range " + aLow + ".." + aHigh);
    }
  }


  /**
   If <tt>aNumber</tt> is less than <tt>1</tt>, then throw an 
   <tt>IllegalArgumentException</tt>.
  */
  public static void checkForPositive(int aNumber) {
    if (aNumber < 1) {
      throw new IllegalArgumentException(aNumber + " is less than 1");
    }
  }


  /**
   If {@link Util#matches} returns <tt>false</tt>, then 
   throw an <code>IllegalArgumentException</code>. 
  */
  public static void checkForMatch(Pattern aPattern, String aText){
    if (! Util.matches(aPattern, aText)){
      throw new IllegalArgumentException(
        "Text " + Util.quote(aText) + " does not match '" +aPattern.pattern()+ "'"
      );
    }
  }
  
  /**
   If <code>aObject</code> is null, then throw a <code>NullPointerException</code>.
  
   <P>Use cases :
  <pre>
   doSomething( Football aBall ){
     //1. call some method on the argument : 
     //if aBall is null, then exception is automatically thrown, so 
     //there is no need for an explicit check for null.
     aBall.inflate();
    
     //2. assign to a corresponding field (common in constructors): 
     //if aBall is null, no exception is immediately thrown, so 
     //an explicit check for null may be useful here
     Args.checkForNull( aBall );
     fBall = aBall;
     
     //3. pass on to some other method as parameter : 
     //it may or may not be appropriate to have an explicit check 
     //for null here, according the needs of the problem
     Args.checkForNull( aBall ); //??
     fReferee.verify( aBall );
   }
   </pre>
  */
  public static void checkForNull(Object aObject) {
    if (aObject == null) {
      throw new NullPointerException();
    }
  }
  
  // PRIVATE 
  private Args(){
    //empty - prevent construction
  }
}











































  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值