由于ByteArrayOutputStream
只是写入记忆,因此不应该出现IOException
。但是,由于OutputStream
接口的契约,所有流操作都在其IOException
子句中定义throws
。
“处理”这个从未发生的IOException
的正确方法是什么?只需将操作包装在空的try-catch
块中?
或者有没有ByteArrayOutputStream
可以抛出异常的实际情况?
(另见:How can I handle an IOException which I know can never be thrown, in a safe and readable manner?)
编辑
正如乔恩所指出的那样,ByteArrayOutputStream
没有声明它定义的throws
方法的write
条款 - 但是,它继承了write(byte[])
的OutputStream
,而且确实抛出IOEXception
(很奇怪BAOS
不会覆盖这种方法,因为它可以替换超类版本 - 一次写入一个字节 - 使用更高效的arraycopy
调用)
好吧,ByteArrayOutputStream
没有声明它的任何方法抛出IOException
除了writeTo
和close
。 (我不知道为什么close
仍然声明它,说实话。)
如果你有一个OutputStream
类型的引用,当然你仍然可以看到抛出声明。
我不会使用一个空的catch块 - 我会抛出像IllegalStateException
或类似的未经检查的异常:它意味着你处于一种你真的没有想到的情况,而且出现了严重错误。
我只是注意到ByteArrayOutputStream.write实际上并没有声明IOException - 但每当我使用它时Eclipse都会抱怨未处理的异常......很奇怪。
这很容易解释。你可能做过这样的事情:
OutputStream os = new ByteArrayOutputStream();
...
os.write();
“问题”是你将方法称为OutputStream.write()
而不是ByteArrayOutputStream.write()
。所以编译器说:
“啊......
write()
上的OutputStream
可以抛出一个IOException
,所以你必须处理它。”
它不能说:
“这个特别的
OutputStream
真的是一个ByteArrayOutputStream
......所以我们会让你失望。”
因为JLS不允许它。
这是通过编码到接口而不是实现类的“最佳实践”回到咬合你的边缘情况之一。
好的......
OutputStream
实现为Java类而不是Java接口,但这不是重点。一个典型的陈词滥调是在阻挡块中的throw new RuntimeException(theIOException)
。如果不可能发生,你至少要了解它。
在这种情况下,异常链接是最佳实践。即抛出RuntimeException。
自2002年以来,这个问题有一个增强的ticket。之所以没有得到解决,是因为它会影响与以前的java版本的兼容性。
这里有两个我会考虑的解决方法。
write(byte[], int, int)
方法不会抛出已检查的异常。指定2个附加参数有点冗长。但是,如果没有try-catch,所有足迹都会更小。
baos.write(array, 0, array.length);
另一种可能的解决方案是编写自己的ByteUtil
类,它在内部捕获异常。
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);
从Java 11开始,还有一个new method ByteArrayOutputStream.writeBytes(byte[])
也不会抛出IOException
:
/**
* 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);
}
如果您不想处理从未抛出的IOException
,则可以使用此方法。