jueves, 30 de julio de 2009

Aserciones en Java.

   Saludos de nuevo, ¡compañeros!. El tema que se discutirá ahora son las aserciones que permiten evaluar si nuestra aplicación se encuentra en los valores asumidos y cumple con lo esperado.

   Existe la posibilidad que incurramos en un error lógico de programación y el programa no esté arrojando los resultados que que esperamos, en estos casos se puede agregar una sentencia Java que permite evaluar una condicion booleana y arrojar mensajes de error. Si, es a través de las aserciones.

   La sintaxis general es:

assert ExpresionBooleana [: Expresion_que_expresa_el_error];

   Puede verse que existe una expresión booleana que es obligatoria, y una expresión que es opcional, durante la ejecución del programa, se evalúa primero la expresión booleana de ser verdadera el programa continúa ejecutándose como sino hubiese pasado nada, sino (de ser falsa) el programa lanza una AssertionError y escribe además la Expresion_que_expresa_el_error si existe una, sino existe soló lanza la excepción mencionada. La Expresion_que_expresa_el_error puede ser cualquier tipo de cadena, mensaje o valor que quiere mostrar para saber lo que sucedió. Después de esto el programa detiene su ejecución.

   La aserciones están inhabilitadas por defecto, para habilitarlas debe escribir en línea para ejecutar:

> java -ea NombrePrograma

donde ea son las siglas de "ennable assertions"

   Por ejemplo supongamos que el programa que usted realiza debe mantener siempre valores positivos en la variable radio (radio de un circulo), puede que haya incurrido en un error y dentro del programa y el radio toma valores negativos. Si agregamos la sentencia:

assert radio >= 0:"Error. Variable radio tomo un valor negativo";

   Al ejecutar esta sentencia Java y además habilitar las aserciones el programa evalúa la condicición booleana (radio >= 0) si es verdadera el programa continúa su ejecución normalmente en caso contrario lanza una AssertionError, imprimiendo el mensaje: "Error. Variable radio tomo un valor negativo" además de indicar de imprimir la traza de la pista del error (línea donde se encontró la aserción negativa y demás).

   Para mayor información verifique en la Página de Java. Programando con Aserciones

lunes, 13 de julio de 2009

Expresiones Regulares. II Parte

    Ahora que ya conocemos los metacaracteres, sus significados y reglas, veamos ahora como podemos utilizarlo para hacer que nuestras cadenas de caracteres puedan coincidir con los patrones:

La Clase Pattern: (Patrón):


    En las expresiones regulares de java la clase Pattern tiene varios métodos que nos sirven para establecer el patrón y buscar coincidencias, veamos:Métodostatic Pattern compile(String regex)
    Permite compilar una expresión regular para uso posterior como un patrón. Si la expresión regular tiene un error el compilador no permite la compilación.
El error mas común es: “Invalid escape sequence”.
Ejemplo:


Pattern patron = Pattern.compile("\w*");


Este código lanza un error ya que se deben colocar una barra invertida adicional para que la expresión \w tome efecto de la siguiente manera:

Pattern patron = Pattern.compile("\\w*");

Ahora si nuestro patrón está compilado y listo para usarse en cualquier parte del código, en este caso coincidirá con cualquier palabra que use sólo letras y/o números.

Método
static boolean matches(String regex, CharSequence input)
Sirve para hacer coincidir una expresión regular con una entrada, es muy útil si sabemos que la expresión regular se utilizará una sola vez.
Ejemplo:

System.out.println(Pattern.matches("\\w*","cadena2")); //Consola muestra true


Método
Matcher matcher(CharSequence entrada)
Devuelve un matcher que permitirá posteriormente buscar coincidencias con el patrón.Ejemplo:

Pattern patron = Pattern.compile("\\s*palabra");
Matcher m = patron.matcher("\t\t palabra");
if(m.matches()){
    System.out.println("Patron coincide");
}else{
    System.out.println("Patron No coincide");
}//Imprime Patron coincide


Método
String pattern()
Devuelve la expresión regular (como una cadena de caracteres) compilada por el método compile.Ejemplo:

Pattern patron = Pattern.compile("\\s*palabra");
System.out.println(patron.pattern());
//Se imprime \s*palabra


Método
String[] split(CharSequence entrada)
String[] split(CharSequence entrada, int limite)

Devuelve un arreglo de cadenas que resulta al separar la cadena entrada con la expresion regular, omitiendo la expresion regular.Ejemplo:

Pattern patron = Pattern.compile("\\s*palabra");
String[] cadenas = patron.split("uno palabra dos");
for(String fragmento: cadenas){
    System.out.print(fragmento.trim()+" ");
}
//Imprime uno dos

  La variante con límite, tiene tres modalidades, si límite es un entero positivo se aplicará al menos el límite menos 1 veces; si es cero, se aplicara tantas veces como se pueda eliminándose las cadenas vacías y por último
si es negativo es igual a cero pero se dejan las cadenas vacías.




    A continuación un código que utiliza las expresiones regulares para mostrar todas las clases que se encuentran dentro de un archivo java siempre y cuando la clase no extienda de ninguna clase y no implemente interfaces. La clase se llama Buscadora y cuando se va a utilizar hay que pasar como parámetro el archivo de clase al que se le quiere encontrar todas sus clases. Por ejemplo:

java Buscadora ClaseDestino.java

Aqui el codigo:


import java.io.*;
import java.util.regex.*;
import javax.swing.JOptionPane;

public class Buscadora {
  public static void main(String[] args) {
    BufferedReader entrada = null;
    String texto = "";
    String[] cadenas = null;
    Matcher m = null;
    Pattern patronBusqueda = Pattern.compile("\\s*\\w*\\s*\\w*\\s*class\\s*\\w*\\s*\\W*");
    Pattern patronSplit = Pattern.compile("\\s*\\w*\\s*\\w*\\s*class");

    try {
      File archivo = new File(args[0]);
      FileReader fr = new FileReader(archivo);
      entrada = new BufferedReader(fr);
      System.out.println(args[0]);
      while((texto = entrada.readLine()) != null){
        m = patronBusqueda.matcher(texto);
        if(m.matches()){
          cadenas = patronSplit.split(texto,0);
          for(String cadena: cadenas){
            cadena = cadena.replace("{", " ");
            cadena = cadena.replace("}", " ");
            if(cadena.trim().length() == 0)
              continue;
            System.out.println("Nombre de la clase: "+cadena.trim());
          }
        }
      }
    } catch (ArrayIndexOutOfBoundsException e) {
      JOptionPane.showMessageDialog(null, "Debe especificar un archivo como paramentro");
    } catch (FileNotFoundException e) {
      JOptionPane.showMessageDialog(null, "Error. Archivo no encontrado");
    } catch (IOException e){
      JOptionPane.showMessageDialog(null, "Error al leer archivo");
    }
  }
}


    Como puede ver se utilizan dos patrones, uno para verificar que la línea que se compara coincida con una linea de declaración de una clase y el otro patrón para romper la cadena (split) y obtener así el nombre de la clase.

También es importante mencionar que el primer patrón (patronBusqueda) utiliza el metacaracter \W para hacerla coincidir con un caracter de no palabra, en este caso puede ser una llave "{" o "}". Otros utilizados son los caracteres de palabra \w y de espacio en blanco o tabulador \s.