2023Ensayo sobre estereotipos anormales de Java: preguntas de la entrevista

Arquitectura de excepción de Java y palabras clave de excepción

Introducción a las excepciones de Java

La excepción de Java es un mecanismo consistente proporcionado por Java para identificar y responder a errores.

El mecanismo de excepción de Java puede separar el código de manejo de excepciones y el código comercial normal en el programa, garantizar que el código del programa sea más elegante y mejorar la solidez del programa. En el caso del uso efectivo de excepciones, las excepciones pueden responder claramente a las tres preguntas de qué, dónde y por qué: el tipo de excepción responde "qué" se lanza, el seguimiento de la pila de excepciones responde "dónde" se lanza y la información de excepción responde "por qué" tirará.

Arquitectura de excepción de Java

[Error en la transferencia de la imagen del enlace externo, el sitio de origen puede tener un mecanismo anti-limpieza, se recomienda guardar la imagen y cargarla directamente (img-g4pG306A-1692508916341) (03-Preguntas de la entrevista de excepción de Java (última versión de 2020).assets /Excepción de Java.png) ]

1. Lanzable

Throwable es la superclase de todos los errores y excepciones en el lenguaje Java.

Throwable contiene dos subclases: Error (error) y Exception (excepción), que generalmente se usan para indicar que ha ocurrido una condición anormal.

Throwable contiene una instantánea de la pila de ejecución del subproceso cuando se crea su subproceso y proporciona interfaces como printStackTrace() para obtener información como datos de seguimiento de la pila.

2.Error

Definición: Clase de error y sus subclases. Un error que el programa no puede manejar, lo que indica que se ha producido un error grave al ejecutar la aplicación.

Características: Este tipo de error generalmente indica un problema con la JVM cuando se ejecuta el código. Generalmente hay virtuales

MachineError (error de ejecución de la máquina virtual), NoClassDefFoundError (error de definición de clase)

esperar. Por ejemplo, OutOfMemoryError: error de memoria insuficiente; StackOverflowError: error de desbordamiento de pila. Cuando se produce un error de este tipo, la JVM finalizará el hilo. Estos errores son excepciones no comprobadas, no errores de código. Por lo tanto, cuando ocurren tales errores, la aplicación no

Estos errores deben solucionarse. Según la convención de Java, ¡no deberíamos implementar ninguna subclase de Error nueva!

3. Excepción

Una excepción que el propio programa puede detectar y manejar. Excepción Este tipo de excepción se divide en dos categorías: excepción de tiempo de ejecución y excepción de tiempo de compilación.

excepción en tiempo de ejecución

Definición: La clase RuntimeException y sus subclases representan excepciones que pueden ocurrir durante el tiempo de ejecución de JVM.

Característica: el compilador de Java no lo verifica. En otras palabras, cuando tal excepción puede ocurrir en el programa, si no se "lanza mediante la declaración throws" ni "no se detecta con la declaración try-catch", aún se compilará. Por ejemplo, NullPointerException excepción de puntero nulo,

ArrayIndexOutBoundException excepción de subíndice de matriz fuera de límites, excepción de conversión de tipo ClassCastException, excepción aritmética ArithmeticExecption. Este tipo de excepción es una excepción no verificada, que generalmente es causada por un error de lógica del programa, puede optar por capturarlo en el programa o no. Aunque el compilador de Java no verifica las excepciones en tiempo de ejecución, también podemos declarar lanzamientos mediante lanzamientos.

También se puede capturar y procesar mediante try-catch. Si se produce una excepción en tiempo de ejecución, es necesario modificar el código para evitarla. Por ejemplo, si ocurre un divisor por cero, ¡necesitas codificar para evitar que esto suceda!

Las excepciones RuntimeException serán lanzadas y capturadas automáticamente por la máquina virtual Java (¡incluso si no escribimos declaraciones de captura de excepciones, se generarán errores durante el tiempo de ejecución!), la gran mayoría de dichas excepciones son problemas con el código en sí, que debería Ser lógicamente arreglar y mejorar el código.

excepción de tiempo de compilación

Definición: Excepciones en Exception distintas de RuntimeException y sus subclases.

Características: El compilador de Java lo comprueba. Si se produce una excepción de este tipo en el programa, como

ClassNotFoundException (no se encontró la excepción de clase especificada), IOException (excepción de flujo IO), ya sea declarada y lanzada mediante throws, o capturada y procesada mediante try-catch; de lo contrario, no se puede compilar. En el programa, este tipo de excepción generalmente no se personaliza, sino que se utiliza directamente la clase de excepción proporcionada por el sistema. Para esta excepción, debemos agregar manualmente una declaración catch al código para manejar la excepción.

4. Excepciones marcadas y no marcadas

Todas las excepciones en Java se pueden dividir en excepciones marcadas y excepciones no marcadas.

(excepción no marcada)。

excepción marcada

El compilador requiere excepciones que deben manejarse. Durante la operación del programa correcto, a menudo es fácil aparecer y cumplir con los

Excepciones esperadas. Una vez que se produce una excepción de este tipo, se debe manejar de alguna manera. eliminar

A excepción de RuntimeException y sus subclases, otras excepciones de excepción son excepciones marcadas. El compilador verificará dichas excepciones, es decir, cuando el compilador detecte que dichas excepciones pueden ocurrir en algún lugar de la aplicación, le solicitará que maneje esta excepción; ya sea use try-catch para detectarla o úsela en el firma del método La palabra clave throws arroja; de lo contrario, la compilación falla.

excepción no marcada

El compilador no verifica y no requiere excepciones que deban ser manejadas, es decir, cuando ocurre tal excepción en el programa, incluso si no la detectamos con try-catch, ni usamos throws para lanzar la excepción, el La compilación se realizará normalmente. Este tipo de excepción incluye excepciones de tiempo de ejecución (RuntimeException y sus subclases) y errores (Error).

Palabra clave de excepción de Java

• intentar – para escuchar. Coloque el código a monitorear (el código que puede generar una excepción) en el bloque de declaración de prueba, y cuando ocurre una excepción en el bloque de declaración de prueba, se lanza la excepción.

• catch: se utiliza para detectar excepciones. catch se utiliza para detectar excepciones que ocurren en el bloque try.

• finalmente: el bloque de sentencia finalmente siempre se ejecutará. Se utiliza principalmente para recuperar recursos materiales (como conexiones de bases de datos, conexiones de red y archivos de disco) abiertos en el bloque try. Solo el bloque finalmente, una vez completada la ejecución, volverá a ejecutar la declaración return o throw en el bloque try o catch. Si la declaración del método de terminación, como return o throw, se usa en el bloque finalmente, no regrese a la ejecución y deténgase directamente.

• throw – usado para lanzar una excepción.

• throws: utilizado en firmas de métodos para declarar las excepciones que el método puede generar.

Manejo de excepciones de Java

[Falló la transferencia de la imagen del enlace externo, el sitio de origen puede tener un mecanismo anti-sanguijuela, se recomienda guardar la imagen y cargarla directamente (img-NPsLcXex-1692508916342) (03-Preguntas de entrevista anormales de Java (última versión de 2020).assets /imagen-20201109173809704.png )]

Java maneja excepciones a través de métodos orientados a objetos. Una vez que un método arroja una excepción, el sistema encuentra automáticamente un controlador de excepciones adecuado (controlador de excepciones) basado en el objeto de excepción para manejar la excepción, clasifica varias excepciones y proporciona una buena interfaz. En Java, cada excepción es un par.

Objeto, que es una instancia de la clase Throwable o sus subclases. Cuando ocurre una excepción en un método, se lanza un objeto de excepción, que contiene información de excepción, y el método que llama a este objeto puede detectar la excepción y procesarla. El manejo de excepciones de Java se implementa mediante cinco palabras clave: probar, atrapar, lanzar, lanzar y finalmente.

En las aplicaciones Java, el mecanismo de manejo de excepciones se divide en declarar excepciones, lanzar excepciones y detectar excepciones.

excepción de declaración

En general, debe detectar aquellas excepciones que sabe cómo manejar y transmitir las excepciones que no sabe cómo manejar.

ir. Pasar excepciones Puede utilizar la palabra clave throws en la firma del método para declarar las excepciones que se pueden generar. Aviso

[Falló la transferencia de la imagen del enlace externo, el sitio de origen puede tener un mecanismo anti-sanguijuela, se recomienda guardar la imagen y cargarla directamente (img-OOzCWT0z-1692508916343) (03-Preguntas de la entrevista anormal de Java (última versión de 2020).assets /clip_image001-1604914706296.gif )] Las excepciones no marcadas (Error, RuntimeException o sus subclases) no pueden usar la palabra clave throws para declarar excepciones que se lanzarán.

​ [Error en la transferencia de la imagen del enlace externo, el sitio de origen puede tener un mecanismo anti-sanguijuela, se recomienda guardar la imagen y cargarla directamente (img-UO6CA5bd-1692508916343) (03-Preguntas de entrevista anormales de Java (última versión de 2020). activos/clip_image002-1604914706296.gif)] Si se produce una excepción en tiempo de compilación en un método, necesita procesamiento try-catch/throws; de lo contrario, provocará un error de compilación

Lanzar una excepción

Si cree que algunos problemas anormales no se pueden resolver y no es necesario que la persona que llama los maneje, puede generar una excepción. La palabra clave throw se utiliza para generar una excepción de tipo Throwable dentro del método. Cualquier código Java puede generar una excepción mediante la declaración de lanzamiento.

excepción de captura

El programa generalmente no informa un error antes de ejecutarse, pero pueden ocurrir algunos errores desconocidos después de ejecutarse, pero si no desea lanzarlo directamente al nivel superior, debe detectar la excepción en forma de intento. .catch..., y luego según diferentes excepciones La situación se trata en consecuencia. Cómo elegir el tipo de excepción

Puede elegir si detectar una excepción, declarar una excepción o lanzar una excepción de acuerdo con la siguiente figura

[Falló la transferencia de la imagen del enlace externo, el sitio de origen puede tener un mecanismo anti-sanguijuela, se recomienda guardar la imagen y cargarla directamente (img-AOhVX6eX-1692508916344)(03-Preguntas de entrevista anormales de Java (última versión de 2020).assets /imagen-20201109173855168.png )]

Los métodos comunes de manejo de excepciones arrojan excepciones directamente

En general, debe detectar aquellas excepciones que sabe cómo manejar y transmitir las excepciones que no sabe cómo manejar. Pasar excepciones Puede utilizar la palabra clave throws en la firma del método para declarar las excepciones que se pueden generar.

1 private static void readFile(String filePath) throws IOException { 
2 File file = new File(filePath);
3 String result; 
4 BufferedReader reader = new BufferedReader(new FileReader(file)); 
5 while((result = reader.readLine())!=null) { 
6 System.out.println(result);
7	}
8	reader.close();
9	}

Encapsular excepción y lanzar

A veces lanzamos una excepción desde el catch para cambiar el tipo de excepción. Se utiliza principalmente en la integración de múltiples sistemas. Cuando falla un subsistema, puede haber múltiples tipos de excepciones, que pueden exponerse al exterior con un tipo de excepción unificado sin exponer demasiados detalles de las excepciones internas.

1 private static void readFile(String filePath) throws MyException {
2	try {
3	// code
4 } catch (IOException e) {
5	MyException ex = new MyException("read file failed.");
6	ex.initCause(e);
7	throw ex;
8	}
9	}

excepción de captura

Se pueden capturar múltiples tipos de excepciones en un bloque de declaración try-catch y diferentes tipos de excepciones se pueden manejar de manera diferente

1	private static void readFile(String filePath) {
2	try {
3	// code
4	} catch (FileNotFoundException e) {
5	// handle FileNotFoundException
6 } catch (IOException e){
7	// handle IOException
8	}
9	}

La misma captura también puede detectar varios tipos de excepciones, separadas por |

1	private static void readFile(String filePath) {
2	try {
3	// code
4	} catch (FileNotFoundException | UnknownHostException e) {
5	// handle FileNotFoundException or UnknownHostException
6 } catch (IOException e){
7	// handle IOException
8	}
9	}

excepción personalizada

Por convención, definir una clase de excepción debe contener dos constructores, un constructor sin argumentos y un

Constructor para información de descripción detallada (el método toString de Throwable imprimirá esta información detallada, lo cual es útil al depurar)

1	public class MyException extends Exception {
2	public MyException(){ }
3	public MyException(String msg){
4	super(msg);
5	}
6	// ...
7	}

intentar atrapar finalmente

Cuando ocurre una excepción en el método, el código después de la excepción no se ejecutará nuevamente. Si algunos recursos locales se han adquirido antes y deben liberarse, el código para liberar los recursos locales debe llamarse cuando el método finalice normalmente y en la declaración catch, lo que hace que el código sea más engorroso, y la declaración finalmente puede resolver este problema.

1 private static void readFile(String filePath) throws MyException { 
2  File file = new File(filePath); 
3  String result;
4  BufferedReader reader = null; 
5  try { 
6  reader = new BufferedReader(new FileReader(file)); 
7  while((result = reader.readLine())!=null) {
8  System.out.println(result); 
9  } 
10  } catch (IOException e) {
11  System.out.println("readFile method catch block."); 
12  MyException ex = new MyException("read file failed."); 
13  ex.initCause(e);
14  throw ex; 
15  } finally { 
16  System.out.println("readFile method finally block.");
17  if (null != reader) { 
18  try {
19  reader.close(); 
20  } catch (IOException e) {
21  e.printStackTrace(); 
22  } 
23  }
24  } 
25 }

Al llamar a este método, si ocurre una excepción al leer el archivo, el código ingresará al bloque de código de captura y luego ingresará al bloque de código finalmente; si no ocurre ninguna excepción al leer el archivo, omitirá el bloque de código de captura e ingresará directamente el bloque de código finalmente. Entonces, el código en fianlly se ejecutará independientemente de si ocurre una excepción en el código. Si el bloque de código catch contiene una declaración de retorno, ¿se seguirá ejecutando el código finalmente? Modifique la cláusula catch en el código anterior de la siguiente manera:

1 catch (IOException e) { 
2  System.out.println("readFile method catch block.");
3  return; 
4 }

Llame al método readFile para observar si la cláusula finalmente se ejecuta cuando se llama a la declaración de retorno en la cláusula catch

1 readFile method catch block. 
2 readFile method finally block.

Se puede ver que incluso si la declaración de retorno se incluye en la captura, la cláusula finalmente se seguirá ejecutando. Si finalmente también contiene una declaración de devolución, la devolución finalmente sobrescribirá la devolución anterior.

prueba con recurso

En el ejemplo anterior, el método de cierre finalmente también puede generar IOException, cubriendo así la excepción original. JAVA 7 proporciona una forma más elegante de realizar la liberación automática de recursos. Los recursos liberados automáticamente deben ser clases que implementen la interfaz AutoCloseable.

1	private static void tryWithResourceTest(){
2	try (Scanner scanner = new Scanner(new FileInputStream("c:/abc"),"UTF8")){
3	// code
4 } catch (IOException e){
5	// handle exception
6	}
7	}

Cuando el bloque de código de prueba sale, el método scanner.close se llamará automáticamente. La diferencia con colocar el método scanner.close en el bloque de código finalmente es que si scanner.close arroja una excepción, se suprimirá y se lanzará. Uno sigue siendo la excepción original. La excepción suprimida se agregará a la excepción original mediante el método addSusppressed. Si desea obtener la lista de excepciones suprimidas, puede llamar al método getSuppressed para obtenerla.

Preguntas comunes de la entrevista sobre excepciones de Java

1. ¿Cuál es la diferencia entre error y excepción?

Los errores de tipo Error suelen ser errores relacionados con la máquina virtual, como fallos del sistema, memoria insuficiente, desbordamiento de pila, etc. El compilador no detectará dichos errores y las aplicaciones JAVA no deberían capturarlos. Una vez que se producen dichos errores, normalmente el la aplicación finalizará y la aplicación en sí no podrá restaurarse;

Los errores de la clase Exception se pueden detectar y procesar en la aplicación. Por lo general, cuando se encuentran dichos errores, deben procesarse para que la aplicación pueda continuar ejecutándose normalmente.

2. ¿Cuál es la diferencia entre excepciones de tiempo de ejecución y excepciones generales (excepciones marcadas)?

Las excepciones en tiempo de ejecución incluyen la clase RuntimeException y sus subclases, que representan excepciones que pueden ocurrir durante el tiempo de ejecución de la JVM. El compilador de Java no busca excepciones en tiempo de ejecución.

Una excepción marcada es una excepción en Exception distinta de RuntimeException y sus subclases. Las excepciones marcadas las verifica el compilador de Java.

La diferencia entre ** excepción RuntimeException y excepción marcada: ** Si es obligatorio que la persona que llama maneje esta excepción, si es obligatorio que la persona que llama la maneje, entonces use la excepción marcada; de lo contrario, elija la excepción no marcada (RuntimeException). En términos generales, si no hay ningún requisito especial, recomendamos utilizar RuntimeException.

3. ¿Cómo maneja la JVM las excepciones?

Si ocurre una excepción en un método, este método creará un objeto de excepción y lo transferirá a la JVM. El objeto de excepción contiene el nombre de la excepción, la descripción de la excepción y el estado de la aplicación cuando ocurre la excepción. El proceso de crear un objeto de excepción y pasarlo a la JVM se denomina lanzar una excepción. Puede haber una serie de llamadas a métodos antes de ingresar al método que generó la excepción. La lista ordenada de esta serie de llamadas a métodos se denomina pila de llamadas.

La JVM seguirá la pila de llamadas para ver si hay código que pueda manejar excepciones y, de ser así, llamará al código de manejo de excepciones. Cuando la JVM encuentra código que puede manejar la excepción, pasa la excepción que se le ocurrió. Si la JVM no encuentra un bloque de código que pueda manejar la excepción, la JVM reenvía la excepción al controlador de excepciones predeterminado (el controlador de excepciones predeterminado es parte de la JVM), que imprime el mensaje de excepción y finaliza la aplicación.

4. ¿Cuál es la diferencia entre tirar y tirar?

El manejo de excepciones en Java incluye no solo capturar y manejar excepciones, sino también declarar y lanzar excepciones. Puede declarar las excepciones que lanzará el método en el método mediante la palabra clave throws, o lanzar excepciones mediante throw dentro del objeto del método.

**Las diferencias entre el uso de la palabra clave throws y la palabra clave throw son las siguientes: **

  • La palabra clave throw se usa dentro de un método y solo se puede usar para lanzar una excepción. Se usa para lanzar una excepción en un método o bloque de código. Se pueden lanzar excepciones marcadas y no marcadas.
  • La palabra clave throws se usa en la declaración del método y se pueden generar múltiples excepciones, que se usa para identificar la lista de excepciones que puede generar el método. Un método utiliza throws para identificar la lista de excepciones que se pueden lanzar. El método que llama a este método debe contener código que pueda manejar excepciones; de lo contrario, la excepción correspondiente debe declararse con la palabra clave throws en la firma del método.

5. ¿Cuál es la diferencia entre final, finalmente y finalizar?

  • Final puede modificar clases, variables y métodos: las clases modificadas indican que la clase no se puede heredar, los métodos modificados indican que el método no se puede anular y las variables modificadas indican que la variable es una constante que no se puede reasignar.
  • Finalmente generalmente funciona en el bloque de código try-catch. Cuando se trata de excepciones, generalmente colocamos el método de código que debe ejecutarse en el bloque de código finalmente, lo que indica que el bloque de código se ejecutará independientemente de si ocurre una excepción. Generalmente es Se utiliza para almacenar algunos recursos cerrados.código.
  • finalize es un método que pertenece a la clase Object, y la clase Object es la clase principal de todas las clases. Java permite el uso del método finalize() para realizar la limpieza necesaria antes de que el recolector de basura borre el objeto de la memoria.

6. ¿Cuál es la diferencia entre NoClassDefFoundError y ClassNotFoundException?

NoClassDefFoundError es una excepción de tipo Error, causada por la JVM y no se debe intentar detectar.

El motivo de esta excepción es que la definición de la clase no se puede encontrar en la memoria cuando la JVM o ClassLoader intenta cargar una clase. Esta acción ocurre durante el tiempo de ejecución, es decir, la clase existe en el momento de la compilación, pero no se puede encontrar en tiempo de ejecución.Puede ser que se eliminó después de la mutación y otras razones;

ClassNotFoundException es una excepción marcada que debe detectarse y manejarse explícitamente mediante un try-catch o declararse con la palabra clave throws en la firma del método. Cuando se utiliza Class.forName, ClassLoader.loadClass o ClassLoader.findSystemClass para cargar dinámicamente una clase en la memoria, si la clase no se encuentra a través de los parámetros de ruta de clases pasados, se generará esta excepción; se genera otra posible razón para esta excepción. una clase que ha sido cargada en la memoria por un cargador de clases y otro cargador intenta cargarla.

7. ¿Qué parte de try-catch-finalmente se puede omitir?

Respuesta: se puede omitir la captura

**razón**

En realidad, una declaración más estricta es: try solo es adecuado para manejar excepciones de tiempo de ejecución, y try+catch es adecuado para manejar excepciones de tiempo de ejecución + excepciones comunes. En otras palabras, si solo usa try para manejar excepciones comunes sin capturar, la compilación no pasará, porque el compilador estipula rígidamente que si elige capturar excepciones comunes, debe usar catch para mostrar la declaración para su posterior procesamiento. Sin embargo, las excepciones de tiempo de ejecución no se especifican en el momento de la compilación, por lo que se puede omitir el catch y el compilador se siente comprensible si agrega el catch.

En teoría, el compilador no parece agradable a la vista de ningún código y cree que puede haber problemas potenciales, por lo que incluso si agrega try a todo el código, el código simplemente agrega una capa de máscara sobre la base del funcionamiento normal durante tiempo de ejecución. Pero una vez que agrega try a un fragmento de código, equivale a prometer explícitamente al compilador que detectará la excepción que este código pueda generar en lugar de generarla. Si es una excepción ordinaria, el compilador requiere que se capture con un catch para su posterior procesamiento; si es una excepción en tiempo de ejecución, se captura y luego se descarta y finalmente barre el procesamiento, o se captura con un captura para su posterior procesamiento.

En cuanto a agregar finalmente, es un proceso de "barrido" que debe realizarse independientemente de si se detecta una excepción o no.

8. En try-catch-finally, si hay un retorno en la captura, ¿se seguirá ejecutando finalmente?

Respuesta: Se ejecutará y se ejecutará antes del regreso.

**Nota:** No es bueno cambiar el valor de retorno en finalmente, porque si hay un bloque de código finalmente, la declaración de retorno en el intento no regresará a la persona que llama inmediatamente, sino que registrará el valor de retorno hasta el bloque de código finalmente se ejecuta Luego, devuelve su valor a la persona que llama, y ​​si el valor de retorno se modifica finalmente, se devolverá el valor modificado. Obviamente, devolver o modificar el valor de retorno en finalmente causará muchos problemas al programa. En C#, los errores del compilador se utilizan directamente para evitar que los programadores hagan cosas tan sucias. En Java, el nivel de verificación de sintaxis del compilador también puede ser mejorado para generar advertencias o errores.

Ejemplo de código 1:

1 public static int getInt() { 
2  int a = 10; 
3  try {
4  System.out.println(a / 0); 
5  a = 20; 
6  } catch (ArithmeticException e) { 
7  a = 30; 
8  return a; 
9  /* 
10  * return a 在程序执行到这一步的时候,这里不是return a 而是 return 30;这个返 回路径就形成了 
11  * 但是呢,它发现后面还有finally,所以继续执行finally的内容,a=40 
12  * 再次回到以前的路径,继续走return 30,形成返回路径之后,这里的a就不是a变量 了,而是常量30 
13  */ 
14  } finally { 
15  a = 40; 
16  } 
17  return a; 
18 } 

**Resultado de la ejecución: **30

Ejemplo de código 2:

1 public static int getInt() { 
2  int a = 10; 
3  try { 
4  System.out.println(a / 0); 
5  a = 20; 
6  } catch (ArithmeticException e) { 
7  a = 30; 
8  return a; 
9  } finally { 
10  a = 40; 
11  //如果这样,就又重新形成了一条返回路径,由于只能通过1个return返回,所以这里直 接返回40 
12  return a; 
13  }
14 
15 } 

**Resultado de la ejecución: **40

9. La clase EjemploA hereda Exception y la clase EjemploB hereda EjemploA.

Existe el siguiente fragmento de código:

1 try { 
2  throw new ExampleB("b") 
3 } catch(ExampleA e){ 
4  System.out.println("ExampleA"); 
5 } catch(Exception e){ 
6  System.out.println("Exception"); 
7 } 

¿Cuál es el resultado de ejecutar este código?

respuesta:

Salida: EjemploA. (De acuerdo con el principio de sustitución de Liskov [donde se puede usar el tipo principal, se debe usar el subtipo], el bloque catch que detecta la excepción del tipo EjemploA puede detectar la excepción del tipo EjemploB lanzada en el bloque try)

Pregunta de la entrevista: indique el resultado de ejecutar el siguiente código. (La fuente de esta pregunta es el libro "Pensamientos sobre programación Java")

1 class Annoyance extends Exception { 
2 } 
3 class Sneeze extends Annoyance { 
4 } 
5 class Human { 
6  public static void main(String[] args) 
7  throws Exception { 
8  try { 
9  try { 
10  throw new Sneeze(); 
11  } catch ( Annoyance a ) { 
12  System.out.println("Caught Annoyance"); 
13  throw a; 
14  } 
15  } catch ( Sneeze s ) { 
16  System.out.println("Caught Sneeze"); 
17  return ; 
18  } finally { 
19  System.out.println("Hello World!"); 
20  } 
21  } 
22 }

resultado

1 Caught Annoyance 
2 Caught Sneeze 
3 Hello World! 

10. ¿Cuáles son las RuntimeExceptions comunes?

  • ClassCastException (excepción de conversión de clase)
  • IndexOutOfBoundsException (matriz fuera de límites)
  • NullPointerException (puntero nulo)
  • ArrayStoreException (excepción de almacenamiento de datos, el tipo es inconsistente al operar la matriz)
  • También existen excepciones BufferOverflowException para operaciones IO

11. ¿Cuáles son las excepciones comunes en Java?

java.lang.IllegalAccessError: error de acceso ilegal. Esta excepción se produce cuando una aplicación intenta acceder o modificar el campo de una clase (Campo) o llamar a su método, pero viola la declaración de visibilidad del campo o método.

java.lang.InstantiationError: error de creación de instancias. Esta excepción se produce cuando una aplicación intenta construir una clase o interfaz abstracta a través del nuevo operador de Java.

java.lang.OutOfMemoryError: Error de falta de memoria. Este error se produce cuando no hay suficiente memoria disponible para que la máquina virtual Java la asigne a un objeto.

java.lang.StackOverflowError: error de desbordamiento de pila. Este error se produce cuando el nivel de llamada recursiva de una aplicación es demasiado profundo, lo que provoca un desbordamiento de la pila o un bucle infinito.

java.lang.ClassCastException: excepción de conversión de clases. Supongamos que hay clases A y B (A no es una clase principal o subclase de B) y O es una instancia de A, entonces esta excepción se produce cuando se fuerza a O a construirse como una instancia de la clase B. Esta excepción a menudo se denomina excepción de conversión.

java.lang.ClassNotFoundException: excepción de clase no encontrada. Esta excepción se produce cuando la aplicación intenta construir una clase basada en el nombre de la clase en forma de cadena, pero no puede encontrar un archivo de clase con el nombre correspondiente después de atravesar CLASSPAH. java.lang.ArithmeticException: excepción de condición aritmética. Por ejemplo: división de números enteros por cero, etc.

java.lang.ArrayIndexOutOfBoundsException: excepción de índice de matriz fuera de límites. Se lanza cuando un índice en una matriz es negativo o mayor o igual que el tamaño de la matriz.

java.lang.IndexOutOfBoundsException: excepción de índice fuera de límites. Esta excepción se produce cuando el valor del índice de acceso a una secuencia es menor que 0 o mayor o igual al tamaño de la secuencia. java.lang.InstantiationException: excepción de creación de instancias. Esta excepción se produce cuando se intenta crear una instancia de una clase que es una clase o interfaz abstracta a través del método newInstance().

java.lang.NoSuchFieldException: la propiedad no existe excepción. Esta excepción se produce al acceder a una propiedad no existente de una clase.

java.lang.NoSuchMethodException: el método no existe excepción. Esta excepción se produce al acceder a un método inexistente de una clase.

java.lang.NullPointerException: excepción de puntero nulo. Esta excepción se produce cuando la aplicación intenta utilizar nulo donde se espera un objeto. Por ejemplo: llame al método de instancia del objeto nulo, acceda a las propiedades del objeto nulo, calcule la longitud del objeto nulo, use la declaración de lanzamiento para arrojar nulo, etc.

java.lang.NumberFormatException: excepción de formato numérico. Esta excepción se produce cuando se intenta convertir una cadena a un tipo de número específico, pero la cadena no cumple con el formato requerido por el tipo de número.

java.lang.StringIndexOutOfBoundsException: excepción de índice de cadena fuera de límites. Cuando se utiliza un valor de índice para acceder a caracteres en una cadena, y el valor de índice es menor que 0 o mayor o igual que el tamaño de la secuencia, se genera esta excepción.

Mejores prácticas de manejo de excepciones de Java

Manejar excepciones en Java no es una cuestión sencilla. No solo es difícil de entender para los principiantes, sino que incluso algunos desarrolladores experimentados necesitan dedicar mucho tiempo a pensar en cómo manejar las excepciones, incluidas qué excepciones deben manejarse, cómo manejarlas, etc. Es por eso que la mayoría de los equipos de desarrollo formulan algunas reglas para regular el manejo de excepciones. Y estas normas suelen ser drásticamente diferentes entre equipos. Este artículo presenta algunas de las mejores prácticas de manejo de excepciones utilizadas por muchos equipos.

1. Limpiar recursos en el bloque finalmente o usar la declaración try-with-resource

Cuando se utilizan recursos como InputStream que deben cerrarse después de su uso, un error común es cerrar el recurso después del bloque de prueba.

1	public void doNotCloseResourceInTry() {
2	FileInputStream inputStream = null;
3	try {
4	File file = new File("./tmp.txt");
5	inputStream = new FileInputStream(file);
6	// use the inputStream to read a file
7	// do NOT do this
8	inputStream.close();
9	} catch (FileNotFoundException e) {
10	log.error(e);
11	} catch (IOException e) {
12	log.error(e);
13	}
14	}

El problema es que este código sólo funciona cuando no se produce ninguna excepción. El código dentro del bloque de código de prueba se ejecutará normalmente y el recurso se podrá cerrar normalmente. Sin embargo, hay una razón para usar un bloque de código de prueba: generalmente llama a uno o más métodos que pueden generar una excepción, y también puede generar una excepción usted mismo, lo que significa que es posible que el código no se ejecute después de la parte del bloque de código de prueba. Como resultado, no cierra el recurso.

Por lo tanto, debe colocar el código de limpieza finalmente o utilizar la función de prueba con recursos.

1.1 Usando finalmente el bloque de código

A diferencia del bloque try de las líneas anteriores, el bloque finalmente siempre se ejecutará. Independientemente del éxito del bloque try

Se ejecutará después de la ejecución o después de que maneje la excepción en el bloque de código de captura. Por lo tanto, puede asegurarse de limpiar todos los recursos abiertos.

1 public void closeResourceInFinally() { 
2  FileInputStream inputStream = null; 
3  try { 
4  File file = new File("./tmp.txt");
5  inputStream = new FileInputStream(file); 
6  // use the inputStream to read a file
7  } catch (FileNotFoundException e) {
8  log.error(e);
9  } finally {
10  if (inputStream != null) { 
11  try { 
12  inputStream.close(); 
13  } catch (IOException e) { 
14  log.error(e); 
15  } 
16  } 
17  }
18 }

1.2 La sintaxis de prueba con recursos de Java 7

Puede utilizar esta sintaxis si su recurso implementa la interfaz AutoCloseable. La mayoría de los recursos estándar de Java heredan de esta interfaz. Cuando abre un recurso en una cláusula de prueba, el recurso se cerrará automáticamente después de que se ejecute el bloque de código de prueba o después de que se maneje la excepción.

1	public void automaticallyCloseResource() {
2	File file = new File("./tmp.txt");
3	try (FileInputStream inputStream = new FileInputStream(file);) {
4	// use the inputStream to read a file
5	} catch (FileNotFoundException e) {
6	log.error(e);
7 } catch (IOException e) {
8	log.error(e);
9	}
10	}
11

2. Priorizar excepciones claras

Cuanto más específica sea la excepción que lances, mejor, siempre recuerda que tu colega, o tú, dentro de unos meses, llamará a tu método y manejará la excepción.

Por lo tanto, es necesario garantizar que se les proporcione la mayor cantidad de información posible. De esta manera su API es más fácil de entender. Las personas que llaman a sus métodos pueden manejar mejor las excepciones y evitar comprobaciones adicionales. Por lo tanto, siempre trate de encontrar la clase apropiada para su evento de excepción, por ejemplo, lanzando un

NumberFormatException para reemplazar una IllegalArgumentException. Evite lanzar una excepción ambigua.

1 public void doNotDoThis() throws Exception {
2 ...
3	}
4	public void doThis() throws NumberFormatException { 
5 ...
6 }
7

3. Excepciones de documentos

También se requiere documentación cuando se declara un método para generar una excepción. El propósito es proporcionar a la persona que llama tanta información como sea posible para que las excepciones puedan evitarse o manejarse mejor.

Agregue la declaración @throws al Javadoc y describa el escenario donde se lanza la excepción.

1 public void doSomething(String input) throws MyBusinessException { 
2 ...
3 }

4. Lanzar excepciones con mensajes descriptivos.

Cuando se produce una excepción, es necesario describir el problema y la información relacionada con la mayor precisión posible, de modo que, ya sea que esté impreso en el registro o en la herramienta de monitoreo, se pueda leer más fácilmente, de modo que el mensaje de error específico y el error se puede localizar mejor, gravedad, etc.

Pero esto no quiere decir que debamos hablar mucho sobre el mensaje de error, porque el nombre de clase de Excepción puede reflejar la causa del error, por lo que solo necesitamos describirlo en una o dos oraciones.

Si se produce una excepción particular, lo más probable es que su nombre de clase ya describa el error. Por lo tanto, no es necesario que proporciones mucha información adicional. Un buen ejemplo es NumberFormatException. El constructor de la clase java.lang.Long lo generará cuando proporcione una cadena en un formato incorrecto.

1	try {
2	new Long("xyz");
3 } catch (NumberFormatException e) {
4	log.error(e);
5	}

5. Capte primero la excepción más específica

La mayoría de los IDE pueden ayudarle a implementar esta mejor práctica. Cuando intenta detectar excepciones menos específicas primero, informan de un bloque de código inalcanzable.

Pero el problema es que sólo se ejecutará el primer bloque catch que coincida con la excepción. Por lo tanto, si primero captura

IllegalArgumentException, el bloque catch que debería manejar la NumberFormatException más específica nunca se alcanza, porque es una subclase de IllegalArgumentException. Las clases de excepción concretas siempre se capturan primero y los bloques catch menos específicos se agregan al final de la lista. Puede ver un ejemplo de dicha declaración try-catch en el siguiente fragmento de código. El primer bloque catch maneja todas las excepciones NumberFormatException, el segundo maneja todas las excepciones

IllegalArgumentException para la excepción NumberFormatException.

1 public void catchMostSpecificExceptionFirst() { 
2  try {
3  doSomething("A message");
4	} catch (NumberFormatException e) {
5	log.error(e);
6	} catch (IllegalArgumentException e) {
7	log.error(e)
8	}
9	}

6. No coger clases Throwable

Throwable es la superclase de todas las excepciones y errores. Puedes usarlo en una cláusula catch, pero

¡Esto nunca debería hacerse!

Si se usa Throwable en la cláusula catch, detectará no solo todas las excepciones sino también todos los errores. La JVM arroja errores que indican problemas graves que la aplicación no debe manejar. Ejemplos típicos son OutOfMemoryError o StackOverflowError. Ambos son causados ​​por condiciones fuera del control de la aplicación y no pueden manejarse.

Por lo tanto, es mejor no detectar Throwable a menos que esté seguro de estar en una situación especial en la que pueda manejar errores.

1	public void doNotCatchThrowable() {
2	try {
3	// do something
4	} catch (Throwable t) {
5 // don't do this!
6	}
7	}

7. No ignores las excepciones

Muchas veces, los desarrolladores tienen mucha confianza en que no se generará ninguna excepción, por lo que escriben un bloque catch, pero no realizan ningún procesamiento ni registro.

1	public void doNotIgnoreExceptions() {
2	try {
3	// do something
4 } catch (NumberFormatException e) {
5	// this will never happen
6	}
7	}

Pero la realidad es que a menudo ocurren excepciones inesperadas, o es imposible determinar si el código aquí cambiará en el futuro (elimine el código que evita que se genere la excepción), y en este momento, debido a que se detecta la excepción, Es imposible obtener suficiente información sobre el error.Problema de posicionamiento. Es razonable al menos registrar la información de la excepción.

1	public void logAnException() {
2	try {
3	// do something
4 } catch (NumberFormatException e) {
5	log.error("This should never happen: " + e);
6	}
7	}

8. No registre ni arroje excepciones

Esta es probablemente una práctica recomendada que a menudo se pasa por alto en este artículo. Se puede encontrar que muchos códigos e incluso bibliotecas de clases tienen lógica para detectar excepciones, registrar registros y lanzarlos nuevamente. como sigue:

1	try {
2	new Long("xyz");
3 } catch (NumberFormatException e) {
4	log.error(e);
5	throw e;
6	}

Esta lógica de procesamiento parece razonable. Pero esto a menudo genera varios registros para la misma excepción. como sigue:

1 17:44:28,945 ERROR TestExceptionHandling:65 ‐ java.lang.NumberFormatExcep tion: For input string: "xyz" 
2 Exception in thread "main" java.lang.NumberFormatException: For input str ing: "xyz" 
3 at java.lang.NumberFormatException.forInputString(NumberFormatException.j ava:65)
4 at java.lang.Long.parseLong(Long.java:589) 
5 at java.lang.Long.(Long.java:965) 
6 at com.stackify.example.TestExceptionHandling.logAndThrowException(TestEx ceptionHandling.java:63) 
7 at com.stackify.example.TestExceptionHandling.main(TestExceptionHandling.java:5
8)

Como se muestra arriba, no hay más información útil adjunta a los registros posteriores. Si desea proporcionar más información útil, puede ajustar la excepción como una excepción personalizada.

 public void wrapException(String input) throws MyBusinessException {
3	// do something
4	} catch (NumberFormatException e) {
5	throw new MyBusinessException("A message that describes the error.", e);
6	}
7	}

Por lo tanto, solo detecte la excepción cuando desee manejarla; de lo contrario, solo necesita declararla en la firma del método y dejar que la persona que llama la maneje.

9. No deseche la excepción original al envolverla.

Es una práctica común detectar excepciones estándar y envolverlas como excepciones personalizadas. De esta manera, se puede agregar información de excepción más específica y se puede realizar un manejo de excepciones específico.

Cuando haga esto, asegúrese de establecer la excepción original como causa (nota: consulte el código a continuación

La excepción original e en NumberFormatException e). La clase de excepción proporciona especial

Un método constructor que toma un Throwable como parámetro. De lo contrario, perderá el seguimiento de la pila y el mensaje de la excepción original, lo que dificultará el análisis del evento excepcional que provocó la excepción.

1 public void wrapException(String input) throws MyBusinessException {
2	try {
3	// do something
4 } catch (NumberFormatException e) {
5	throw new MyBusinessException("A message that describes the error.", e);
6	}
7	}
8

10. No utilice excepciones para controlar el flujo del programa.

No debe usar excepciones para controlar el proceso de ejecución de la aplicación. Por ejemplo, debe usar el manejo de excepciones cuando debe usar sentencias if para juicios condicionales. Este es un muy mal hábito y afectará seriamente el rendimiento de la aplicación.

11. Uso de excepciones estándar

No defina sus propias excepciones si puede resolver el problema utilizando las excepciones integradas. La API de Java proporciona cientos de tipos de excepciones para diferentes situaciones. En desarrollo, primero utilice las excepciones proporcionadas por la API de Java tanto como sea posible. Si las excepciones estándar no pueden cumplir con sus requisitos, cree sus propias excepciones personalizadas en este momento. Utilice excepciones estándar tanto como sea posible para ayudar a los nuevos desarrolladores a comprender el código del proyecto.

12. Las excepciones pueden afectar el rendimiento

El costo de rendimiento del manejo de excepciones es muy alto y todo programador de Java debe tener en cuenta esta frase al desarrollar. La creación de una excepción es muy lenta y su lanzamiento consumirá entre 1 y 5 ms. Cuando se pasa una excepción entre varias capas de la aplicación, reducirá el rendimiento de toda la aplicación.

  • Utilice excepciones sólo en circunstancias excepcionales;
  • Utilice excepciones en excepciones recuperables; aunque el uso de excepciones es beneficioso para el desarrollo de Java, es mejor no capturar demasiadas pilas de llamadas en la aplicación, porque en muchos casos no es necesario imprimir la pila de llamadas para saber qué salió mal. Por lo tanto, los mensajes de excepción deben proporcionar la cantidad justa de información.

13. Resumen

En resumen, cuando se lanza o detecta una excepción, hay muchas situaciones diferentes a considerar y la mayoría de ellas tienen como objetivo mejorar la legibilidad del código o la usabilidad de la API.

Las excepciones no son sólo un mecanismo de control de errores, sino también un medio de comunicación. Por lo tanto, para cooperar mejor con los colegas, un equipo debe desarrollar un conjunto de mejores prácticas y reglas, solo así los miembros del equipo podrán comprender estos conceptos comunes y utilizarlos en su trabajo.

Manejo de excepciones: manual de desarrollo de Java de Alibaba

  1. [Obligatorio] Aquellos definidos en la biblioteca de clases de Java que se pueden eludir mediante una verificación previa

RuntimeException no debe ser manejada por catch, por ejemplo:

NullPointerException, IndexOutOfBoundsException, etc. Nota: Excepto en el caso de excepciones que no pueden pasar la verificación previa, por ejemplo, al analizar un número en forma de cadena, puede haber un error de formato de número, que debe implementarse detectando NumberFormatException. Ejemplo positivo: if (obj != null) {...} Ejemplo negativo: try { obj.method(); } catch

(NullPointerException e) {…}

  1. [Obligatorio] Las anomalías no deben utilizarse para el control de procesos o el control condicional. Explicación: La intención original del diseño de excepciones es resolver diversas situaciones inesperadas durante la operación del programa, y ​​la eficiencia del procesamiento de las excepciones es mucho menor que la del juicio condicional.

  2. [Obligatorio] Al detectar, distinga entre código estable y código inestable. El código estable se refiere al código que no saldrá mal de todos modos. Para detectar código inestable, distinga el tipo de excepción tanto como sea posible.

Luego haga el manejo de excepciones correspondiente. Explicación: Try-catch una gran porción de código, de modo que el programa no puede dar una respuesta de estrés correcta de acuerdo con diferentes excepciones, y no es propicio para localizar el problema, lo cual es una actuación irresponsable. Ejemplo positivo: en el escenario de registro de usuario, si el usuario ingresa caracteres ilegales, o el nombre de usuario ya existe, o el usuario ingresa la contraseña con demasiada facilidad, el programa realizará un juicio de clasificación y avisará al usuario.

  1. [Obligatorio] Detectar una excepción es manejarla, no la detecte, pero deséchela sin procesar nada; si no desea manejarla, envíe la excepción a la persona que la llama. Los usuarios comerciales en la capa externa deben manejar las excepciones y convertirlas en contenido que los usuarios puedan entender.

  2. [Obligatorio] Se coloca un bloque de prueba en el código de transacción. Después de la excepción de captura, si necesita revertir la transacción, debe prestar atención para revertir la transacción manualmente.

  3. [Obligatorio] El bloque finalmente debe cerrar el objeto de recurso y el objeto de transmisión, y tratar de capturar si hay una excepción. Nota: Si es JDK7 y superior, puede utilizar el método de prueba con recursos.

  4. [Obligatorio] No utilice return en el bloque finalmente. Explicación: Después de que la declaración de retorno en el bloque try se ejecuta con éxito, no regresa inmediatamente, pero continúa ejecutando la declaración en el bloque finalmente. Si hay una declaración de retorno aquí, regresa directamente aquí y el punto de retorno en el El bloque try se descarta sin piedad. Ejemplo de contador:

1	private int x = 0;
2	public int checkReturn() {
3	try {
4	// x等于1,此处不返回
5	return ++x;
6	} finally {
7	// 返回的结果是2
8	return ++x;
9	}
10	}
  1. [Obligatorio] Las excepciones de captura y las excepciones de lanzamiento deben coincidir exactamente, o las excepciones de captura deben ser la clase principal de las excepciones de lanzamiento. Explicación: Si se espera que el oponente lance una hortensia pero en realidad recibe un lanzamiento de peso, ocurrirá un accidente.

  2. [Obligatorio] Al llamar a RPC, paquetes de terceros o métodos relacionados de clases generadas dinámicamente, debe utilizar la clase Throwable para interceptar excepciones. Descripción: Llame al método a través del mecanismo de reflexión. Si no se puede encontrar el método, se lanzará NoSuchMethodException. ¿Qué condición arrojará?

¿Qué pasa con NoSuchMethodError? Cuando el paquete de dos partes entra en conflicto en la clase, el mecanismo de arbitraje puede provocar la introducción de una versión inesperada que hace que la firma del método de la clase no coincida, o en el marco de modificación del código de bytes (como:

Cuando ASM) crea o modifica dinámicamente una clase, se modifica la firma del método correspondiente. En estos casos, incluso si el código es correcto durante la compilación, se generará NoSuchMethodError cuando se ejecute el código.

  1. [Recomendación] El valor de retorno del método puede ser nulo y no es obligatorio devolver una colección vacía o un objeto vacío. Se deben agregar notas para explicar completamente bajo qué circunstancias se devolverá un valor nulo. Nota: Este manual deja claro que prevenir NPE es responsabilidad de la persona que llama. Incluso si el método llamado devuelve una colección vacía o un objeto vacío, no es una tranquilidad para la persona que llama y debe considerar la situación en la que la llamada remota falla, la serialización falla, las excepciones de tiempo de ejecución y otros escenarios devuelven nulo.

  2. [Recomendación] Prevenir NPE es el cultivo básico de los programadores. Preste atención a los escenarios donde ocurre NPE: 1) El tipo de retorno es un tipo de datos básico. Al devolver un objeto de un tipo de datos empaquetado, el unboxing automático puede generar NPE. Contraejemplo: public int f() {devolver objeto entero}, si es nulo, se desempaquetará automáticamente y arrojará NPE. 2) El resultado de la consulta de la base de datos puede ser nulo. 3) Incluso si los elementos del conjunto no están vacíos, los elementos de datos recuperados pueden ser nulos. 4) Cuando la llamada remota devuelve un objeto, se requiere un juicio de puntero nulo para evitar NPE. 5) Para los datos obtenidos en la Sesión, se recomienda realizar comprobaciones de NPE para evitar punteros nulos. 6) llamadas en cascada

obj.getA().getB().getC(); Una serie de llamadas pueden generar fácilmente NPE.

Ejemplo positivo: utilice la clase opcional de JDK8 para evitar problemas de NPE.

  1. [Recomendación] Distinga las excepciones no marcadas/marcadas al definir y evite lanzar nuevas directamente

RuntimeException(), sin mencionar el lanzamiento de Exception o Throwable, debe usar excepciones personalizadas con significado comercial. Recomendar excepciones personalizadas que se hayan definido en la industria, como por ejemplo:

DAOException / ServiceException等。

  1. [Referencia] El "código de error" debe usarse para la interfaz abierta http/api fuera de la empresa; se recomienda lanzar una excepción dentro de la aplicación; se le da prioridad a la llamada RPC entre aplicaciones para usar el método Result, que encapsula el Método isSuccess(), "código de error", "mensaje corto de error". Explicación: Las razones para usar el método Result como método de retorno del método RPC: 1) Si se usa el método de retorno para generar una excepción, si la persona que llama no la detecta, se producirá un error de tiempo de ejecución. 2) Si no agrega información de la pila, solo nuevas excepciones personalizadas y agrega su propia comprensión del mensaje de error, no ayudará demasiado a la persona que llama a resolver el problema. Si se agrega información de la pila, en el caso de errores de llamadas frecuentes, la pérdida de rendimiento de la serialización y transmisión de datos también es un problema.

  2. [Referencia] Evite el código repetido (No se repita), es decir, el principio DRY. Nota: Copiar y pegar el código a voluntad conducirá inevitablemente a la duplicación del código. Cuando necesite modificarlo en el futuro, deberá modificar todas las copias, lo cual es fácil de pasar por alto. Extraiga métodos comunes cuando sea necesario, o clases públicas abstractas, o incluso componentes. Ejemplo positivo: hay varios métodos públicos en una clase, todos los cuales necesitan realizar varias filas de la misma operación de verificación de parámetros. En este momento, extraiga: checkParam booleano privado (DTO dto) {…}

Cuando una llamada a un procedimiento devuelve un objeto, se requiere un juicio de puntero nulo para evitar NPE. 5) Para los datos obtenidos en la Sesión, se recomienda realizar comprobaciones de NPE para evitar punteros nulos. 6) llamadas en cascada

obj.getA().getB().getC(); Una serie de llamadas pueden generar fácilmente NPE.

Ejemplo positivo: utilice la clase opcional de JDK8 para evitar problemas de NPE.

  1. [Recomendación] Distinga las excepciones no marcadas/marcadas al definir y evite lanzar nuevas directamente

RuntimeException(), sin mencionar el lanzamiento de Exception o Throwable, debe usar excepciones personalizadas con significado comercial. Recomendar excepciones personalizadas que se hayan definido en la industria, como por ejemplo:

DAOException / ServiceException等。

  1. [Referencia] El "código de error" debe usarse para la interfaz abierta http/api fuera de la empresa; se recomienda lanzar una excepción dentro de la aplicación; se le da prioridad a la llamada RPC entre aplicaciones para usar el método Result, que encapsula el Método isSuccess(), "código de error", "mensaje corto de error". Explicación: Las razones para usar el método Result como método de retorno del método RPC: 1) Si se usa el método de retorno para generar una excepción, si la persona que llama no la detecta, se producirá un error de tiempo de ejecución. 2) Si no agrega información de la pila, solo nuevas excepciones personalizadas y agrega su propia comprensión del mensaje de error, no ayudará demasiado a la persona que llama a resolver el problema. Si se agrega información de la pila, en el caso de errores de llamadas frecuentes, la pérdida de rendimiento de la serialización y transmisión de datos también es un problema.

  2. [Referencia] Evite el código repetido (No se repita), es decir, el principio DRY. Nota: Copiar y pegar el código a voluntad conducirá inevitablemente a la duplicación del código. Cuando necesite modificarlo en el futuro, deberá modificar todas las copias, lo cual es fácil de pasar por alto. Extraiga métodos comunes cuando sea necesario, o clases públicas abstractas, o incluso componentes. Ejemplo positivo: hay varios métodos públicos en una clase, todos los cuales necesitan realizar varias filas de la misma operación de verificación de parámetros. En este momento, extraiga: checkParam booleano privado (DTO dto) {…}

Supongo que te gusta

Origin blog.csdn.net/leader_song/article/details/132391085
Recomendado
Clasificación