Es difícil hacer que un programa sea perfecto e inevitablemente habrá varias anomalías. Por ejemplo, hay un error en el programa en sí, como que la impresora se queda sin papel cuando el programa imprime o no hay suficiente memoria. Para resolver estas excepciones, necesitamos saber por qué ocurrió la excepción. Para algunas excepciones comunes, también podemos proporcionar ciertos planes de respuesta. El manejo de excepciones en lenguaje C se implementa simplemente a través de valores de retorno de funciones, pero el significado del valor de retorno a menudo está determinado por convención. Los programadores necesitan consultar una gran cantidad de información antes de poder encontrar una razón vaga. Los lenguajes orientados a objetos, como C++, Java y Python, suelen tener mecanismos de manejo de excepciones más complejos. El mecanismo de manejo de excepciones en Java se analiza aquí.
Manejo de excepciones de Java
Manejo de excepciones
Una gran parte del mecanismo de manejo de excepciones de Java proviene de C++. Permite a los programadores omitir problemas que no se pueden manejar temporalmente para continuar con el desarrollo posterior, o permitir que el programa maneje excepciones de manera más inteligente.
Java utiliza algunos objetos especiales para representar condiciones anormales, dichos objetos se denominan objetos de excepción. Cuando ocurre una excepción, Java generará un objeto que representa la situación actual según la configuración preestablecida. El llamado lanzamiento es una forma especial de devolución. El hilo se detendrá y saldrá de las llamadas a métodos capa por capa hasta que encuentre un controlador de excepciones. El controlador de excepciones puede detectar el objeto de excepción y decidir la siguiente acción en función del objeto, como por ejemplo:
Recuerde al usuario que maneje las excepciones y continúe el programa para salir del programa.
...
El controlador de excepciones se ve así, consta de try, catch, finalmente y los siguientes bloques. finalmente no es necesario.
prueba { ...;}catch() { ...;}catch() { ...;}finalmente { ...;}
Este controlador de excepciones monitorea el bloque del programa después del intento. Los paréntesis de captura tienen un parámetro que representa el tipo de excepción que se va a capturar. catch capturará el tipo correspondiente y sus clases derivadas. El bloque de programa después del intento contiene las operaciones que se realizarán para el tipo de excepción. El bloque de programa monitoreado por try puede generar más de un tipo de excepción, por lo que un controlador de excepciones puede tener múltiples módulos catch. El bloque de programa después de finalmente es un programa que debe ejecutarse independientemente de si ocurre o no una excepción.
Ponemos a prueba programas que pueden salir mal y necesitan ser monitoreados, y diseñamos soluciones para lidiar con excepciones en la captura.
El siguiente es un programa Java parcial que utiliza manejo de excepciones. La parte de prueba del programa lee líneas de texto de un archivo. Durante el proceso de lectura del archivo, puede ocurrir una IOException:
BufferedReader br = new BufferedReader(new FileReader("file.txt")); prueba { StringBuilder sb = new StringBuilder(); String line = br.readLine() while (line!= null) { sb.append(line) ; sb.append("/n"); línea = br.readLine() } Cadena todo = sb.toString();} catch(IOException e) { e.printStackTrace(); System.out.println("problema IO");}finalmente { br.close();}
Si capturamos el objeto de clase IOException e, podemos operar sobre el objeto. Por ejemplo, llame a printStackTrace() del objeto para imprimir el estado actual de la pila. Además, también imprimimos el mensaje "Problema IO" en el rango medio.
Independientemente de si hay una excepción o no, el programa eventualmente ingresará al bloque finalmente. Cerramos el archivo en el bloque finalmente y limpiamos los recursos que ocupa el descriptor del archivo.
tipo de excepción
Todas las clases de excepción en Java heredan de la clase Trowable. Se puede lanzar (lanzar) un objeto de la clase Throwable.
Naranja: sin marcar; azul: marcado
Los objetos arrojables se pueden dividir en dos grupos. Un grupo son excepciones no controladas. Los mecanismos de manejo de excepciones a menudo no se utilizan para este grupo de excepciones, que incluyen:
1. La clase Error generalmente se refiere a errores internos de Java y errores como el agotamiento de recursos. Cuando ocurre un Error (y sus derivados), no podemos solucionar el Error a nivel de programación, por lo que debemos salir del programa directamente.
2. La clase Exception tiene una clase derivada especial RuntimeException. RuntimeException (y sus derivados) son causados por el propio programa Java, es decir, debido a que el programador comete errores durante la programación. RuntimeException se puede evitar por completo modificando el programa Java. Por ejemplo, convertir un objeto de un tipo en otro tipo sin relación de herencia es una ClassCastException. Estas anomalías deberían y pueden evitarse.
El resto son excepciones marcadas. Estas clases son causadas por interacciones de programación con el entorno que provocan errores en el programa en tiempo de ejecución. Por ejemplo, al leer un archivo, se produce una IOException debido a un error en el propio archivo. Otro ejemplo es que el servidor de red cambia temporalmente la dirección URL, lo que provoca MalformedURLException. El sistema de archivos y el servidor de red están fuera del entorno Java y no están bajo el control del programador. Si los programadores pueden anticipar excepciones, pueden utilizar el mecanismo de manejo de excepciones para desarrollar planes de respuesta. Por ejemplo, cuando hay un problema con un archivo, se alerta al administrador del sistema. Otro ejemplo es cuando hay un problema con el servidor de red, se recuerda al usuario y espera a que el servidor de red se recupere. El mecanismo de manejo de excepciones se utiliza principalmente para manejar dichas excepciones.
lanzar una excepción
En el programa anterior, la excepción proviene de nuestra llamada a la API Java IO. También podemos lanzar excepciones en nuestros propios programas, como la siguiente clase de batería, que tiene métodos de carga y uso:
prueba de clase pública{ public static void main(String[] args) { Batería aBattery = new Battery(); aBattery.chargeBattery(0.5); aBattery.useBattery(-0.5); class Batería { /** * aumentar batería * / public void chargeBattery(double p) { // potencia <= 1 if (this.power + p < 1.) { this.power = this.power + p; else { this.power = 1.; } } /** * consume batería */ public boolean useBattery(double p) { try { test(p); out.println("catch Exception"); System.out.println(e.getMessage()); p = 0.0; - p; return true; } else { this.power = 0.0; return false } } /** * uso de prueba */ private void test(double p) lanza una excepción // Simplemente tiro, no manejo { if ( p < 0) { Excepción e = nueva Excepción ("p debe ser positiva"); throw e; } } potencia doble privada = 0.0;
useBattery() indica que se utiliza el funcionamiento con batería. Hay un parámetro en el método useBattery() que indica la cantidad de electricidad utilizada. Usamos el método test() para probar este parámetro. Si este parámetro es negativo, entonces pensamos que hay una excepción y la lanzamos.
En la prueba, cuando ocurre una excepción (p <0), creamos un objeto de excepción e y usamos una cadena como parámetro. La cadena contiene información relacionada con la excepción y este parámetro no es necesario. Utilice throw para lanzar el objeto de excepción.
Tenemos un controlador de excepciones en useBattery(). Dado que el método test () no maneja directamente la excepción que genera, sino que arroja la excepción al useBattery () superior, debemos explicar los lanzamientos de excepción en la definición de test ().
(Suponiendo que el controlador de excepciones no está ubicado en useBattery(), sino en el método main() de nivel superior, también necesitamos agregar throws Exception a la definición de useBattery().)
En catch, utilizamos el método getMessage() para extraer la información contenida en su excepción. Los resultados de ejecutar el programa anterior son los siguientes:
catch Exceptionp debe ser positivo
En el controlador de excepciones, detectaremos cualquier excepción de la clase Exception o sus derivados. Esto a menudo no nos ayuda a identificar problemas, especialmente cuando un programa puede generar múltiples excepciones. Podemos proporcionar una clase más específica para capturar.
Excepción personalizada
Podemos crear nuevas clases de excepción mediante herencia. Al heredar, a menudo necesitamos anular el constructor. Las excepciones tienen dos constructores, uno sin parámetros y otro con un parámetro String. Por ejemplo:
clase BatteryUsageException extiende Exception{ public BatteryUsageException() {} public BatteryUsageException(String msg) { super(msg }}
Podemos proporcionar más métodos e información relacionados con excepciones en clases derivadas.
Al personalizar las excepciones, tenga cuidado con la clase base de la que hereda. Una clase más específica debería contener más información de excepción, como IOException versus Exception.
Resumir
El manejo de excepciones resuelve problemas, pero también crea problemas. En proyectos grandes, el manejo excesivo y detallado de excepciones a menudo hace que el programa se convierta en un desastre. El manejo de excepciones no es simple por diseño y debe usarse con precaución.