Muchos métodos y constructores tienen ciertas restricciones en el valor que pueden tomar los parámetros. Por ejemplo, es común que el índice de un listado no pueda ser nulo o que la referencia a un objeto. Estas restricciones deben estar documentadas y se deben validar al iniciar el método. Esta es una forma de detectar errores antes de que ocurran. De no realizar esto, será más difícil determinar la fuente del error cuando esta ocurra.
Si un valor inválido es pasado a un método y este es validado antes de la ejecución, este fallara antes de la ejecución y se puede enviar una excepción adecuada. Si el método no valida estos parámetros, muchas cosas pueden ocurrir. El método puede fallar con una excepción un poco confusa de interpretar. Peor aún, el método puede retornar un valor, pero con un resultado equivocado. Lo peor de todo, el método puede devolver un valor correcto, pero dejar el estado de algunos objetos con valores incorrectos, causando un error en el código en un lugar no determinado a futuro.
Para métodos públicos, utilizar la etiqueta @throws de Javadoc para indicar las excepciones que serán lanzadas si alguno de los parámetros se ingresa en forma incorrecta. La excepción puede ser IllegalArgumentException, IndexOutOfBoundsException o NullPointerException. Cuando documente las restricciones para los parámetros de un método y documente las excepciones estas podrán ser lanzadas si una restricciones no se respeta, es una forma simple de reforzar las restricciones. A continuación un ejemplo:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | /** * Returns a BigInteger whose value is (this mod m). This method * differs from the remainder method in that it always returns a * non-negative BigInteger. * * @param m the modulus, which must be positive * @return this mod m * @throws ArithmeticException if m is less than or equal to 0 */ public BigInteger mod(BigInteger m) { if (m.signum() <= 0) throw new ArithmeticException("Modulus <= 0: " + m); ... // Do the computation } |
Para métodos privados, generalmente se utiliza sentencias con assert a fin de realizar las validaciones.
1 2 3 4 5 6 7 | // Private helper function for a recursive sort private static void sort(long a[], int offset, int length) { assert a != null; assert offset >= 0 && offset <= a.length; assert length >= 0 && length <= a.length - offset; ... // Do the computation } |
En esencia, las sentencias assert son responsables de validar si la sentencia es verdadero, sin tener en cuenta como se utiliza los métodos. A diferencia de otros controles, los assert lanzan AssertionError si estas fallan. Y a diferencia de los controles normales de validación, no tienen ningún efecto y, esencialmente, sin costo alguno a menos que estos sean habilitados con el parámetro –ea ( o –enableassertion) al interprete java.
El Constructor representa un caso especial donde se deben validar los valores que serán utilizados luego. Es crítico validar los parámetros de un constructor a fin de prevenir tener un objeto que no respete los valores que debe tener la clase.