Reputation: 41357
Since ByteArrayOutputStream
simply writes to memory, an IOException
should never occur. However, because of the contract of the OutputStream
interface, all stream operations define IOException
in their throws
clause.
What is the correct way to "handle" this never-occurring IOException
? Simply wrap operations in an empty try-catch
block?
Or are there any actual situations where ByteArrayOutputStream
could throw an exception?
(See also: How can I handle an IOException which I know can never be thrown, in a safe and readable manner?)
EDIT
As Jon points out, ByteArrayOutputStream
doesn't declare a throws
clause on the write
methods it defines -- however, it inherits write(byte[])
from OutputStream
, and that one does throw IOEXception
(quite odd that BAOS
wouldn't override this method, as it could replace the superclass version -- which writes one byte at a time -- with a far more efficient arraycopy
call)
Upvotes: 14
Views: 13151
Reputation: 39536
Since Java 11, there is also a new method ByteArrayOutputStream.writeBytes(byte[])
which does not throw an IOException
as well:
/**
* Writes the complete contents of the specified byte array
* to this {@code ByteArrayOutputStream}.
*
* ...
*
* @since 11
*/
public void writeBytes(byte b[]) {
write(b, 0, b.length);
}
You could use this method if you don't want to handle an IOException
which is never thrown.
Upvotes: 4
Reputation: 24740
There is an enhancement ticket for this issue since 2002. The reason why this does not get fixed, is that it would impact compatibility with previous java versions.
Here follow 2 workarounds that I would consider.
The write(byte[], int, int)
method does not throw checked exceptions. It is a bit more verbose to specify the 2 additional parameters. But all by all the footprint is smaller without the try-catch.
baos.write(array, 0, array.length);
Another possible solution, is to write your own ByteUtil
class, which catches the exception internally.
public final class ByteUtil
{
public static void write(ByteArrayOutputStream baos, byte[] bytes)
{
try
{
baos.write(bytes);
}
catch (IOException e)
{
// impossible
}
}
}
// usage
ByteUtil.write(baos, bytes);
Upvotes: 1
Reputation: 718826
I just noticed that ByteArrayOutputStream.write doesn't in fact declare IOException -- but Eclipse complains about an unhandled exception whenever I use it... strange.
That's easy to explain. You've probably done something like this:
OutputStream os = new ByteArrayOutputStream();
...
os.write();
The "problem" is that you are calling the method as OutputStream.write()
rather than as ByteArrayOutputStream.write()
. So the compiler says:
"Ah ...
write()
on anOutputStream
can throw anIOException
, so you gotta deal with it."
It cannot say:
"This particular
OutputStream
is really aByteArrayOutputStream
... so we'll let you off."
because the JLS doesn't allow it.
This is one of those edge cases where following "best practice" by coding to the interface rather than the implementation class comes back to bite you.
OK so ...
OutputStream
is implemented as a Java class not a Java interface, but that is beside the point.Upvotes: 2
Reputation: 6490
Exception chaining is the best practice in this situation. i.e throw a RuntimeException.
Upvotes: 1
Reputation: 100050
A typical cliche is to throw new RuntimeException(theIOException)
in the catch block. If the impossible happens, you at least find out about it.
Upvotes: 1
Reputation: 1500595
Well, ByteArrayOutputStream
doesn't declare that any of its methods throw IOException
except writeTo
and close
. (I don't know why close
still declares it, to be honest.)
If you've got a reference of type OutputStream
though, you would still see the throws declarations from that, of course.
I wouldn't use an empty catch block - I'd throw something like IllegalStateException
or a similar unchecked exception: it means you're in a situation you really don't expect, and something's gone badly wrong.
Upvotes: 12