Is it good practice to use Exception to prevent class from being instantiated with unwanted parameter

Viewed 47

I'm new to Java. I wrote a class called QueryCondition which is used to represent query conditions in a SQL command, such as id > 5, bankBalance < 100, etc. Obviously, a query condition like this needs to have both of the operands, so in the constructor of QueryCondition I check for empty or null operands and throw an exception if such is the case. Is this good practice?

public class QueryCondition
{
  public enum Comparator
  {
    smallerThan,
    smallerThanOrEqualTo,
    largerThan,
    largerThanOrEqualTo,
    equals,
    doesNotEqual
  }

  private final String _leftOp;
  private final String _rightOp;
  private final Comparator _comp;
  public QueryCondition( String leftOperand, Comparator compare, String rightOperand ) throws Exception
  {
    if( leftOperand == null || leftOperand.isEmpty() ||
        rightOperand == null || rightOperand.isEmpty() )
    {
      throw new Exception("QueryCondition cannot be constructed with empty operands.");
    }
    
    _leftOp = leftOperand;
    _rightOp = rightOperand;
    _comp = compare;
  }
  
}
2 Answers

Yes, such precondition checks are absolutely recommended in a constructor. It is the responsibility of the constructor to establish the invariants of your class. As a constructor does not have any other way to signal failure than throwing an exception, this is the only (and correct) thing to do in most cases.

Which type of Exception to throw is up to you, but the currently most idiomatic way is NullPointerException in case of null arguments and IllegalArgumentException in case of other illegal values.

There is even some support built into the standard library: Objects.requireNonNull allows you to write the null checks as

public QueryCondition( String leftOperand, Comparator compare, String rightOperand )
{
    _leftOp = Objects.requireNonNull(leftOperand, "left operand null");
    _rightOp = Objects.requireNonNull(rightOperand, "right operand null");
    _comp = Objects.requireNonNull(compare, "compare null");
}

This does not check for emptiness, though. It throws a NullPointerException with the message given as the second parameter if the first parameter is null.

Some libraries offer additional utility functions for such checks (e.g. apache commons StringUtils)

It depends on how these objects are to be constructed. Many of these protective habits are from the days of C/C++ when a bad argument could trigger a confusing memory dump. With a VM, the failure reporting is usually clearer.

In your case, I wouldn't check the string, but would assign Comparator values (which I presume is what you really want), so that the object really is created correctly. If there's to be a conversion from Strings, I usually add a static factory method that separates out all the error checking, leaving a minimal constructor.

One more thing, you don't need the leading underbars in Java. That's another habit left over from brittle languages and ascii terminals.

Related