excepción java
En el proceso de ejecutar un programa de computadora, siempre ocurrirán varios errores.
Hay algunos errores cometidos por el usuario, por ejemplo, se espera que el usuario ingrese un int
tipo de edad, pero la entrada del usuario es abc
:
// 假设用户输入了abc:
String s = "abc";
int n = Integer.parseInt(s); // NumberFormatException!
Un programa quiere leer y escribir el contenido de un archivo, pero el usuario lo ha eliminado:
// 用户删除了该文件:
String t = readFile("C:\\abc.txt"); // FileNotFoundException!
También hay algunos errores que aparecen aleatoriamente y nunca se pueden evitar. Por ejemplo:
La red se desconecta repentinamente y el servidor remoto no se puede conectar;
la memoria se agota y el programa falla;
el usuario hace clic en "imprimir", pero no hay ninguna impresora;
...
Por lo tanto, un programa robusto debe lidiar con varios errores.
El llamado error es cuando el programa llama a una función, si falla, significa un error.
¿Cómo conoce la persona que llama la información sobre la falla de la llamada? Hay dos métodos:
Método 1: accedió a devolver un código de error.
Por ejemplo, para procesar un archivo, si devuelve 0, significa éxito, y si devuelve otros enteros, significa el código de error acordado:
int code = processFile("C:\\test.txt");
if (code == 0) {
// ok:
} else {
// error:
switch (code) {
case 1:
// file not found:
case 2:
// no read permission:
default:
// unknown error:
}
}
Debido al tipo de código de error utilizado int
, es muy problemático manejarlo. Este enfoque es común en funciones C de bajo nivel.
Método 2: Proporcione un mecanismo de manejo de excepciones a nivel de lenguaje.
Java tiene un mecanismo de manejo de excepciones incorporado que siempre usa excepciones para indicar errores.
Exception es una clase, por lo que lleva información de tipo en sí misma. Las excepciones se pueden lanzar en cualquier lugar, pero solo se deben detectar en el nivel superior, de modo que se separen de las llamadas a métodos:
try {
String s = processFile(“C:\\test.txt”);
// ok:
} catch (FileNotFoundException e) {
// file not found:
} catch (SecurityException e) {
// no read permission:
} catch (IOException e) {
// io error:
} catch (Exception e) {
// other error:
}
Debido a que la excepción de Java es una clase, su relación de herencia es la siguiente:
Se puede ver a partir de la relación de herencia: Throwable
es la raíz del sistema anormal, del cual hereda Object
. Throwable
Hay dos sistemas: Error
y Exception
, Error
que representan errores graves, para los cuales el programa generalmente no puede hacer nada, por ejemplo:
- OutOfMemoryError: Sin memoria
- NoClassDefFoundError: no se puede cargar un
Class
- StackOverflowError: el desbordamiento de pila
Exception
es un error de tiempo de ejecución que se puede detectar y manejar.
Ciertas excepciones son parte del procesamiento de la lógica de la aplicación y deben detectarse y manejarse. Por ejemplo:
- NumberFormatException: formato incorrecto para el tipo numérico
- FileNotFoundException: archivo no encontrado
- SocketException: no se pudo leer la red
También hay algunas excepciones causadas por una lógica de programa incorrecta, y el propio programa debe repararse. Por ejemplo:
- NullPointerException: llamar a un método o campo en un objeto nulo
- IndexOutOfBoundsException: índice de matriz fuera de los límites
La excepción se divide en dos categorías:
- RuntimeException y sus subclases;
- Non-RuntimeException (incluyendo IOException, ReflectiveOperationException, etc.)
Java estipula:
Las excepciones que deben capturarse, incluyendo Exception
y excluyendo RuntimeException
sus subclases, se denominan excepciones de este tipo Checked Exception
.
Excepciones que no necesitan capturarse, incluidas Error
sus subclases RuntimeException
y sus subclases.
Nota: el compilador
RuntimeException
no establece requisitos de captura obligatorios para sus subclases, lo que no significa que la aplicación en sí no deba capturar y procesar archivosRuntimeException
. Si es necesario capturarlo depende del análisis específico de problemas específicos.
excepción de captura
Use declaraciones para capturar excepciones try...catch
, coloque el código que puede causar excepciones try {...}
y luego use catch
el catch correspondiente Exception
y sus subclases:
// try...catch
import java.io.UnsupportedEncodingException;
import java.util.Arrays;
public class Main {
public static void main(String[] args) {
byte[] bs = toGBK("中文");
System.out.println(Arrays.toString(bs));
}
static byte[] toGBK(String s) {
try {
// 用指定编码转换String为byte[]:
return s.getBytes("GBK");
} catch (UnsupportedEncodingException e) {
// 如果系统不支持GBK编码,会捕获到UnsupportedEncodingException:
System.out.println(e); // 打印异常信息
return s.getBytes(); // 尝试使用用默认编码
}
}
}
Si no lo detectamos UnsupportedEncodingException
, habrá un problema de falla de compilación:
// try...catch
import java.io.UnsupportedEncodingException;
import java.util.Arrays;
public class Main {
public static void main(String[] args) {
byte[] bs = toGBK("中文");
System.out.println(Arrays.toString(bs));
}
static byte[] toGBK(String s) {
return s.getBytes("GBK");
}
}
El compilador reportará un error, el mensaje de error es similar a: unreported exception UnsupportedEncodingException; must be caught or declared to be thrown
, y precisamente se señala que la sentencia que hay que capturar es return s.getBytes("GBK")
;. Es decir, UnsupportedEncodingException
así Checked Exception
, tiene que ser atrapado.
Esto se debe a que la definición del método String.getBytes(String) es:
public byte[] getBytes(String charsetName) throws UnsupportedEncodingException {
...
}
Cuando se define el método, utilice throws Xxx para indicar el tipo de excepción que puede generar el método. Al llamar, la persona que llama debe detectar estas excepciones a la fuerza, de lo contrario, el compilador informará un error.
En el método toGBK(), debido a que String.getBytes(String)
se llama al método, debe capturarse UnsupportedEncodingException
. Tampoco podemos capturarlo, pero usarlo en la definición del método para throws
indicar que toGBK()
el método puede arrojar UnsupportedEncodingExceptio
n, de modo que toGBK()
el método pueda pasar la verificación del compilador:
// try...catch
import java.io.UnsupportedEncodingException;
import java.util.Arrays;
public class Main {
public static void main(String[] args) {
byte[] bs = toGBK("中文");
System.out.println(Arrays.toString(bs));
}
static byte[] toGBK(String s) throws UnsupportedEncodingException {
return s.getBytes("GBK");
}
}
El código anterior aún obtendrá errores de compilación, pero esta vez, el compilador no genera return s.getBytes("GBK");
el problema de llamar, sino byte[] bs = toGBK("中文");
. Porque en el método main(), la llamada toGBK()
no captura lo que declara que puede arrojar UnsupportedEncodingException
.
La solución es capturar la excepción y manejarla en el método main():
// try...catch
import java.io.UnsupportedEncodingException;
import java.util.Arrays;
public class Main {
public static void main(String[] args) {
try {
byte[] bs = toGBK("中文");
System.out.println(Arrays.toString(bs));
} catch (UnsupportedEncodingException e) {
System.out.println(e);
}
}
static byte[] toGBK(String s) throws UnsupportedEncodingException {
// 用指定编码转换String为byte[]:
return s.getBytes("GBK");
}
}
Se puede ver que siempre que sea declarado por un método Checked Exception
, debe capturarse en un nivel de llamada superior si no se captura en el nivel de llamada. Todas las excepciones no capturadas deben eventualmente main()
ser capturadas en el método, y no habrá omisión de intento. Esto está garantizado por el compilador. main()
El método es también la última Exception
oportunidad de atrapar.
Si es un código de prueba, el método de escritura anterior es un poco problemático. Si no desea escribir ningún código de prueba, puede main()
definir directamente el método como throws Exception
:
// try...catch
import java.io.UnsupportedEncodingException;
import java.util.Arrays;
public class Main {
public static void main(String[] args) throws Exception {
byte[] bs = toGBK("中文");
System.out.println(Arrays.toString(bs));
}
static byte[] toGBK(String s) throws UnsupportedEncodingException {
// 用指定编码转换String为byte[]:
return s.getBytes("GBK");
}
}
Debido a que main()
el método declara que puede arrojar Exception
, también declara que puede arrojar todo Exception
, por lo que no es necesario capturarlo internamente. El precio es que una vez que ocurre una excepción, el programa saldrá inmediatamente.
También hay algunos zapatos para niños a los que les gusta toGBK()
"digerir" las anomalías internamente:
static byte[] toGBK(String s) {
try {
return s.getBytes("GBK");
} catch (UnsupportedEncodingException e) {
// 什么也不干
}
return null;
```
这种捕获后不处理的方式是非常不好的,即使真的什么也做不了,也要先把异常记录下来:
```java
static byte[] toGBK(String s) {
try {
return s.getBytes("GBK");
} catch (UnsupportedEncodingException e) {
// 先记下来再说:
e.printStackTrace();
}
return null;
Todas las excepciones pueden llamar printStackTrace()
al método para imprimir la pila de excepciones, que es un método simple y útil para imprimir excepciones rápidamente.
resumen
Java usa excepciones para indicar errores y al try ... catch
capturar excepciones;
Las excepciones de Java son de clase y Throwable
se heredan de;
Error
es un error grave que no necesita detectarse Exception
y es un error manejable que debe detectarse;
RuntimeException
No hay captura obligatoria, RuntimeException(Checked Exception)
captura obligatoria o declaración de lanzamiento;
No se recomienda capturar una excepción pero no hacer nada.