几天前我意识到PrintWriter(以及PrintStream)在写入,刷新或关闭时从不抛出IOException。
相反,当发生错误时,它会设置一个内部标志(trouble=true
)。
无法获取确切的异常,但只能通过checkError()来确定是否有异常。
我的问题是:为什么要这样做?这不是糟糕的API设计吗?
几天前我意识到PrintWriter(以及PrintStream)在写入,刷新或关闭时从不抛出IOException。
相反,当发生错误时,它会设置一个内部标志(trouble=true
)。
无法获取确切的异常,但只能通过checkError()来确定是否有异常。
我的问题是:为什么要这样做?这不是糟糕的API设计吗?
我认为由于System.out
和System.err
是PrintStream
的实例,所以提供了一些更轻松的错误处理方式。正如其他帖子中提到的那样,这可能是为了使那些从C/C++ 1995年左右过渡的人更加顺畅。当添加Reader/Writer API时,创建了PrintWriter
来与现有的PrintStream
并行。
这种行为极其适用于日志记录。日志记录是一个大型应用程序的附属服务。通常,如果日志记录失败,则不希望整个应用程序都失败。因此,至少对于System.err
来说,忽略异常是有意义的。
我想这是因为IOExceptions是被检查的,这会要求你在每个System.out.调用周围放置一个try catch块。
更新:或者在你的方法签名中加上throws。
那会很快变得很烦人。
我不是很清楚这个故事,但我认为它的目的是让Java更容易使用,特别是对于那些设计师希望能够使用简单的stdio打印方法而无需知道异常处理的新手程序员。因此,在这方面,这是一个好的设计(尽管我有些同意你的看法)。
有可能这个设计是由一个来自C语言背景的人完成的,因为stdio错误处理方式类似。由于我习惯了这种范式,我不会说它不好,但我同意它是不一致的。
我也同意关于尝试让PrintWriter更易于使用的评论。Java中的IO类很令人困惑(至少对我认识的每个人都是如此),也许有人只是想让生活变得更轻松一些。
这不是设计错误。它是一种适合在写输出并希望忽略错误的情况下使用的正确设计。
作为典型用例,已经提到了System.out
和System.err
,但原因不是为了方便或平稳的C/C++过渡而进行的放松处理。而是期望处理这样的情况:
在这种情况下,根据系统实现的不同,可能会发生System.out
或System.err
在关闭控制台后失败,但您不希望这会导致应用程序崩溃。希望应用程序继续在后台运行,并且输出意味着被刮擦。这就是PrintWriter
的作用。
FileWriter
或OutputStreamWriter
。如果您需要一些PrintWriter
中可用但FileWriter
中不可用的方法,请创建自己的TextWriter,继承FileWriter
或OutputStreamWriter
。