在之前关于Java异常的文章中,已经探讨过suppressed exceptions和Java Exceptions TutorialJava Exceptions Tutorial 两个方面的内容。要想在实际项目中正确处理Java异常,你应该熟练掌握一些Java异常处理的最佳实践。
Java 异常处理的最佳实践
public class ExceptionExample {
public FileInputStream testMethod1(){
File file = new File("test.txt");
FileInputStream fileInputStream = null;
try{
fileInputStream = new FileInputStream(file);
fileInputStream.read();
}catch (IOException e){
return null;
}
return fileInputStream;
}
public static void main(String[] args){
ExceptionExample instance1 = new ExceptionExample();
instance1.testMethod1();
}
}
在异常处理时进行异常压制是非常不好的编程习惯,上面的例子中,无论抛出什么异常都会被忽略,以至没有留下任何问题线索。如果在这一层次不知道如何处理异常,最好将异常重新抛出,由上层决定如何处理异常。
public class ExceptionExample {
public FileInputStream testMethod1() throws IOException{
File file = new File("test.txt");
FileInputStream fileInputStream = null;
try{
fileInputStream = new FileInputStream(file);
fileInputStream.read();
}catch (IOException e){
throw e;
}
return fileInputStream;
}
public static void main(String[] args) throws IOException{
ExceptionExample instance1 = new ExceptionExample();
instance1.testMethod1();
}
}
public FileInputStream testMethod1() throws Exception{
这种写法,表示该方法会抛出所有受检查异常,这不是一个良好的编程习惯。在这种情况下,我们最好抛出足够具体的异常,以便调用者进行合适的捕获和处理,例如public FileInputStream testMethod1() throws IOException{
。try {
//some statements
catch(FileNotFoundException e){
//handle here
}
catch(IOException e){
//handle here
}
你最好不要这么写:
try {
//some statements
catch(Exception e){
//handle here
}
try(open the resources) {deal with resources}
语句,如果你还是习惯这种老式写法,则可以按照如下方式写:finally {
try {
if (con != null) {
con.close();
}
if (stat != null) {
stat.close();
}
} catch (SQLException sqlee) {
sqlee.printStackTrace();
}
}
Performance 异常处理的性能成本非常高,每个Java程序员在开发时都应牢记这句话。创建一个异常非常慢,抛出一个异常又会消耗1~5ms,当一个异常在应用的多个层级之间传递时,会拖累整个应用的性能。
尽管使用异常有利于Java开发,但是在应用中最好不要捕获太多的调用栈,因为在很多情况下都不需要打印调用栈就知道哪里出错了。因此,异常消息应该提供恰到好处的信息。
import java.io.IOException;
public class HelloWorld{
public static void main(String []args) throws Exception{
try{
throw new IOException("IOException");
}catch (IOException e){
throw new ExampleException1("Example Exception and " + e.getMessage());
}
}
}
class ExampleException1 extends Exception{
public ExampleException1(String s, Throwable t){
super(s,t);
}
public ExampleException1(String s){
super(s);
}
}
这个程序的输出为:
Exception in thread "main" ExampleException1: Example Exception and IOException
at HelloWorld.main(HelloWorld.java:8)
这里发现,IOException的调用栈已经丢失了,因为我们在catch语句块中没有正确包装IOException。若将catch语句块修改成下面这样,这可以发现原始异常的调用栈也被打印出来了。
catch (IOException e){
throw new ExampleException1("Example Exception",e);
}
这时候的输出如下:
Exception in thread "main" ExampleException1: Example Exception
at HelloWorld.main(HelloWorld.java:8)
Caused by: java.io.IOException: IOException
at HelloWorld.main(HelloWorld.java:6)
try {
method(); //here throws first exception
} finally {
shutdown(); //If finally blockthrew any exception the first exception will be lost forever
}
在上面的这个代码片段中,finally代码块也可能再次抛出异常。如果同时抛出两个异常,则第一个异常的调用栈会丢失。在finally语句块中最好只做打印错误信息或者关闭资源等操作,避免在finally语句块中再次抛出异常。
扫码关注腾讯云开发者
领取腾讯云代金券
Copyright © 2013 - 2025 Tencent Cloud. All Rights Reserved. 腾讯云 版权所有
深圳市腾讯计算机系统有限公司 ICP备案/许可证号:粤B2-20090059 深公网安备号 44030502008569
腾讯云计算(北京)有限责任公司 京ICP证150476号 | 京ICP备11018762号 | 京公网安备号11010802020287
Copyright © 2013 - 2025 Tencent Cloud.
All Rights Reserved. 腾讯云 版权所有