在Java中,我注意到有时候,System.err
语句会先在System.out
语句之前打印,尽管后者在我的代码中首先出现在前者之前。为什么?我很好奇。
答案 0 :(得分:17)
通常,System.out
是缓冲的输出流,因此在将文本刷新到目标位置之前会累积文本。这可以显着提高打印大量文本的应用程序的性能,因为它可以最大限度地减少必须进行的昂贵系统调用的次数。但是,这意味着文本并不总是立即显示,并且打印时间可能比写入的时间晚得多。
System.err
通常不会被缓冲,因为错误消息需要立即打印。这是较慢的,但直觉是错误消息可能是时间关键的,因此程序减速可能是合理的。根据{{3}}:
通常,此流对应于主机环境或用户指定的显示输出或其他输出目标。 按照惯例,此输出流用于显示错误消息或应立即引起用户注意的其他信息,即使主要输出流(变量out的值)已重定向到通常不会持续监控的文件或其他目的地。
(我的重点)
但是,因此,发送到System.out
的旧数据可能会在较新的System.err
消息之后显示,因为旧的缓冲数据会在消息发送到System.err
之后刷新。例如,这一系列事件:
System.out
System.err
并立即打印。System.out
,并打印缓冲的数据会导致输出
PANIC
Hello, world!
即使在Hello
打印到System.out
之前,PANIC
已打印到System.err
。
希望这有帮助!
答案 1 :(得分:2)
它与缓冲和优先级有关。据推测,Java(如C和C衍生物)不会缓冲System.err
,stderr
等,与System.out
,stdout
等不同。这样,系统可以确保您最有可能获得任何相关的错误消息,即使由于某种原因必须丢弃标准输出。
来自Wikipedia:
将标准输出和标准错误定向到同一目的地(例如文本终端)是可接受的 - 也是正常的。除非涉及缓冲,否则消息的显示顺序与程序写入的顺序相同。 (例如,常见的情况是标准错误流是无缓冲的,但标准输出流是行缓冲的;在这种情况下,如果标准输出流的缓冲区不是,则稍后写入标准错误的文本可能会更早出现在终端上但已经满了。)