JDK-8199713 : ByteArrayOutputStream should not throw IOExceptions
  • Type: CSR
  • Component: core-libs
  • Sub-Component: java.io
  • Priority: P4
  • Status: Closed
  • Resolution: Approved
  • Fix Versions: 11
  • Submitted: 2018-03-15
  • Updated: 2018-03-23
  • Resolved: 2018-03-21
Related Reports
CSR :  
Description
Summary
-------------
Add `writeBytes` method to `ByteArrayOutputStream`.

Problem
-------------
The variant of `ByteArrayOutputStream.write` which accepts a single byte array parameter is inherited from `OutputStream` where it is declared to throw an `IOException` but when invoked on a `ByteArrayOutputStream` it cannot throw an `IOException`. Thus use of this method requires a useless `try-catch` block:

    try {
        baos.write(b);
    } catch (IOException e) {
        assert false : "cannot get here";
    }

Solution
-------------
Add a new method `ByteArrayOutputStream.writeBytes` which does not throw an `IOException`. Overriding `OutputStream.write` not to throw an `IOException` is not a good option as it could cause an unwelcome source incompatibility especially for those that are compiling to multiple releases without specifying `--release` (or `-source/-target`).

Specification
-------------
Please refer to the attachment `specdiff-baos-writeBytes-8180410.zip`.

__Principal Change__

Add `ByteArrayOutputStream.writeBytes`:

    /**
     * Writes the complete contents of the specified byte array
     * to this {@code ByteArrayOutputStream}.
     *
     * @apiNote
     * This method is equivalent to {@link #write(byte[],int,int)
     * write(b, 0, b.length)}.
     *
     * @param   b     the data.
     * @throws  NullPointerException if {@code b} is {@code null}.
     * @since   11
     */
    public void writeBytes(byte b[]) {}

__Incidental changes__

1. Document that `write(b,i,i)` throws `NullPointerException` and `IndexOutOfBoundsException`.
2. Document that `writeTo` throws `NullPointerException`.
3. Globally replace verbiage "byte array output stream" with `ByteArrayOutputStream`.
Comments
Reaffirming approval to use an @apiNote.
23-03-2018

The statement "This method is equivalent to {@link #write(byte[],int,int) write(b ,0, b.length)}" is moved to an @apiNote and the updated specdiff-baos-writeBytes-8180410-2.zip is attached.
23-03-2018

Incidental changes 1 and 2 indeed merely document long-standing behavior.
22-03-2018

Regarding the statement "this method is equivalent to..." this should be an @apiNote, not @implSpec. I wrote the following on the mailing list. Including it here for convenience: ��Having this as an @implSpec sounds as if the implementation of this method in BAOS is *required* to call write(b, 0, b.length). It happens to do that in the current webrev, but this is not a requirement on the implementation. (At least that doesn't appear to be the intent.) ��Instead, this statement explains and clarifies, but otherwise doesn't add any testable assertions or change any semantics of the contract specified in the first sentence of the doc. Thus, it's a note on the API.�� http://mail.openjdk.java.net/pipermail/core-libs-dev/2018-March/052164.html See JDK-8068562 for definitions of @apiNote and @implSpec.
21-03-2018

I assume the incidental changes are only documenting long-standing behavior. Unfortunate that the original version of the class did not override write(byte[]) to not throw an exception. As a code review comment, perhaps as follow-up work, BAOS is ripe for some @Override annotations. The comment <p> This method is equivalent to {@link #write(byte[],int,int) write(b ,0, b.length)} looks like an @implSpec tag. Moving to Approved.
21-03-2018