欢迎访问 生活随笔!

凯发k8官方网

当前位置: 凯发k8官方网 > 编程资源 > 编程问答 >内容正文

编程问答

eval a string with null-凯发k8官方网

发布时间:2024/10/14 编程问答 4 豆豆
凯发k8官方网 收集整理的这篇文章主要介绍了 eval a string with null_try-with-resources--java成长之路 小编觉得挺不错的,现在分享给大家,帮大家做个参考.

jdk1.7之后,引入了try-with-resources,使得关闭资源操作无需层层嵌套在finally中,代码简洁不少,本质是一个语法糖,能够使用try-with-resources关闭资源的类,必须实现autocloseable接口。

  1.7版本之前,传统的关闭资源操作如下:

public static void main(string[] args){

    fileinputstream fileinputstream = null;    try {        fileinputstream = new fileinputstream("file.txt");        fileinputstream.read();    } catch (ioexception e) {        e.printstacktrace();    }finally {        try {            assert fileinputstream != null;            fileinputstream.close();        } catch (ioexception e) {            e.printstacktrace();        }    }}

  可以看到,为了确保资源关闭正常,需要finall中再嵌入finally,try中打开资源越多,finall嵌套越深,可能会导致关闭资源的代码比业务代码还要多。

  但是使用了try-with-resources语法后,上面的例子可改写为:

try(fileinputstream fileinputstream1 = new fileinputstream("file.txt")){    fileinputstream1.read();} catch (ioexception e) {    e.printstacktrace();}

  如何判读资源是否真的被关闭了呢,我们手写个demo:

  实现autocloseable的资源类

class myresource implements autocloseable{    public void open(){        system.out.println("resource is open!");    }    @override    public void close() throws exception {        system.out.println("resource is close!");    }}

  调用方:

public static void main(string[] args){    try(myresource myresource = new myresource()){        myresource.open();    } catch (exception e) {        e.printstacktrace();    }}

  输出如下,可以看到close方法被自动调用了,

resource is open!resource is close!

  底层原理是什么呢,看一下编译后的class文件:

try {        myresource myresource = new myresource();        throwable var2 = null;        try {            myresource.open();        } catch (throwable var12) {            var2 = var12;            throw var12;        } finally {            if (myresource != null) {                if (var2 != null) {                    try {                        myresource.close();                    } catch (throwable var11) {                        var2.addsuppressed(var11);                    }                } else {                    myresource.close();                }            }        }    } catch (exception var14) {        var14.printstacktrace();    }}

  很明显,编译器生成了finally代码块,并在其中调用了close 方法,同1.7之前的关闭资源操作的实现原理是相同的,但是可以看到,这里多调用了一个addsuppressed方法,这么做其实是为了处理异常屏蔽,什么是异常屏蔽,首先,我们先修改一下刚刚的demo,使资源类在open和close方法中抛出异常,并且使用1.7之前的关闭资源的方法,资源类以及调用方代码修改如下:

public void open() throws ioexception {    system.out.println("resource is open!");    throw new ioexception("open() exception!");}@overridepublic void close() throws exception {    system.out.println("resource is close!");    throw new ioexception("close()  exception!");}public static void main(string[] args) throws exception {    myresource myresource = null;    try{        myresource = new myresource();        myresource.open();    }finally {        try {            myresource.close();        } catch (exception e) {            e.printstacktrace();        }    }}

  控制台打印如下:

  open方法抛出的异常被自动忽略了,而异常信息丢失将导致程序调试困难,所以try-with-resources语法中加入了addsuppressed处理异常屏蔽,现在修改demo为使用try-with-resource关闭资源,调用方代码如下:

public static void main(string[] args) throws exception {    try(myresource myresource = new myresource()){        myresource.open();    }

  控制台打印如下

  异常信息中多了提示:close方法中抛出的异常被open方法中抛出的异常抑制了。

  其他问题:使用try-catch-resources,并不能完全保证资源被关闭,在javabio中,使用了大量的装饰器模式,调用装饰类的close方法时实际是在调用其中包裹的流的close方法,但是在调用包裹的流的close方法时,装饰类还做了一些其他的操作,如果这些操作出现异常,将导致包裹流的close方法被跳过,资源没有被正确关闭,正确的方式是在try中单独声明底层资源类以及装饰类,这样就可以保证,每个类的close方法都被调用。

总结

以上是凯发k8官方网为你收集整理的eval a string with null_try-with-resources--java成长之路的全部内容,希望文章能够帮你解决所遇到的问题。

如果觉得凯发k8官方网网站内容还不错,欢迎将凯发k8官方网推荐给好友。

  • 上一篇:
  • 下一篇:
网站地图