如何在不支持mark时正确实现Java InputStream.mark()方法?
这个问题其实在Java开发者自定义流实现时挺容易碰到的——当我们明确不需要支持mark/reset功能、markSupported()返回false的时候,mark()方法到底该怎么处理?
先给你拆解下两个可选方案的实际场景和业界惯例:
选项(a):忽略操作,空实现
这是Java核心库的标准做法,比如你去看FileInputStream的源码,它的mark()方法就是空实现,啥也不做。原因很简单:既然调用者已经通过markSupported()知道这个流不支持mark功能了,还执意调用的话,通常是调用方自己的问题。空实现不会打断程序的正常执行流程,后续如果调用reset(),才会抛出IOException(因为reset本身也不支持),这符合“晚报错”的惯例,也和标准流的行为保持一致。选项(b):抛出
UnsupportedOperationException异常
这种方式属于“早报错”,能立刻提醒调用者他们执行了不被支持的操作,避免后续可能出现的逻辑错误。但问题在于,Java标准库的实现里并没有采用这种方式,如果你这么做,可能会让熟悉标准流行为的开发者感到困惑,甚至导致一些依赖标准流行为的代码出现意外异常。
结论
优先选择选项(a),也就是给mark()写一个空实现。这能保证你的自定义InputStream和JDK自带的实现行为一致,减少使用者的学习成本和潜在的兼容性问题。如果你的业务场景有特别严格的错误检查需求,也可以考虑选项(b),但一定要在类的Javadoc里明确说明这个特殊行为,避免误解。
内容的提问来源于stack exchange,提问作者Neil Bartlett

