Validate method arguments

The first lines of a method are usually devoted to checking the validity of method arguments. The idea is to fail as quickly as possible in the event of an error. This is particularly important for constructors.

It's a reasonable policy for a class to skip validating arguments of private methods. The reason is that private methods can only be called from the class itself. Thus, a class author should be able to confirm that all calls of a private method are valid. If desired, the assert keyword can be used to verify private method arguments, to check the internal consistency of the class. (Using assert for checking the arguments of a non-private method is not recommended, since disabling such assertions would mean the contract of the non-private method is no longer being enforced.)

When validating an argument, an Exception is thrown if the test fails. It's often one of these unchecked exceptions that are thrown:

These are all subclasses of RuntimeException.

Checked exceptions can also be thrown, as shown in the Model Object validation topic. Many programmers document these exceptions in the @throws clause of the method's javadoc, since they clearly state the method's requirements to the caller (the pre-conditions). Others, however, feel that manually documenting exceptions should be avoided.

If every object parameter of every method in a class needs to be non-null in order to avoid throwing NullPointerException, then it's acceptable to state this once in the general class javadoc, instead of repeating it for each method. Another alternative is to state in overview.html (javadoc's summary description of an entire application) that all parameters are to be considered non-null unless explicitly stated otherwise.

Example 1

The constructor of this class validates its arguments before doing anything else. If a validation fails, then an IllegalArgumentException is thrown.


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));
  }
} 


Example 2

Some validations are very common:

Providing a class for such validations can often be useful. In this example, the Args class throws IllegalArgumentException if a corresponding boolean check fails. Using Args to validate arguments will increase legibility noticeably, especially in the case of multiple validations.

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
  }
}
 



See Also :
Validate state with class invariants
Javadoc all exceptions
Assert is for private arguments only
Avoid @throws in javadoc
Model Objects
Would you use this technique?
Yes   No   Undecided   
© 2014 Hirondelle Systems | Source Code | Contact | License | RSS
Individual code snippets can be used under this BSD license - Last updated on September 21, 2013.
Over 2,000,000 unique IPs last year - Built with WEB4J.
- In Memoriam : Bill Dirani -