1. Excepciones

>

Por fin, los programadores pensaron en estandarizar y automatizar el manejo de errores. Esto sucedió cuando se inventaron las excepciones . Ahora el mecanismo de excepción maneja el 80% de las situaciones excepcionales.

Si a algún erudito se le ocurrieron excepciones, probablemente fue el tema de su tesis doctoral. Si se le ocurrió a un programador, es posible que haya recibido una palmada amistosa en la espalda de un compañero de trabajo: "Parece bien, hermano".

Cuando se produce un error en un programa de Java, como la división por 0, suceden algunas cosas maravillosas:

Paso uno

Se crea un objeto de excepción especial, que contiene información sobre el error que ocurrió.

Todo en Java es un objeto, y las excepciones no son excepciones 🙂 Los objetos de excepción tienen sus propias clases, y lo único que los distingue de las clases ordinarias es que heredan la Throwableclase.

Segundo paso

El objeto de excepción es "lanzado". Quizás la redacción aquí podría ser mejor. "Lanzar una excepción" es más como activar una alarma de incendio o hacer sonar una alerta "DEFCON 1".

Cuando se lanza una excepción a la máquina Java, la operación normal del programa se detiene y comienzan los "protocolos de emergencia".

Paso tres

El método en el que se lanzó la excepción sale inmediatamente. La excepción se pasa al método de llamada, que también sale inmediatamente. Y así sucesivamente en la cadena hasta que el mainmétodo finalice. Cuando el mainmétodo termina, también lo hace el programa.

Ejemplo:

Código Salida de consola
class Solution
{
   public static void main(String[] args)
   {
      System.out.println("Your attention, please! Preparing for the end of the world");
      endTheWorld();
      System.out.println("The world ended successfully");
   }

   public static void endTheWorld()
   {
      System.out.println("We're doing something important");
      doSomeWork(0);
      System.out.println("Everything is working well");
   }

   public static void doSomeWork(int n)
   {
      System.out.println("Nothing terrible will happen: " + n);
      System.out.println(2 / n);
      System.out.println("Nothing terrible happened: " + n);
   }
}
Your attention, please! Preparing for the end of the world
We're doing something important
Nothing terrible will happen: 0

Se produce una excepción en la línea 20: división por 0. La máquina Java crea inmediatamente una excepción : un ArithmeticExceptionobjeto y lo "arroja" al método.

El divide()método finaliza inmediatamente, por lo que nunca vemos la cadena: No pasó nada terrible: 0. El programa vuelve al endTheWorld()método y la situación se repite: hay una excepción no controlada en el sistema, lo que significa que el endTheWorld()método también finaliza de manera anormal. Entonces el mainmétodo termina y el programa se detiene.

¿Cuál es el propósito de estas excepciones? Bueno, puede escribir su propio código para capturar tipos particulares de excepciones y escribir su propia lógica para manejar situaciones excepcionales.


2. Atrapar excepciones:try-catch

Java tiene un mecanismo de detección de excepciones que le permite detener esta terminación anormal de métodos. Se parece a esto:

try
{
   // Code where an exception might occur
}
catch(ExceptionType name)
{
   // Exception handling code
}

Esta construcción se llama try-catchbloque.

El código donde pueden ocurrir excepciones está entre llaves, precedido por la palabra try.

Después de las llaves, tenemos la catchpalabra clave y, entre paréntesis, la declaración de una variable de excepción . Esto va seguido de llaves que envuelven el código que se ejecutará si se produce una excepción del tipo especificado .

Si no se lanzan excepciones durante la ejecución del " código principal ", entonces el código dentro del bloque catch no se ejecutará. Si ocurre una excepción, lo será (si el tipo de la excepción lanzada es el mismo que el tipo de la variable entre paréntesis).

Ejemplo:

Código Salida de consola
class Solution
{
   public static void main(String[] args)
   {
      System.out.println("Hadron Collider launched");

      try
      {
         launchHadronCollider(1);
         launchHadronCollider(0);
      }
      catch(Exception e)
      {
         System.out.println("Error! Caught an exception");
         System.out.println("The planet was sucked into a black hole!");
      }

      System.out.println("The Hadron Collider stopped");
   }

   public static void launchHadronCollider(int n)
   {
      System.out.println("Everything is working well: " + n);
      System.out.println(2/n);
      System.out.println("There are no problems: " + n);
   }
}
Hadron Collider launched
Everything is working fine: 1
2
There are no problems: 1
Everything is working fine: 0
Error! Caught an exception
The planet has been sucked into a black hole!
The Hadron Collider is stopped


3. Múltiples catchbloques

Múltiples bloques de captura

En teoría, se pueden lanzar todo tipo de excepciones en un bloque de código. A algunos querrás manejarlos de una manera, a otros de otra manera y aún a otros decidirás no manejarlos en absoluto.

Los desarrolladores de Java decidieron ayudarlo y le permitieron escribir no uno sino muchos catchbloques después del trybloque.

try
{
   // Code where an exception might occur
}
catch (ExceptionType1 name1)
{
   // Code for handling ExceptionType1
}
catch (ExceptionType2 name2)
{
   // Code for handling ExceptionType2
}
   catch (ExceptionType3 name3)
{
   // Code for handling ExceptionType3
}

Ejemplo:

Código Salida de consola
class Solution
{
   public static void main(String[] args)
   {
      System.out.println("Start of main method");
      try
      {
         calculate(0);
      }
      catch (ArithmeticException e)
      {
         System.out.println("Division by 0");
      }
      catch(Exception e)
      {
         System.out.println("Caught some kind of exception");
      }

      System.out.println("End of main method");
   }

   public static void calculate(int n)
   {
      System.out.println("Start of calculate method: " + n);
      System.out.println(2/n);
      System.out.println("End of calculate method: " + n);
   }
}
Start of main method
Start of calculate method: 0
Division by 0
End of main method


4. Orden de catchbloques

Las excepciones que ocurren en un trybloque solo pueden ser capturadas por un solo catchbloque. No puede tener una situación de manejo de excepcionescatch en la que se ejecute el código de varios bloques.

Pero el orden de los bloques importa.

Puede tener una situación en la que varios bloques puedan capturar una excepción. Si ese es el caso, la excepción será capturada por el bloque catch que aparezca primero (el más cercano al trybloque).

¿Cómo puede tener una situación en la que varios bloques catch pueden detectar la misma excepción?

Todas las excepciones pertenecen a una única jerarquía de herencia; consulte el diagrama.

Jerarquía de excepciones

Un ArithmeticExceptionobjeto se puede asignar a una variable cuyo tipo es ArithmeticExceptiono cualquiera de sus clases antecesoras: RuntimeException , Exceptiony Throwable— ver el diagrama.

Hablaremos más sobre la herencia y las clases de ancestros en el Nivel 21.

Este código se compilará muy bien:

Beneficios de la herencia:
ArithmeticException ae    = new ArithmeticException();
RuntimeException runtime  = new ArithmeticException();
Exception exception       = new ArithmeticException();
Throwable trwbl           = new ArithmeticException();

Entonces puedes atrapar una ArithmeticExceptioncon cualquiera de los 4 catchbloques anteriores.

Ejemplo 1:

Código Salida de consola
class Solution
{
   public static void main(String[] args)
   {
      System.out.println("Start of main method");
      try
      {
         calculate(0);
      }
      catch(ArithmeticException e)
      {
         System.out.println("Division by 0");
      }
      catch(Exception e)
      {
         System.out.println("Caught some kind of exception");
      }

      System.out.println("End of main method");
   }

   public static void calculate(int n)
   {
      System.out.println("Start of calculate method: " + n);
      System.out.println(2/n);
      System.out.println("End of calculate method: " + n);
   }
}
Start of main method
Start of calculate method: 0
Division by 0
End of main method

En este ejemplo, el ArithmeticExceptionpuede ser capturado por los bloques catch (Exception e)y catch (ArithmeticException e). Será atrapado por el bloque más cercano al trybloque: el primer catchbloque.

Para evitar sorpresas, es mejor colocar catchbloques que puedan detectar casi todas las excepciones cerca del final de la lista de catchbloques.

El Throwabletipo es generalmente capaz de capturar todas las excepciones posibles en Java . Si lo coloca en el primer catchbloque, el código no se compilará, ya que el compilador sabe que hay bloques de código inalcanzables.