¡Hola! En la lección de hoy, hablaremos sobre las excepciones de Java. La vida cotidiana está llena de situaciones que no anticipamos. Por ejemplo, te levantas por la mañana para ir a trabajar y buscas el cargador de tu teléfono, pero no lo encuentras por ninguna parte. Vas al baño a ducharte y descubres que las tuberías están congeladas. Te subes a tu coche, pero no arranca. Un ser humano es capaz de hacer frente a tales circunstancias imprevistas con bastante facilidad. En este artículo, intentaremos descubrir cómo los programas Java los tratan.
La capacidad de prevenir y resolver situaciones excepcionales en un programa, permitiéndole continuar ejecutándose, es una razón para usar excepciones en Java. El mecanismo de excepción también le permite proteger su código (API) del uso indebido al validar (verificar) cualquier entrada. Ahora imagina que eres el departamento de transporte por un segundo. Primero, debe conocer los lugares donde los automovilistas pueden esperar problemas. En segundo lugar, debe crear e instalar señales de advertencia. Y, por último, debe proporcionar desvíos si surgen problemas en la ruta principal. En Java, el mecanismo de excepción funciona de manera similar. Durante el desarrollo, usamos un bloque de prueba para construir "barreras de excepción" alrededor de secciones peligrosas de código, proporcionamos "rutas de respaldo" usando un catch {}bloque, y escribimos código que debe ejecutarse sin importar qué en un bloque finalmente{} . Si no podemos proporcionar una "ruta de respaldo" o queremos dar al usuario el derecho a elegir, al menos debemos advertirle del peligro. ¿Por qué? ¡Imagínese la indignación de un conductor que, sin ver una sola señal de advertencia, llega a un pequeño puente que no puede cruzar! En programación, cuando escribimos nuestras clases y métodos, no siempre podemos prever cómo podrían ser utilizados por otros desarrolladores. Como resultado, no podemos prever la forma 100% correcta de resolver una situación excepcional. Dicho esto, es de buena educación advertir a los demás sobre la posibilidad de situaciones excepcionales. El mecanismo de excepción de Java nos permite hacer esto con los lanzamientospalabra clave — esencialmente una declaración de que el comportamiento general de nuestro método incluye lanzar una excepción. Por lo tanto, cualquiera que use el método sabe que debe escribir código para manejar las excepciones.
Cuando se lanza una excepción en un bloque de prueba , la JVM busca un controlador de excepciones apropiado en el siguiente bloque catch . Si un bloque catch tiene el controlador de excepciones requerido, el control pasa a él. De lo contrario, la JVM busca más abajo en la cadena de bloques catch hasta que se encuentra el controlador adecuado. Después de ejecutar un bloque catch , el control se transfiere al bloque finalmente opcional . Si una captura adecuadano se encuentra el bloque, JVM detiene el programa y muestra el seguimiento de la pila (la pila actual de llamadas a métodos), después de realizar primero el bloque finalmente , si existe. Ejemplo de manejo de excepciones:
¿Qué es una excepción de Java?
En el mundo de la programación, los errores e imprevistos en la ejecución de un programa se denominan excepciones. En un programa, pueden ocurrir excepciones debido a acciones de usuario no válidas, espacio en disco insuficiente o pérdida de la conexión de red con el servidor. Las excepciones también pueden resultar de errores de programación o uso incorrecto de una API. A diferencia de los humanos en el mundo real, un programa debe saber exactamente cómo manejar estas situaciones. Para ello, Java cuenta con un mecanismo conocido como manejo de excepciones.Algunas palabras sobre las palabras clave
El manejo de excepciones en Java se basa en el uso de las siguientes palabras clave en el programa:- try : define un bloque de código donde puede ocurrir una excepción;
- catch - define un bloque de código donde se manejan las excepciones;
- finalmente : define un bloque de código opcional que, si está presente, se ejecuta independientemente de los resultados del bloque de prueba.
- throw : se utiliza para generar una excepción;
- throws : se utiliza en la firma del método para advertir que el método puede generar una excepción.
// This method reads a string from the keyboard
public String input() throws MyException { // Use throws to warn
// that the method may throw a MyException
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
String s = null;
// We use a try block to wrap code that might create an exception. In this case,
// the compiler tells us that the readLine() method in the
// BufferedReader class might throw an I/O exception
try {
s = reader.readLine();
// We use a catch block to wrap the code that handles an IOException
} catch (IOException e) {
System.out.println(e.getMessage());
// We close the read stream in the finally block
} finally {
// An exception might occur when we close the stream if, for example, the stream was not open, so we wrap the code in a try block
try {
reader.close();
// Handle exceptions when closing the read stream
} catch (IOException e) {
System.out.println(e.getMessage());
}
}
if (s.equals("")) {
// We've decided that an empty string will prevent our program from working properly. For example, we use the result of this method to call the substring(1, 2) method. Accordingly, we have to interrupt the program by using throw to generate our own MyException exception type.
throw new MyException("The string cannot be empty!");
}
return s;
}
¿Por qué necesitamos excepciones?
Veamos un ejemplo del mundo real. Imagine que una sección de una carretera tiene un pequeño puente con capacidad de peso limitada. Si un automóvil más pesado que el límite del puente lo pasa por encima, podría derrumbarse. La situación del conductor se convertiría, por decirlo suavemente, en excepcional. Para evitar esto, el departamento de transporte instala señales de advertencia en la carretera antes de que algo salga mal. Al ver la señal de advertencia, un conductor compara el peso de su vehículo con el peso máximo para el puente. Si el vehículo es demasiado pesado, el conductor toma una ruta de desvío. El departamento de transporte, primero, hizo posible que los camioneros cambiaran su ruta si fuera necesario, segundo, advirtió a los conductores sobre los peligros en la carretera principal y tercero, advirtió a los conductores que el puente no debe usarse bajo ciertas condiciones.
Advertencia a otros sobre "problemas"
Si no planea manejar excepciones en su método, pero quiere advertir a otros que pueden ocurrir excepciones, use la palabra clave throws . Esta palabra clave en la firma del método significa que, bajo ciertas condiciones, el método puede generar una excepción. Esta advertencia es parte de la interfaz del método y permite a los usuarios implementar su propia lógica de manejo de excepciones. Después de los lanzamientos, especificamos los tipos de excepciones lanzadas. Estos generalmente descienden de la clase Exception de Java . Dado que Java es un lenguaje orientado a objetos, todas las excepciones son objetos en Java.
Jerarquía de excepciones
Cuando ocurre un error mientras se ejecuta un programa, la JVM crea un objeto del tipo apropiado de la jerarquía de excepciones de Java, un conjunto de posibles excepciones que descienden de un ancestro común, la clase Throwable . Podemos dividir las situaciones excepcionales de tiempo de ejecución en dos grupos:- Situaciones de las que el programa no puede recuperarse y continuar su funcionamiento normal.
- Situaciones en las que la recuperación es posible.
Crear una excepción
Cuando se ejecuta un programa, las excepciones son generadas por la JVM o manualmente usando una declaración de lanzamiento . Cuando esto sucede, se crea un objeto de excepción en la memoria, el flujo principal del programa se interrumpe y el controlador de excepciones de JVM intenta manejar la excepción.Manejo de excepciones
En Java, creamos bloques de código en los que anticipamos la necesidad de manejar excepciones usando las construcciones try{}catch , try{}catch{}finally e try{}finally{} .
public class Print {
void print(String s) {
if (s == null) {
throw new NullPointerException("Exception: s is null!");
}
System.out.println("Inside print method: " + s);
}
public static void main(String[] args) {
Print print = new Print();
List list= Arrays.asList("first step", null, "second step");
for (String s : list) {
try {
print.print(s);
}
catch (NullPointerException e) {
System.out.println(e.getMessage());
System.out.println("Exception handled. The program will continue");
}
finally {
System.out.println("Inside finally block");
}
System.out.println("The program is running...");
System.out.println("-----------------");
}
}
}
Estos son los resultados del método principal :
Inside print method: first step
Inside finally block
The program is running...
-----------------
Exception: s is null!
Exception handled. The program will continue
Inside finally block
The program is running...
-----------------
Inside print method: second step
Inside finally block
The program is running...
-----------------
El finalmente se usa típicamente para cerrar cualquier flujo y liberar cualquier recurso abierto/asignado en un bloque de prueba . Sin embargo, al escribir un programa, no siempre es posible realizar un seguimiento del cierre de todos los recursos. Para facilitarnos la vida, los desarrolladores de Java ofrecen la construcción try-with-resources , que cierra automáticamente cualquier recurso abierto en un bloque de prueba . Nuestro primer ejemplo se puede reescribir con try-with-resources :
public String input() throws MyException {
String s = null;
try (BufferedReader reader = new BufferedReader(new InputStreamReader(System.in))){
s = reader.readLine();
} catch (IOException e) {
System.out.println(e.getMessage());
}
if (s.equals("")) {
throw new MyException ("The string cannot be empty!");
}
return s;
}
Gracias a las capacidades de Java introducidas en la versión 7, también podemos combinar la captura de excepciones heterogéneas en un bloque, lo que hace que el código sea más compacto y legible. Ejemplo:
public String input() {
String s = null;
try (BufferedReader reader = new BufferedReader(new InputStreamReader(System.in))) {
s = reader.readLine();
if (s.equals("")) {
throw new MyException("The string cannot be empty!");
}
} catch (IOException | MyException e) {
System.out.println(e.getMessage());
}
return s;
}
GO TO FULL VERSION