您的位置:首页 > 职场人生

疯狂Java程序员16堂课---第8课:异常捕捉的陷

2015-11-12 16:03 435 查看
第8课:异常捕捉的陷阱

这本书的每一章节的引言总能引人入胜,我喜欢这种情景引出问题来~

其实就是

问:当系统执行到catch 块代码中有return 时,系统是否还会执行对应的finally 块。

答:依然会执行finally 块里的代码。

再问:catch 里面有System.exit(0) ,Runtime.getRuntime().exit(0);时呢?………….

8.1正确关闭资源的方式:

实际开发中,数据库的连接,网络连接,磁盘文件等物理资源必须显示关闭,否则会引起资源泄漏。

(原以为 JVM提供的垃圾回收机制会回收,其实不会,因为它只负责回收堆内存中分配出来的内存,至于打开的物理资源无能为力。)

对于打开的物理资源:用finally 正确回收

注意3点:

1、 保证finall 会被执行

2、 关闭前保证资源引用的变量不为null

3、 多个资源的关闭单独用 try…catch 关闭,避免互相影响关闭

事例:

Finally{
If( oos != null){
Try{
oos.close();
}catch(Exception e){
e.printStackTrace();
}
}
If( ois != null){
Try{
ois.close();
}catch(Exception e){
e.printStackTrace();
}
}

}


8.2 finally的陷阱(为了保证finally会被执行)

1、try中 有 System.exit(0);不会执行

public class ExitFinally
{
public static void main(String[] args)
throws IOException
{
FileOutputStream fos = null;
try
{
fos = new FileOutputStream("a.bin");
System.out.println("程序打开物理资源!");
System.exit(0);
}
finally
{
//使用finally块关闭资源
if (fos != null)
{
try
{
fos.close();
}
catch (Exception ex)
{
ex.printStackTrace();
}
}
System.out.println("程序关闭了物理资源!");
}
}
}




2、try、catch中 有 return, finally 会执行。若finally中有return直接结束,否则返回try\catch中的return 结束.。

解释:执行到Try中的return时,并不会马上结束该方法,而是去寻找是否有finally 块。

public class FinallyFlowTest
{
public static void main(String[] args)
{
int a = test();
System.out.println(a);
}
public static int test()
{
int count = 5;
try
{
//因为finally块中包含了return语句,
//则下面的return语句不会立即返回
return count++;
}
finally
{
System.out.println("finally块被执行");
return count++;
}
}
}



3、 try、catch中抛出一个异常 , finally 会执行。

解释:类同2

public class FinallyFlowTest2
{
public static void main(String[] args)
{
int a = test();
System.out.println(a);
}
public static int test()
{
int count = 5;
try
{
//因为finally块中包含了return语句,
//则下面的return语句不会立即返回
throw new RuntimeException("测试异常");
}
finally
{
System.out.println("finally块被执行");
return count;
}
}
}



8.3 catch的用法

8.3.1 catch 块的顺序。

多个catch ,排在前面的优先获得执行机会,那么多个catch 块的排列顺序的要求呢?

1、 捕捉父类异常的catch 应该在 子类异常之后,否则编译错误。

(先捕捉小的,再大的,犹如if…else,先处理小的再大的一样)

public class CatchSequenceTest
{
public static void main(String[] args)
throws Exception
{
FileInputStream fis = null;
try
{
fis = new FileInputStream("a.bin");
fis.read();
}
//捕捉IOExcetion异常
catch (IOException ex)
{
ex.printStackTrace();
}
//捕捉FileNotFoundException异常
catch(FileNotFoundException fex)
{
fex.printStackTrace();
}
finally
{
//简单方式关闭资源
if (fis != null)
{
fis.close();
}
}
}
}



8.3.3 只能catch 可能抛出的异常

根据Java 语言规范,如果一个catch 子句试图捕获一个类型为XxxException 的Checked异常时,那么对应的try 块必须可能抛出XxxException 或及其子类的异常,否则编译错误。

首先贴上关于异常的种类的介绍:

通常,Java的异常(包括Exception和Error)分为可查的异常(checked
exceptions)和不可查的异常(unchecked exceptions)


可查异常(编译器要求必须处置的异常):正确的程序在运行中,很容易出现的、情理可容的异常状况。可查异常虽然是异常状况,但在一定程度上它的发生是可以预计的,而且一旦发生这种异常状况,就必须采取某种方式进行处理。

除了RuntimeException及其子类以外,其他的Exception类及其子类都属于可查异常。这种异常的特点是Java编译器会检查它,也就是说,当程序中可能出现这类异常,要么用try-catch语句捕获它,要么用throws子句声明抛出它,否则编译不会通过。

不可查异常(编译器不要求强制处置的异常):包括运行时异常(RuntimeException与其子类)和错误(Error)。

Exception 这种异常分两大类运行时异常和非运行时异常(编译异常)。程序中应当尽可能去处理这些异常。

运行时异常:都是RuntimeException类及其子类异常,如NullPointerException(空指针异常)、IndexOutOfBoundsException(下标越界异常)等,这些异常是不检查异常,程序中可以选择捕获处理,也可以不处理。这些异常一般是由程序逻辑错误引起的,程序应该从逻辑角度尽可能避免这类异常的发生。

运行时异常的特点是Java编译器不会检查它,也就是说,当程序中可能出现这类异常,即使没有用try-catch语句捕获它,也没有用throws子句声明抛出它,也会编译通过。

非运行时异常 (编译异常):是RuntimeException以外的异常,类型上都属于Exception类及其子类。从程序语法角度讲是必须进行处理的异常,如果不处理,程序就不能编译通过。如IOException、SQLException等以及用户自定义的Exception异常,一般情况下不自定义检查异常。(更多的/article/7644552.html)

代码解释:

IOException,ClassNotFoundException属于checked编译异常,代码中检测到
try中不可能抛出

而IndexOutOfBoundsException,NullPointerException属于RuntimeException的子类,属于运行时异常----只要愿意即可抛出

8.4继承得到的异常

Java 语言规定,子类重写父类方法时,子类方法只能声明抛出父类方法所声明抛出异常的子类。

//定义第一个接口
interface Type1
{
void test() throws ClassNotFoundException;
}
//定义第二个接口
interface Type2
{
void test() throws NoSuchMethodException;
}
//该Test类实现Type1、Type2两个接口
public class Test implements Type1, Type2
{
//实现Type1、Type2接口里声明的抽象方法
public void test()
throws ClassNotFoundException
{
System.out.println("www.crazyit.org");
}
public static void main(String[] args)
{
Test t = new Test();
t.test();
}
}


代码解释:

子类实现了两个接口,两个接口的异常交集为空,所以子类不能声明抛出任意一种接口里面的异常。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: