Java 11为何为ByteArrayOutputStream新增与write方法功能重复的writeBytes方法?
为什么Java 11要在
ByteArrayOutputStream中新增看似功能重合的writeBytes(byte[] b)方法 两个方法看似都是把传入字节数组全部写入流,实际设计目的完全不重合,核心原因有三个:
- 消除无意义的异常处理负担
父类OutputStream定义的write(byte[] b)方法按照IO流的通用契约,声明了抛出IOException。但ByteArrayOutputStream是纯内存操作,写入过程根本不会产生任何IO异常。之所以不直接修改继承来的write方法去掉异常声明,是为了保证向后兼容性:如果直接改动重写后的write方法去掉异常抛出声明,会导致所有重写了该方法、并声明抛出IOException的自定义ByteArrayOutputStream子类编译失败,这对JDK核心类库来说是不可接受的兼容性破坏。同时从设计层面,只要把ByteArrayOutputStream当做OutputStream使用,就必须遵守父类的接口契约,保留throws IOException的声明,符合里氏替换原则。
这就导致之前直接操作ByteArrayOutputStream实例时,明明不可能触发IO异常,却必须强制写try-catch块或者在方法上声明抛出异常,全是冗余代码。新增的writeBytes是ByteArrayOutputStream自身定义的方法,不需要遵守父类通用输出流的契约,直接去掉了异常声明,调用时不需要写多余的异常处理逻辑。 - 明确语义,提供确定的高性能实现
父类的write(byte[] b)是可被子类重写的方法,OutputStream的默认实现是循环调用单字节写入的write(int b)方法,性能很差。虽然ByteArrayOutputStream早就重写了该方法实现批量数组拷贝,但如果调用者持有的是OutputStream类型的引用,没法100%确定调用的write方法是不是走的高效批量实现。
而writeBytes的语义非常明确:就是直接把传入字节数组的全部内容批量拷贝到ByteArrayOutputStream的内部缓冲区,没有多余的逻辑,JIT编译器也更容易对这个类自有方法做去虚化、内联优化,在高频写入场景下性能更稳定。 - 对齐Java 11的IO类API风格
Java 11对整套IO流API做了易用性升级,比如给InputStream新增了readAllBytes()、readNBytes()等语义直白的工具方法,给输出流新增writeBytes也是统一API风格——方法名直接表明是操作完整字节数组,不需要额外传偏移量、长度参数,开发者看到方法名就知道作用,降低理解成本。
举个最直观的代码对比,旧写法必须处理永远不会触发的异常:
ByteArrayOutputStream baos = new ByteArrayOutputStream(); // 语法强制要求捕获IOException,实际永远不会触发 try { baos.write(new byte[]{1,2,3}); } catch (IOException e) { e.printStackTrace(); }用
writeBytes的写法就简洁很多:ByteArrayOutputStream baos = new ByteArrayOutputStream(); baos.writeBytes(new byte[]{1,2,3}); // 不需要冗余的异常处理
内容的提问来源于stack exchange,提问作者MTB
相关产品推荐
相关产品推荐

