JavaRush /Blog Java /Random-ES /Pausa para el café #220. Cómo solucionar excepciones en J...

Pausa para el café #220. Cómo solucionar excepciones en Java: una guía detallada

Publicado en el grupo Random-ES
Fuente: JavaTechOnline Este tutorial le ayudará a aprender cómo solucionar excepciones comunes en Java. Además de la teoría, verá ejemplos de código para solucionar este tipo de problemas. Pausa para el café #220.  Cómo solucionar excepciones en Java: una guía detallada - 1Al igual que con otros lenguajes de programación, los desarrolladores de Java pueden encontrar errores o excepciones al escribir código. Las excepciones deben tomarse en serio, ya que su aparición consume tiempo de trabajo. Sin embargo, con un poco de conocimiento, puedes acelerar la resolución de la mayoría de estos problemas. Entonces, aprendamos cómo solucionar excepciones comunes en Java.

Directrices generales para evitar excepciones en Java

Para evitar generar excepciones en Java, es importante comprender y seguir las pautas de codificación:
  1. Valide siempre la entrada del usuario antes de usarla en su código.
  2. Utilice try-catch , throws , throw blocks , dependiendo de lo que sea apropiado para un escenario particular.
  3. No descuides los mensajes en el código sobre procesamiento y errores. Esto ayudará a identificar y corregir problemas.
  4. Asegúrese de registrar excepciones para fines de depuración. Puede utilizar mensajes del registrador para ayudar a identificar problemas.
  5. Siga las mejores prácticas de codificación para evitar excepciones y pruebe su código minuciosamente.
  6. Actualice sus dependencias de API para asegurarse de que está utilizando las versiones más recientes y estables de bibliotecas y marcos.
  7. Utilice las herramientas y los marcos de prueba necesarios para identificar posibles problemas en su código antes de que generen excepciones.
  8. Supervise el rendimiento y los registros de su aplicación para identificar y resolver rápidamente cualquier problema.
  9. Manténgase actualizado con las mejores prácticas de seguridad para garantizar que su código esté seguro y protegido contra posibles ataques.
  10. Documente minuciosamente su código y sus excepciones para que sea más fácil de entender y mantener para otros desarrolladores.

Lista de las excepciones más comunes en Java

Java tiene una lista bastante larga de excepciones. Veamos algunos de los más comunes:

Excepción de puntero nulo

NullPointerException es un tipo de excepción RuntimeException . Ocurre cuando intentamos utilizar una variable de referencia que tiene un valor nulo. Esto significa que apunta a un objeto o variable cuyo valor es nulo . Un error de este tipo puede ocurrir cuando intentamos llamar a un método o acceder a un campo de un objeto que no ha sido inicializado, o cuando pasamos nulo como parámetro a un método que no lo maneja. Para evitar que se genere una excepción NullPointerException , puede verificar si una variable de referencia es nula usando el operador == . Si este es el caso, entonces el caso nulo debe manejarse correctamente. Alternativamente, podemos inicializar nuestras variables a los valores predeterminados (cuando sea posible) para asegurarnos de que nunca encontremos una referencia nula. Otra forma de evitar una NullPointerException es utilizar la clase Opcional . En Java, un Opcional es un objeto contenedor que puede contener o no un valor no nulo. Se utiliza para representar la presencia o ausencia de un valor, de forma similar a como se utiliza el valor nulo para representar la ausencia de un valor. Si un programador intenta acceder al valor vacío de un objeto Opcional , el programa no generará una NullPointerException sino que devolverá un objeto Opcional vacío . En otras palabras, Opcional obliga al programador a manejar el caso en el que falta el valor, lo que ayuda a evitar una NullPointerException .

Excepción IndexOutOfBounds

IndexOutOfBoundsException es una excepción de tiempo de ejecución que se produce cuando el índice utilizado para acceder a una matriz o colección es negativo o mayor o igual que el tamaño de la matriz o colección. Para evitar que ocurra esta excepción, debemos asegurarnos de que el índice utilizado para acceder al arreglo o colección esté dentro de sus límites, es decir, debe ser mayor o igual a cero y menor que el tamaño del arreglo o colección.

ArrayIndexOutOfBoundsExcepción

ArrayIndexOutOfBoundsException es un tipo de IndexOutOfBoundsException que se genera cuando se intenta acceder a una matriz en un índice no válido. En Java, los índices de una matriz comienzan en 0 y terminan en length()-1 , donde length() es el número de elementos de la matriz. Si intenta acceder a un elemento en un índice fuera de este rango, Java generará una ArrayIndexOutOfBoundsException . Cuando encuentre una ArrayIndexOutOfBoundsException , debe revisar su código para asegurarse de que está utilizando los índices correctos al acceder a los elementos de la matriz.

Excepción StringIndexOutOfBounds

StringIndexOutOfBoundsException es un tipo IndexOutOfBoundsException que se genera cuando se intenta acceder a un carácter en una cadena que tiene un índice no válido. Al igual que con la ArrayIndexOutOfBoundsException anterior , recuerde que en Java, el índice de una cadena comienza en 0 y termina en length()-1 , donde length() es el número de caracteres de la cadena. Si intenta acceder a un carácter en un índice fuera de este rango, puede encontrar una StringIndexOutOfBoundsException . Si encuentra una StringIndexOutOfBoundsException , debe revisar su código para asegurarse de que está utilizando los índices correctos al acceder a los caracteres de la cadena.

Excepción ClassCast

Esta excepción ocurre cuando intentamos convertir un objeto a un tipo que es incompatible con su tipo real. Para resolver un problema como este, es importante asegurarse de que su programa Java sólo intente convertir objetos a las clases de las que son instancias. Puede verificar el tipo de un objeto usando el operador instancia de antes de aplicar la conversión.

Argumento de excepción ilegal

IllegalArgumentException es un tipo de RuntimeException que se genera cuando se llama a un método con un argumento ilegal o inapropiado. En otras palabras, este error puede ocurrir cuando se llama a un método con un argumento que está fuera del rango esperado o no tiene el formato o estructura esperado. Por ejemplo, un método requiere un número positivo como argumento y proporcionamos un número negativo, lo cual no es una entrada válida. Si encuentra una IllegalArgumentException , debe verificar su código para asegurarse de que está llamando a métodos con argumentos válidos y apropiados.

Excepción de estado ilegal

IllegalStateException es un tipo de RuntimeException que se genera cuando un objeto se encuentra en un estado inadecuado para la operación que se está realizando. Esto puede suceder si se llama a un método en un objeto que no se encuentra en el estado esperado. Por ejemplo, si creamos un objeto de conexión a una base de datos y luego lo cerramos. Luego, si intentamos crear un objeto Statement en una conexión cerrada, generará una IllegalStateException porque el método createStatement() requiere una conexión abierta. Si encuentra una IllegalStateException , debe revisar su código para asegurarse de que está llamando a métodos en objetos que se encuentran en el estado apropiado.

Excepción de operación no admitida

UnsupportedOperationException es un tipo RuntimeException que se genera cuando se intenta realizar una operación no admitida en un objeto. Este error puede ocurrir cuando llamamos a un método que no está implementado por el objeto o que no es compatible con el objeto. Para evitar que se produzca una excepción, no debemos llamar a operaciones que no sean compatibles con objetos. Necesitamos revisar nuestro código para asegurarnos de que estamos llamando a métodos en objetos que admiten la operación.

Excepción aritmética

ArithmeticException es un tipo de RuntimeException que se genera cuando una operación aritmética produce un resultado no válido. Esta excepción puede ocurrir cuando intentamos realizar una operación aritmética con un argumento no válido o no válido. Por ejemplo, al intentar dividir por cero. Para resolver este problema, podemos realizar una validación de entrada y asegurarnos de que los argumentos cumplan con las condiciones requeridas antes de realizar la operación aritmética.

Excepcion de seguridad

SecurityException es un tipo de RuntimeException que se genera cuando se produce una infracción de seguridad durante la ejecución del programa. Este error puede ocurrir cuando un programa intenta realizar una operación que no está permitida por la política de seguridad. Para solucionar el problema, debemos asegurarnos de tener acceso a los recursos y realizar operaciones para las que tenemos permiso específico.

Excepción de formato de número

NumberFormatException es un tipo de RuntimeException que se genera cuando se llama a un método para convertir una cadena a un formato numérico, pero la cadena no tiene el formato apropiado. Para resolver este problema, primero debemos validar la entrada del usuario antes de intentar convertirla. También verifique su código para asegurarse de que está intentando convertir cadenas con el formato adecuado para el tipo numérico de destino.

Excepción interrumpida

InterruptedException es una excepción marcada que se genera si un subproceso está esperando, inactivo o bloqueando algún evento y ese evento es interrumpido por otro subproceso. El error puede ocurrir cuando un subproceso está esperando una entrada, liberando un bloqueo o completando alguna otra operación, y otro subproceso interrumpe el subproceso en espera. Para resolver este problema, puede detectar InterruptedException y responder limpiando recursos, deteniendo el hilo o tomando otras medidas apropiadas. Si encuentra una InterruptedException , debe verificar su código para asegurarse de que está manejando las interrupciones de subprocesos correctamente.

Excepción de archivo no encontrado

FileNotFoundException es una excepción marcada que se produce cuando un programa intenta acceder a un archivo que no existe o no se puede encontrar en la ubicación especificada. Puede aparecer si un archivo está mal escrito, se mueve o se elimina, o incluso cuando un programa no tiene los permisos necesarios para acceder al archivo. Para corregir el error, puede realizar una validación de entrada para asegurarse de que la ruta del archivo sea correcta y que el programa tenga los permisos necesarios para acceder al archivo.

IOExcepción

IOException es una excepción marcada en Java que representa un error encontrado al realizar operaciones de entrada o salida, como leer o escribir en un archivo o socket de red. Puede ocurrir por varios motivos, como que el archivo especificado falte o sea inaccesible, un error de red o permisos insuficientes. Para solucionar el problema, debe realizar varias acciones, como verificar el mensaje de error, manejar la excepción usando try-catch , cerrar recursos, verificar el permiso del archivo, etc.

No existe tal excepción de método

NoSuchMethodException es una excepción que se produce en tiempo de ejecución cuando intentamos llamar a un método que no existe en la clase. Esta excepción generalmente ocurre si llamamos a un método usando Class.getMethod() o Class.getDeclaredMethod() y el nombre del método especificado no se encuentra en la clase o interfaz. También puede ocurrir una excepción cuando intentamos llamar a un método usando la clase java.lang.reflect.Method y el nombre del método especificado no existe en el objeto. Para evitar esta excepción, asegúrese de llamar a un método válido con la firma del método y el especificador de acceso correctos.

Ninguna excepción de campo tal

NoSuchFieldException es una excepción de tiempo de ejecución que ocurre cuando intentamos acceder a un campo que no está en la clase. Esta excepción generalmente ocurre cuando llamamos a un método usando Class.getField() o Class.getDeclaredField() y el nombre del campo especificado no se encuentra en la clase o interfaz. Además, también se puede llamar si intentamos acceder a un campo utilizando la clase java.lang.reflect.Field y el nombre del campo especificado no existe en el objeto. Para evitar esta excepción, asegúrese de acceder a un campo válido con el nombre y los modificadores de acceso correctos. Si accede a un campo privado, asegúrese de utilizar el método getDeclaredField() en lugar del método getField() .

Excepción de acceso ilegal

IllegalAccessException es una excepción en tiempo de ejecución que ocurre cuando intentamos acceder a un campo o método en una clase pero no tenemos los derechos de acceso necesarios. Esta excepción suele aparecer cuando intentamos acceder a un campo o método privado desde fuera de una clase o cuando intentamos acceder a un campo o método protegido desde una clase que no es una subclase de la clase original. También se puede llamar al intentar acceder a un campo o método que la clase java.lang.reflect.AccessibleObject ha marcado como no disponible . Para evitar este problema, asegúrese de tener los permisos necesarios en el campo o método al que intenta acceder. Si el campo o método es privado, es posible que necesite utilizar la reflexión y establecer AccessibleObject en verdadero (para acceder a él). Sin embargo, tenga cuidado al utilizar la reflexión para acceder a campos o métodos privados, ya que puede romper la encapsulación y comprometer la integridad de la clase.

VerificarError

VerifyError es un error en tiempo de ejecución que es una subclase de LinkageError . Ocurre cuando la Máquina Virtual Java (JVM) encuentra un archivo de clase que viola ciertas reglas de validación. Cuando se compila una clase Java, el compilador verifica si el código de bytes sigue ciertas reglas y restricciones, como la seguridad de tipos y el uso adecuado de la pila y las variables locales. Si un archivo de clase viola estas reglas, la JVM generará un VerifyError al cargar y verificar la clase en tiempo de ejecución. Para evitar VerifyError , asegúrese de que su código siga la sintaxis y la semántica correctas del lenguaje Java. Si encuentra un VerifyError , debe verificar su código para asegurarse de que sea válido y que no haya violaciones de las reglas de verificación del código de bytes de Java.

Error de memoria insuficiente

OutOfMemoryError es una subclase de Error , un tipo Throwable que introduce problemas graves que no se pueden resolver en tiempo de ejecución. Aunque Java 8 incluye algunas mejoras en la recolección de basura y la administración de la memoria, aún puede encontrar un OutOfMemoryError si su aplicación usa demasiada memoria o administra el uso de la memoria incorrectamente. Para evitar OutOfMemoryError , debe administrar adecuadamente el uso de la memoria en su aplicación Java. Esto implica utilizar estructuras de datos y algoritmos que utilicen la memoria de manera eficiente, evitando la creación innecesaria de objetos y eliminando correctamente los objetos cuando ya no sean necesarios. Además, puede aumentar el tamaño máximo del montón para la JVM utilizando el indicador -Xmx al ejecutar su programa Java.

Error de desbordamiento de pila

StackOverflowError es un tipo de error que ocurre cuando el tamaño de pila requerido por un programa excede la cantidad de memoria que se le asigna. Puede ocurrir cuando un programa llama a demasiados métodos anidados o cuando un método se llama a sí mismo de forma recursiva demasiadas veces, lo que da como resultado un bucle infinito. La máquina virtual Java (JVM) asigna una cantidad fija de memoria para la pila de ejecución, que se utiliza para realizar un seguimiento de las llamadas a métodos y las variables locales. Cuando la pila se desborda, la JVM genera un StackOverflowError . Para evitar StackOverflowError , es importante asegurarse de que su programa Java haga un uso adecuado de la recursividad y las llamadas a métodos. Si encuentra un StackOverflowError , puede intentar aumentar el tamaño de la pila utilizando el indicador -Xss cuando ejecute su programa Java.

Excepción de invocación de objetivos

InvocationTargetException es una excepción marcada lanzada por el mecanismo de reflexión de Java. Es parte del paquete java.lang.reflect.InvocationTargetException y se utiliza para indicar que se produjo una excepción durante la invocación de un método o constructor. Cuando se invoca un método o constructor utilizando el mecanismo de reflexión de Java, se llama al método invoke() de la clase java.lang.reflect.Method o java.lang.reflect.Constructor . Si el método o constructor invocado genera una excepción, el método invoke() la detecta y la envuelve en una InvocationTargetException . Esta excepción luego se pasa a la persona que llama al método invoke() . Para corregir la excepción InvocationTargetException , debemos detectarla, obtener la excepción de causa raíz utilizando el método getCause() y manejar la excepción de causa raíz en consecuencia. Tenga en cuenta que la causa raíz podría ser una excepción marcada o una excepción en tiempo de ejecución, así que asegúrese de manejarla correctamente.

Formas de corregir las excepciones más comunes en Java

Cómo arreglar NullPointerException

Escenario: tienes un método que accede a un objeto que tiene el valor nulo .
String title= null;
System.out.println(title.length()); // Это вызовет NullPointerException
Solución n.° 1: verifique si el objeto es nulo antes de usarlo.
if(title!= null) {
   System.out.println(title.length());
} else {
   System.out.println("title is null");
}
Solución n.º 2: utilice Opcional para evitar NullPointerException .
Optional<String> optionalTitle = Optional.ofNullable(getTitle());
if (optionalTitle.isPresent()) {
   String title= optionalTitle.get();
   System.out.println("Title: " + title);
} else {
   System.out.println("Title is not available.");
}

Cómo arreglar ArrayIndexOutOfBoundsException

Escenario: está intentando acceder a una matriz en un índice que está fuera de sus límites.
int[] numbers = {4, 5, 6};
System.out.println(numbers[3]);   // Это вызовет ArrayIndexOutOfBoundsException
Solución: verifique la longitud de la matriz antes de acceder a ella y asegúrese de estar utilizando índices válidos.
int[] numbers = {4, 5, 6};
if (numbers.length > 3) {
   System.out.println(numbers[3]);
} else {
   System.out.println("ArrayIndexOutOfBoundsException: Please use valid indexes of the Array");
}

Cómo arreglar ClassCastException

Escenario: está intentando convertir un objeto a un tipo que es incompatible con su tipo real.
Object obj = "Java Exception";
Integer number = (Integer) obj; // Это вызовет ClassCastException
Solución: asegúrese de convertir objetos únicamente a tipos con los que sean compatibles.
Object obj = "Java Exception";
if(obj instanceof Integer) {
   Integer number = (Integer) obj;
   System.out.println(number);
} else {
   System.out.println("Object cannot caste to Integer");
}

Cómo solucionar la excepción IllegalArgumentException

Escenario: pasó un argumento no válido a un método.
public void printNumber(int number) {
   if(number <= 0) {
      throw new IllegalArgumentException("You cannot pass a negative number or zero");
   }
   System.out.println(number);
}

printNumber(-1); // Это вызовет IllegalArgumentException
Solución: asegúrese de pasar argumentos válidos a los métodos. En este caso, pase un número positivo.
printNumber(1); //  Это успешно напечатает 1.

Cómo solucionar la excepción de estado ilegal

Escenario: el objeto se encuentra en un estado no válido.
public class Bike {

   private Boolean isStarted;

   public void start() {
      if(isStarted) {
        throw new IllegalStateException("Bike is already started");
      }
      isStarted = true;
      System.out.println("Bike started");
   }
}

Bike bike= new Bike();
bike.start();
bike.start(); // Это вызовет IllegalStateException потому что bike is already started
Solución: asegúrese de mantener el estado del objeto correctamente.
Bike bike= new Bike();
bike.start();

Cómo solucionar la excepción de operación no compatible

Escenario: utiliza una operación que no es compatible con un objeto. Un ejemplo popular es cuando usa la operación remove() en una colección inmutable, probablemente verá una excepción UnsupportedOperationException .
List<String> list = Arrays.asList("Java", "Angular", "Spring");
list.add("Python"); // Это вызовет UnsupportedOperationException
Debido a que el método Arrays.asList() devuelve una lista inmutable, no admite agregar ni eliminar elementos. Solución: asegúrese de llamar solo a operaciones admitidas en objetos.
List<String> list = new ArrayList<>(Arrays.asList("Java", "Angular" "Spring"));
list.add("Python");
System.out.println(list);

Cómo arreglar la excepción aritmética

Escenario n.º 1: está intentando realizar una operación de división de números enteros que produce un resultado fraccionario.
int i = 10;
int j = 4;
int k = i/j; // Это вызовет исключение ArithmeticException: целочисленное деление будет дробным
Aquí el resultado de la operación de división es 2,5, que es un valor fraccionario. Debido a que los números enteros no pueden almacenar valores fraccionarios, se lanza una ArithmeticException . Solución: para evitar esta excepción, podemos usar un tipo de datos que admita valores fraccionarios, como double , para almacenar el resultado de la operación de división. He aquí un ejemplo:
int i = 10;
int j = 4;
double k = (double) i/j;
Escenario #2: Intentas dividir por cero y obtienes esta excepción. Este es el escenario más común.
int i = 4;
int j = 0;
int k = i/j; // Это вызовет исключение ArithmeticException: нельзя делить на ноль
Solución: Maneje correctamente la división por cero. Por ejemplo, el siguiente código demuestra el procesamiento correcto.
int i = 4;
int j = 0;
if(j != 0) {
int k = i/j;
System.out.println(k);
} else {
System.out.println("ArithmeticException: Cannot divide by zero");
}

Cómo solucionar la excepción IndexOutOfBoundsException

Escenario: está intentando acceder a una colección con un índice que está fuera de ella.
List<String> list = Arrays.asList("Apple", "Papaya", "Mango");
System.out.println(list.get(3)); // Это вызовет IndexOutOfBoundsException
Solución: verifique el tamaño de la colección antes de acceder a ella y asegúrese de estar utilizando índices válidos.
List<String> list = Arrays.asList("Apple", "Papaya", "Mango");
if (list.size() > 3) {
   System.out.println(list.get(3));
} else {
   System.out.println("You are using the Index which is out of bounds");
}

Cómo arreglar IOException

Escenario: una operación de entrada/salida falla porque no se puede acceder al archivo.
try {
   File inputFile = new FileReader("pqr.txt");
   BufferedReader reader = new BufferedReader(inputFile);
   String line = reader.readLine();
   System.out.println(line);
} catch (IOException e) {
   e.printStackTrace();
}
Solución: Maneje los errores de E/S y asegúrese de que los recursos se cierren correctamente.
File inputFile = new File("pqr.txt");

if (!inputFile.exists() || !inputFile.canRead()) {
 System.out.println("The input file is missing or not readable.");
 return;
}

try {
BufferedReader reader = new BufferedReader(inputFile);
 String line = reader.readLine();
 System.out.println(line);
  reader.close();
} catch (IOException e) {
 e.printStackTrace();
}
Tenga en cuenta que, como alternativa, podemos utilizar la función de prueba con recursos introducida en Java 7 para cerrar recursos automáticamente como se muestra a continuación. Podemos declarar uno o más recursos en una declaración try y Java cerrará automáticamente los recursos al final del bloque, independientemente de si el bloque se completa normalmente o si se lanza una excepción.
try (BufferedReader reader = new BufferedReader(new FileReader("pqr.txt"))) {
....
} catch {
....
}

Cómo reparar FileNotFoundException

Escenario: el archivo no se encontró en la ubicación especificada.
try {
     BufferedReader reader = new BufferedReader(new FileReader("abc.txt"));
     String line = reader.readLine();
     System.out.println(line);
     reader.close();
} catch (FileNotFoundException | IOException e) {
     System.out.println("An error has occurred while reading the file: " + e.getMessage());
}
Solución: asegúrese de que el archivo exista y tenga los permisos adecuados para acceder a él.
try {
    File file = new File("abc.txt");
    if(!file.exists()) {
    throw new FileNotFoundException("File not found at the specified location");
    }
    BufferedReader reader = new BufferedReader(new FileReader(file));
    String line = reader.readLine();
    System.out.println(line);
    reader.close();
} catch (IOException e) {
    e.printStackTrace();
}

Cómo arreglar NoSuchMethodException

Escenario: si está intentando acceder a un método que no se puede encontrar.
public class TestClass {
   public void sayHello() {
      System.out.println("Hello");
   }
}

TestClass obj = new TestClass();
Method method = obj.getClass().getMethod("printHello"); // Это вызовет NoSuchMethodException
Solución: Verifique que el método exista y que el nombre y la firma del método sean correctos.
public class TestClass {
   public void sayHello() {
      System.out.println("Hello");
   }
}

TestClass  obj = new TestClass();
try {
    Method method = obj.getClass().getMethod("sayHello");
} catch (NoSuchMethodException e) {
    e.printStackTrace();
}

Cómo arreglar la excepción de modificación concurrente

Escenario: una colección cambia mientras se itera.
List<String> list = new ArrayList<>();
list.add("Java");
list.add("Python");
for (String str : list) {
  list.remove(str);  // Это вызовет ConcurrentModificationException
}
Solución: utilice un iterador para iterar sobre una colección y modifíquela utilizando métodos de iterador.
List<String> list = new ArrayList<>();
list.add("Java");
list.add("Python");
Iterator<String> iterator = list.iterator();
while (iterator.hasNext()) {
    String str = iterator.next();
    iterator.remove();
}
Comentarios
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION