Validación de datos
Introducción
Una vez vistas las excepciones surge la necesidad de poder validar y comprobar la información que recogemos, ya sea desde teclado, web etc…
Validar si un caracter tiene letra
Con el método estático de Character isAlphabetic() que devuelve boolean:
public class StudyTonight
{
public static void main(String[] args)
{
int cp1 = 56;
int cp2 = 88;
boolean b1 = Character.isAlphabetic(cp1);
boolean b2 = Character.isAlphabetic(cp2);
System.out.println((char) cp1 + " is alphabet? " + b1);
System.out.println((char) cp2 + " is alphabet? " + b2);
}
}
Character tiene más métodos interesantes como: isDigit() isDefined() etc…
isEmpty()
Este método comprueba sólo la longitud de la cadena, y devuelve boolean true si es 0.
isBlank()
Método que nos sirve para comprobar si el String está vacio o con espacios vacios (devolvería true):
System.out.println("ABC".isBlank()); //false
System.out.println(" ABC ".isBlank()); //false
System.out.println(" ".isBlank()); //true
System.out.println("".isBlank()); //true
Uso de NumberFormatException
Una de las formas de comprobar si un String tiene un número es con los siguientes métodos de Wrappers:
- Integer.parseInt()
- Integer.valueOf()
- Double.parseDouble()
- Float.parseFloat()
- Long.parseLong()
Estos métodos generarán la excepción NumberFormatException si no se puede parsear a número. Método que comprueba lo anterior:
public static boolean isNumeric(String string) {
int intValue;
System.out.println(String.format("Parsing string: \"%s\"", string));
if(string == null || string.equals("")) {
System.out.println("String cannot be parsed, it is null or empty.");
return false;
}
try {
intValue = Integer.parseInt(string);
return true;
} catch (NumberFormatException e) {
System.out.println("Input String cannot be parsed to Integer.");
}
return false;
}
Uso de InputMismatchException
Ejemplo de validación de datos con excepciones:
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int [] array = {4,2,6,7};
int n;
boolean repetir = false;
do{
try{
repetir = false;
System.out.print("Introduce un número entero > 0 y < " + array.length + " ");
n = sc.nextInt();
System.out.println("Valor en la posición " + n + ": " + array[n]);
}catch(InputMismatchException e){
sc.nextLine();
n = 0;
System.out.println("Debe introducir un número entero ");
repetir = true;
}catch(IndexOutOfBoundsException e){
System.out.println("Debe introducir un número entero > 0 y < " + array.length + " ");
repetir = true;
}catch(Exception e){ //resto de excepciones de tipo Exception y derivadas
System.out.println("Error inesperado " + e.toString());
repetir = true;
}
}while(repetir);
}
Comprobar objetos nulos
Ya estáis acostumbrados a usar “==” o “!=” con null para comprobar si una variable de un objeto referencia o no un objeto. En versiones recientes de Java también tenéis Objects.nonNull:
List<String> lista= new ArrayList<String>();
lista.add("juan");
lista.add("ana");
lista.add("gema");
lista.add(null);
lista.add("blanca");
lista.add(null);
lista.add("david");
for (String p:lista) {
if (Objects.nonNull(p)) {
System.out.println(p);
}
}
Expresiones regulares
¿Qué son las expresiones regulares? –> Es una formula o conjunto de caracteres que nos serviran para definir o validar un String. Es decir la expresión regular la construiremos indicando que Strings aceptamos.
Las más utilizadas:
- ^ Indica el principio de una cadena
- $ Indica el final de una cadena
- () Un agrupamiento de parte de una expresión
- [] Un conjunto de caracteres de la expresión
- {} Indica un número o intervalo de longitud de la expresión
- . Cualquier caracter salvo el salto de línea
- ? 0-1 ocurrencias de la expresión
- “+” 1-n ocurrencias de la expresión
- “*” 0-n ocurrencias de la expresión
- \ Para escribir un caracter especial como los anteriores y que sea tratado como un literal
- | Para indicar una disyunción lógica (para elegir entre dos valores: a|b se tiene que cumplir al menos uno de los dos)
Portal web de prueba –> https://regex101.com/
Método matches() de String
Es la forma más sencilla de usar expresiones regulares con Java, devuelve booleano (verdadero si la expresión regular encaja con el String). Hay que tener cuidado con , ya que tanto para Java como para la expresiones regulares tiene un significado por tanto hay que “escaparlo” “\”:
String str = new String("Welcome to Tutorialspoint.com");
System.out.print("Return Value :" );
System.out.println(str.matches("(.*)Tutorials(.*)"));
System.out.print("Return Value :" );
System.out.println(str.matches("Tutorials"));
System.out.print("Return Value :" );
System.out.println(str.matches("Welcome(.*)"));
Otra forma de usar este método pero de manera estática es con la clase Pattern:
System.out.println(Pattern.matches("-?\\d+","1234"));
Pero lo más frecuente y con más posibilidades es usar la clase Pattern para crear el patrón de la expresión regular con el método compile() que genera el objeto. Este objeto tiene el método matcher() para ir obteniendo los tokens que encage con la expresión regular:
Pattern pat;
Matcher mat;
pat = Pattern.compile("-?\\d+");
mat=pat.matcher("-1234");
System.out.println(mat.matches());
Método split() de Pattern
Este método lo podemos usar para recoger los tokens que encagen en una expresión regular:
Pattern p = Pattern.compile(" ");
String tmp = "this is a test";
String[] tokens = p.split(tmp);
for (int i = 0; i < tokens.length; i++) {
System.out.println(tokens[i]);
}
Hay muchas posibilidades podéis investigar por ejemplo el método find() de Matcher.
Ejercicio 1
Actualiza la clase DNI para que el constructor procese el String usando una expresión regular que de por bueno el siguiente formato: de 1 a 8 dígitos seguidos por una letra mayúscula o minúscula. Si el dni no es válido que se lance una excepción personalizada.
Ejercicio 2
Crea un validador de direcciones IP. Recuerda que las direcciones IP se especifican en decimal como 4 grupos de números separados por “.” Cada grupo puede contener un número decimal de 0 a 255. Por ejemplo son IP válidas:
- 0.1.2.3
- 255.255.255.255
- 9.234.1.199
Son inválidas:
- 0.1.2.
- 0.1.2.3.
- 256.1.2.3
Solución:
String trozoER="(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])";
String ERCompleta=trozoER+"\\."+trozoER+"\\."+trozoER+"\\."+trozoER;
/**
* la base de la ER es (25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9]), observa:
va entre paréntesis para que la opcionalidad de | sea dentro de lo que hay en los paréntesis
Cada parte de una dirección IP puede tener 1, 2 o 3 dígitos:
3 dígitos pueden ser números que:
empiezan por 25: 251,252,253,254 o 255. Lo que se resume con 25[0-5]
empiezan por 2 pero siendo algo menor que 250. Lo que se resume con 2[0-4][0-9]
empiezan por 1: 1[0-9][0-9]
2 digitos, : pero el primero de los números no puede ser cero [1-9][0-9]
1 digito [0-9]
* /