java中关于资源的使用大家估计都不陌生,无非就是请求资源,建立连接,读取资源,关闭资源几个步骤,为了保证资源能够顺利释放,都是在finally块中进行资源释放,下面常见的资源访问实例:
public static void main(String[] args) {
FileInputStream fis = null;
try {
fis = new FileInputStream("");
} catch (FileNotFoundException e) {
e.printStackTrace();
} finally {
try {
if(fis != null)
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
上面的代码 ,简单的功能需要的代码长且不说,而且不够优雅,在同时有输入流输出流的情况,将会更加复杂,异常处理难度令人抓狂。
现在我们可以摆脱这种现状了,java7新语法,提供自动关闭资源的方式,如下
public static void main(String[] args) {
try (FileInputStream fis = new FileInputStream("");) {
fis.read();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
仔细看,资源的连接是在try()中,这种新语法支持,凡是实现接口AutoCloseable的类都可以使用这种方式进行资源访问,并且会自动释放。
下面,我们仔细分析下,为什么资源会自动释放,我们看下面这段,是新 方式代码javap后的汇编,我简单的注释下:
public static void main(java.lang.String[]);
Code:
0: aconst_null
1: astore_1
2: aconst_null
3: astore_2
4: new #16 // class java/io/FileInputStream
7: dup
8: ldc #18 // String
10: invokespecial #20 // Method java/io/FileInputStream."<init>":(Ljava/lang/String;)V
13: astore_3 //将实例化的FileInputStream对象引入保存到局部变量3中
14: aload_3 //FileInputStream引用入栈
15: invokevirtual #23 // Method java/io/FileInputStream.read:()I
18: pop
19: aload_3
20: ifnull 76 //资源为空,则表示没有开启资源,也成功返回
23: aload_3 //如果保存FileInputStream对象引用的变量不为空则关闭资源
24: invokevirtual #27 // Method java/io/FileInputStream.close:()V
27: goto 76 //成功返回
30: astore_1 //既然上面代码就能保证成功返回,此处开始的代码就是异常处理了
31: aload_3
32: ifnull 39
35: aload_3
36: invokevirtual #27 // Method java/io/FileInputStream.close:()V
39: aload_1
40: athrow
41: astore_2
42: aload_1
43: ifnonnull 51
46: aload_2
47: astore_1
48: goto 61
51: aload_1
52: aload_2
53: if_acmpeq 61
56: aload_1
57: aload_2
58: invokevirtual #30 // Method java/lang/Throwable.addSuppressed:(Ljava/lang/Throwable;)V
61: aload_1
62: athrow
63: astore_1
64: aload_1
65: invokevirtual #36 // Method java/io/FileNotFoundException.printStackTrace:()V
68: goto 76
71: astore_1
72: aload_1
73: invokevirtual #41 // Method java/io/IOException.printStackTrace:()V
76: return
Exception table: //这是java异常处理的机制,维护异常表,根据表来查询异常后的跳转代码。
from to target type
14 19 30 any //当资源读时异常,跳到30处(内存偏移量)继续执行,可以看到是资源关闭的处理。
4 41 41 any
0 63 63 Class java/io/FileNotFoundException
0 63 71 Class java/io/IOException
分析后发现,新的语法其实就是一种编译器优化,资源总会关闭,不管是否发生异常。人通常会犯错,但是编译器却不会,所以使用新的方式进行资源访问,能够避免隐藏的bug,而在java7中绝大多数的资源访问都已经重新实现了AutoCloseable接口,包括网络访问socket等,所以基本上可以放心的使用,就算没实现,编译器也会快速报错。