printStackTrace()输出和System.out输出非调用顺序输出

来源:互联网 发布:注册淘宝网店 编辑:程序博客网 时间:2024/05/22 08:03

IDE:NetBeans8.0.2
jdk:1.7.0_45

我们在处理异常的时候,捕获异常e,并e.printStackTrace()。如果在其他地方添加标准输出System.out.println,会发现控制台显示并不是按照我们代码中的输出顺序显示信息的。
首先我需要确定e.printStackTrace()会输出到哪里,所以在try语块的内部和外部都添加了标准输出来验证。
参见如下代码:

public class JavaTest {    private static void dosomething(){        System.out.println("1+1=2");    }    public static void main(String[] args) {        File file=new File("test.txt");        FileInputStream input=null;        try {                        System.out.println("Before new");            input=new FileInputStream(file);            System.out.println("After new");            input.close();        } catch (Exception e) {            System.out.println("Before printStackTrace");            e.printStackTrace();            System.out.println("After printStackTrace");        }        finally{            System.out.println("Finally block");        }        System.out.println("try block finished");        dosomething();    }}

那么我们现在运行这个程序。
得到如下输出:

Before newBefore printStackTracejava.io.FileNotFoundException: test.txt (系统找不到指定的文件。)After printStackTraceFinally block    at java.io.FileInputStream.open(Native Method)try block finished1+1=2    at java.io.FileInputStream.<init>(FileInputStream.java:146)    at javatest.JavaTest.main(JavaTest.java:18)

也有可能是如下情况:

Before newjava.io.FileNotFoundException: test.txt (系统找不到指定的文件。)Before printStackTrace    at java.io.FileInputStream.open(Native Method)After printStackTraceFinally blocktry block finished1+1=2    at java.io.FileInputStream.<init>(FileInputStream.java:146)    at javatest.JavaTest.main(JavaTest.java:18)

当然,还可以尝试出其他情况。

从上面两种运行情况可以发现,输出的顺序是不一定的。由此猜想,两种输出可能根本就不是一种输出,然而由于操作系统调度,而让信息输出每次都呈现不一样的结果。
这样参照jdk1.6.0版本的API文档,找到Exception类的printStackTrace()方法,在其父类Throwable中看到printStackTrace()的第一句解释:

将此 throwable 及其追踪输出至标准错误流。此方法将此 Throwable 对象的堆栈跟踪输出至错误输出流,作为字段 System.err 的值。

可以看到,printStackTrace是通过System.err流输出到控制台的,而我们写的标准输出是通过System.out流输出到控制台的。二者写入控制台会收到操作系统调度的影响,出现以上运行结果。

类似于C\C++中的stdin,stdout,stderr三种标准流,Java的System.in,System.out,System.err与以上三种标准流对应。

参考网络资料(未经本人验证)
如果要让System.out和System.err区分开,则需要将System.out重定向到其他地方,比如文件。因为System.err无法重定向到控制台以外的地方,所以控制台用来显示System.err的数据,文件显示System.out的数据,二者的信息就不会掺杂在一起了。

1 0
原创粉丝点击