Update per latest feedback

This commit is contained in:
Daniel Gredler 2026-01-17 18:11:05 +01:00
parent ecd31f591a
commit dee9d96a41
2 changed files with 49 additions and 24 deletions

View File

@ -34,18 +34,23 @@ import jdk.internal.util.ArraysSupport;
/**
* This class implements an output stream in which the data is
* written into a byte array. The buffer automatically grows as data
* is written to it.
* The data can be retrieved using {@code toByteArray()} and
* {@code toString()}.
* is written to it. The data can be retrieved using {@code toByteArray()}
* and {@code toString()}.
*
* <p>
* Closing a {@code ByteArrayOutputStream} has no effect. The methods in
* this class can be called after the stream has been closed without
* generating an {@code IOException}.
*
* <p>
* Subclasses of this class may override {@code ensureCapacity(int)} in
* order to customize the buffer growth behavior. Subclasses which add
* additional write methods should either manage buffer growth manually
* or invoke {@code ensureCapacity(int)} to grow the buffer.
*
* @author Arthur van Hoff
* @since 1.0
*/
public class ByteArrayOutputStream extends OutputStream {
/**
@ -81,22 +86,6 @@ public class ByteArrayOutputStream extends OutputStream {
buf = new byte[size];
}
/**
* Increases the capacity if necessary to ensure that this
* {@code ByteArrayOutputStream} can hold at least the number of
* elements specified by the {@code minCapacity} argument.
* If the {@code minCapacity} argument is nonpositive, this
* method takes no action and simply returns.
*
* @param minCapacity the desired minimum capacity.
* @since 27
*/
protected void ensureCapacity(int minCapacity) {
if (minCapacity > 0) {
ensureCapacityInternal(minCapacity);
}
}
/**
* Increases the capacity if necessary to ensure that this
* {@code ByteArrayOutputStream} can hold at least the number of
@ -105,10 +94,11 @@ public class ByteArrayOutputStream extends OutputStream {
* @param minCapacity the desired minimum capacity.
* @throws OutOfMemoryError if {@code minCapacity < 0} and
* {@code minCapacity - buf.length > 0}. This is interpreted as a
* request for the unsatisfiably large capacity.
* request for the unsatisfiably large capacity
* {@code (long) Integer.MAX_VALUE + (minCapacity - Integer.MAX_VALUE)}.
* @since 27
*/
private void ensureCapacityInternal(int minCapacity) {
protected void ensureCapacity(int minCapacity) {
// overflow-conscious code
int oldCapacity = buf.length;
int minGrowth = minCapacity - oldCapacity;
@ -125,7 +115,7 @@ public class ByteArrayOutputStream extends OutputStream {
*/
@Override
public synchronized void write(int b) {
ensureCapacityInternal(count + 1);
ensureCapacity(count + 1);
buf[count] = (byte) b;
count += 1;
}
@ -145,7 +135,7 @@ public class ByteArrayOutputStream extends OutputStream {
@Override
public synchronized void write(byte[] b, int off, int len) {
Objects.checkFromIndexSize(off, len, b.length);
ensureCapacityInternal(count + len);
ensureCapacity(count + len);
System.arraycopy(b, off, buf, count, len);
count += len;
}

View File

@ -71,6 +71,23 @@ public class EnsureCapacity {
byte[] actual = out.toByteArray();
byte[] expected = new byte[] { 1, 2, 3, 4, 5, 6 };
assertEquals(expected, actual);
// verify that overriding ensureCapacity() affects behavior of standard write methods
EvenOutputStream out2 = new EvenOutputStream();
assertEquals(0, out2.getBufferLength());
out2.write(89);
assertEquals(2, out2.getBufferLength());
out2.write(12);
assertEquals(2, out2.getBufferLength());
out2.write(new byte[] { 1, 2, 3 }, 0, 3);
assertEquals(6, out2.getBufferLength());
out2.write(77);
assertEquals(6, out2.getBufferLength());
}
private static void assertAtLeast(int actual, int min) {
@ -95,6 +112,7 @@ public class EnsureCapacity {
}
}
// provides extra visibility into internals
private static final class TestOutputStream extends ByteArrayOutputStream {
public void ensureCapacity(int minCapacity) {
super.ensureCapacity(minCapacity);
@ -103,4 +121,21 @@ public class EnsureCapacity {
return buf.length;
}
}
// starts empty, is always sized to an even number of bytes
private static final class EvenOutputStream extends ByteArrayOutputStream {
public EvenOutputStream() {
super(0);
}
protected void ensureCapacity(int minCapacity) {
int deficit = minCapacity - buf.length;
if (deficit > 0) {
minCapacity += minCapacity % 2;
buf = Arrays.copyOf(buf, minCapacity);
}
}
public int getBufferLength() {
return buf.length;
}
}
}