异常概念
如果某个方法出错会抛出一个封装了错误信息的对象。此时,这个方法会立刻退出同时不返回任何值。另外,调用
这个方法的其他代码也无法继续执行,异常处理机制会将代码执行交给异常处理器。
简单来说,异常是Java传达给你的系统和程序错误的方式。
异常分类
Throwable 是 Java 语言中所有错误或异常的超类。下一层分为 Error 和 Exception
Error
Error 类是指 java 运行时系统的内部错误和资源耗尽错误。应用程序不会抛出该类对象。如果
出现了这样的错误,除了告知用户,剩下的就是尽力使程序安全的终止。
Exception
Exception 又 有分为编译时异常和运行时异常 (RuntimeException和CheckedException)
检查异常:一般是外部错误,这种异常都发生在编译阶段,Java 编译器会强制程序去捕获此类异常,即会出现要求你把这 段可能出现异常的程序进行 try catch,该类异常一 般包括几个方面
1. 试图在文件尾部读取数据
2. 试图打开一个错误格式的 URL
3. 试图根据给定的字符串查找 class 对象,而这个字符串表示的类并不存在
异常的处理方式
遇到问题不进行具体处理,而是继续抛给调用者 ( throw,throws ) try catch 捕获异常针对性处理方式
public static void main(String[] args) {
String s = "abc";
if(s.equals("abc")) {
throw new NumberFormatException();
} else {
System.out.println(s);
}
}
int div(int a,int b) throws Exception{
return a/b;}
Throw 和 throws 的区别:
位置不同:throws 用在函数上,后面跟的是异常类,可以跟多个;而 throw 用在函数内,后面跟的
是异常对象。
功能不同:
- throws 用来声明异常,让调用者只知道该功能可能出现的问题,可以给出预先的处理方
式;throw抛出具体的问题对象,执行到throw,功能就已经结束了,跳转到调用者,并
将具体的问题对象抛给调用者。也就是说 throw 语句独立存在时,下面不要定义其他语
句,因为执行不到 - throws 表示出现异常的一种可能性,并不一定会发生这些异常;throw 则是抛出了异常,
执行 throw 则一定抛出了某种异常对象。 - 两者都是消极处理异常的方式,只是抛出或者可能抛出异常,但是不会由函数去处理异
常,真正的处理异常由函数的上层调用处理。
Java异常类有哪些的重要方法?
答:
- String getMessage():方法返回Throwable的String型信息,当异常通过构造器创建后可用。
- String getLocalizedMessage():此方法通过被重写来得到用本地语言表示的异常信息返回给调用程序。Throwable类通常只是用getMessage()方法来实现返回异常信息。
- synchronized Throwable getCause():此方法返回异常产生的原因,如果不知道原因的话返回null。(原文有拼写错误 应该是if 不是id)
- String toString():方法返回String格式的Throwable信息,此信息包括Throwable的名字和本地化信息。
- void printStackTrace():该方法打印栈轨迹信息到标准错误流。该方法能接受PrintStream 和PrintWriter作为参数实现重载,这样就能实现打印栈轨迹到文件或流中。
java 中如何编写自定义异常?
public class DemoException extends IOException {
private static final long serialVersionUID = 123456789L;
private String errorCode="DemoException";
public DemoException(String msg, String errorCode){
super(msg);
this.errorCode = errorCode;
}
public String getErrorCode(){
return this.errorCode;
}
}
关于 java 中的异常处理你有啥心得或者经验?
答:
-
方法返回值尽量不要使用 null(特殊场景除外),这样可以避免很多 NullPointerException 异常。
-
catch 住了如果真的没必要处理则至少加行打印,这样可在将来方便排查问题。
-
接口方法抛出的异常尽量保证是运行时异常类型,除非迫不得已才抛出检查类型异常。
-
避免在 finally 中使用 return 语句或者抛出异常,如果调用的其他代码可能抛出异常则应该捕获异常并进行处理,因为 finally 中 return 不仅会覆盖 try 和 catch 内的返回值且还会掩盖 try 和 catch 内的异常,就像异常没有发生一样(特别注意,当 try-finally 中没有 return 时该方法运行会继续抛出异常)。
-
尽量不要在 catch 块中压制异常(即什么也不处理直接 return),因为这样以后无论抛出什么异常都会被忽略,以至没有留下任何问题线索,如果在这一层不知道如何处理异常最好将异常重新抛出由上层决定如何处理异常。
-
方法定义中 throws 后面尽量定义具体的异常列表,不要直接 throws Exception。
-
捕获异常时尽量捕获具体的异常类型而不要直接捕获其父类,这样容易造成混乱。
-
避免在 finally 块中抛出异常,不然第一个异常的调用栈会丢失。
-
不要使用异常控制程序的流程,譬如本应该使用 if 语句进行条件判断的情况下却使用异常处理是非常不好的习惯,会严重影响性能。
-
不要直接捕获 Throwable 类,因为 Error 是 Throwable 类的子类,当应用抛出 Errors 的时候一般都是不可恢复的情况。
java 中 finally 块一定会执行吗?
答:
不一定,分情况。因为首先想要执行 finally 块的前提是必须执行到了 try 块,当在 try 块或者 catch 块中有 System.exit(0); 这样的语句存在时 finally 块就不会被执行到了,因为程序被结束了。此外当在 try 块或者 catch 块里 return 时 finally 会被执行;而且 finally 块里 return 语句会把 try 块或者 catch 块里的 return 语句效果给覆盖掉且吞掉了异常。