前几天看了一篇文章,自己试了一下,得出了一些不同的结论。我做了一个博客记录。本文主要研究两个问题:wrappedstream的close方法会自动关闭wrappedstream吗?是否有关闭流方法的命令?包装流的关闭方法是否自动关闭包装流?通常我们把输入流和输出流用buffer包裹起来,看看下面的代码(这段代码运行正常,不会报错)importjava.io.BufferedOutputStream;importjava.io.FileOutputStream;importjava.io.IO异常;公共类IOTest{publicstaticvoidmain(String[]args)throwsIOException{FileOutputStreamfileOutputStream=newFileOutputStream("c:\\a.txt");BufferedOutputStreambufferedOutputStream=newBufferedOutputStream(fileOutputStreamtest);wbuffer("某事".getBytes());bufferedOutputStream.flush();//从包装器流中关闭流bufferedOutputStream.close();}}让我们研究一下bufferedOutputStream.close();此代码的方法调用fileOutputStream.close();先看BufferedOutputStream的源码:publicclassBufferedOutputStreamextendsFilterOutputStream{...可以看到它继承了FilterOutputStream,并没有重写close方法,直接看FilterOutputStream的源代码:publicvoidclose()throwsIOException{try{flush();}catch(IOExceptionignored){}out.close();}trackout(inFilterOutputStream):protectedOutputStreamout;publicFilterOutputStream(OutputStreamout){this.out=out;}再看看BufferedOutputStream:if(size<=0){thrownewIllegalArgumentException("缓冲区大小<=0");}buf=newbyte[size];}可以看到BufferedOutputStream调用了super(out);也就是说,out.close();调用通过BufferedOutputStream传入的wrappedstream,这里是FileOutputStream我们在看其他类似的,比如BufferedWriter的源码:publicvoidclose()throwsIOException{synchronized(lock){if(out==null){return;}尝试{flushBuffer();}最后{out.close();输出=空;cb=空;}}}通过观察各种流的源码可以得出,wrappedstream会自动调用wrappedstream的close方法,不需要自己调用。是否有关闭流方法的命令?从上面的结论,产生一个问题:如果wrappedstream被手动关闭会怎么样,关闭stream有没有顺序?事实上,我们习惯于关闭两个流。首先,让我们做一个简单的实验。在第一题代码的基础上,添加手动增加关闭流的代码,那么有两个命令:1.先关闭wrappedstream(一般不会抛出异常)importjava.io.BufferedOutputStream;importjava.io.FileOutputStream;importjava.io.IOException;publicclassIOTest{publicstaticvoidmain(String[]args)throwsIOException{FileOutputStreamfileOutputStream=newFileOutputStream("c:\\a.txt");BufferedOutputStreambufferedOutputStream=newBufferedOutputStream(fileOutputStream);bufferedOutputStream.write("测试写东西".getBytes());bufferedOutputStream.flush();fileOutputStream.close();//先关闭wrappedstreambuffered.close(Stre)}}2.先关闭wrappingstream(一般不会抛出异常)importjava.io.BufferedOutputStream;importjava.io.FileOutputStream;importjava.io.IOException;publicclassIOTest{publicstaticvoidmain(String[]args)throwsIOException{FileOutputStreamfileOutputStream=newFileOutputStream("c:\\a.txt");BufferedOutputStreambufferedOutputStream=newBufferedOutputStream(文件输出流);bufferedOutputStream.write("测试写东西".getBytes());bufferedOutputStream.flush();bufferedOutputStream.close();//先关闭包装流fileOutputStream.close();}}上面两种写法都没有问题。我们已经知道bufferedOutputStream.close();会自动调用fileOutputStream.close();方法,那么这个方法是如何执行的呢?我们再看一下FileOutputStream的源码:publicvoidclose()throwsIOException{synchronized(closeLock){if(closed){return;}关闭=真;}...可以看出,它使用了同步锁,并且使用了关闭标记,如果已经关闭,就不会再操作,所以多次调用不会有问题如果没有看过参考文章,我可能会得出一个结论,关闭流不需要考虑顺序。我们看下面的代码(参考文章修改):(String[]args)抛出IOException{FileOutputStreamfos=newFileOutputStream("c:\\a.txt");OutputStreamWriterosw=newOutputStreamWriter(fos,"UTF-8");BufferedWriterbw=newBufferedWriter(osw);bw.write("javaIO关闭测试");//内外带顺序会报异常fos.close();关闭();bw.close();}}将抛出StreamclosedIO异常:Exceptioninthread"main"java.io.IOException:Streamclosedatsun.nio.cs.StreamEncoder.ensureOpen(StreamEncoder.java:45)atsun.nio.cs.StreamEncoder。写(StreamEncoder.java:118)在java.io.OutputStreamWriter.write(OutputStreamWriter.java:207)在java.io.BufferedWriter.flushBuffer(BufferedWriter.java:129)在java.io.BufferedWriter.close(BufferedWriter.java:264)在IOTest.main(IOTest.java:18)和ifbw.close();先放,其他的顺序随意,即修改成如下两个:bw.close();osw.close();fos.close();bw.close();fos.close();osw。关闭();不会报错,这是为什么呢,马上来看看BufferedWriter的close源码:publicvoidclose()throwsIOException{synchronized(lock){if(out==null){return;}尝试{flushBuffer();}最后{out.close();输出=空;cb=空;}}}调用flushBuffer()方法,也是抛异常中的error方法:voidflushBuffer()throwsIOException{synchronized(lock){ensureOpen();如果(nextChar==0)返回;out.write(cb,0,nextChar);下一个字符=0;你可以看到一条大线out.write(cb,0,nextChar);如果这一行是在stream关闭后执行,会抛出IO异常,有时我们会写成:fos.close();fos=null;osw.close();osw=null;bw.close();bw=null;这样也会抛出异常,不过是flushBuffer()中的ensureOpen()抛出的,从源码可以看出:privatevoidensureOpen()throwsIOException{if(out==null)thrownewIOException("Streamclosed");}voidflushBuffer()throwsIOException{synchronized(lock){ensureOpen();如果(nextChar==0)返回;out.write(cb,0,nextChar);下一个字符=0;}}如何防止这种情况?只需编写以下形式:bw.close();bw=空;结论:流上的close方法可以多次调用。理论上不需要考虑关闭流的顺序,但有时在close方法中调用write等待方法时会抛出异常。从以上两个结论,可以得出如下建议:关闭流只需要关闭最外层的wrapper流,其他流会自动调用关闭,保证不会抛出异常。如:bw.close();//下面三个无序osw=null;fos=null;bw=null;注意,在某些方法中,close方法除了wrappedstream的close方法外,还会调用wrappedstream,将其设置为null,方便JVM回收。在bw.close()中:publicvoidclose()throwsIOException{synchronized(lock){if(out==null){return;}尝试{flushBuffer();}最后{out.close();输出=空;cb=空;}}}终于有了设置为null的代码,所以有时候不需要手动设置为null。(个人建议写下来,执行时间不多)来源:blog.csdn.net/maxwell_nc/article/details/49151005近期热点文章推荐:1.1,000+Java面试题及答案(2022最新版)2.劲爆!Java协程来了。..3.SpringBoot2.x教程,太全面了!4.不要用爆破爆满画面,试试装饰者模式,这才是优雅的方式!!5.《Java开发手册(嵩山版)》最新发布,赶快下载吧!感觉不错,别忘了点赞+转发!
