为什么Java StringReader会抛出IOException?

时间:2014-04-17 07:24:44

标签: java api stringreader

今天我正在使用Java类StringReader,我发现它在read方法上抛出IOException非常烦人。我知道它扩展Reader类,其中方法read抛出IOException,但我认为StringReader不需要它。此类不使用任何可能导致错误的外部资源。

经过简短的调查后,我发现StringReader#read抛出IOException如果此类读取的字符串为空,但事实上无法发生,因为如果我们愿意的话尝试将null传递给StringReader构造函数,它会抛出NPE。

您如何看待它,总是抛出与超类相同的异常是一种好习惯吗?


编辑: 正如U Mad Reader所说,读者是一个不是接口的类。

3 个答案:

答案 0 :(得分:5)

如果您的实现确保它永远不会发生,那么抛出与超类或接口定义相同的异常并不是一个好习惯。我总是将签名减少到最低要求。

IOException是可以想象的所有实现所必需的,包括文件源和流和套接字等。没有,这样的实现不能将它们的错误通知为已检查的异常。但是如果一个实现不需要抛出一个已检查的异常(通常会对调用代码感到讨厌),那么从实现类中删除它不会造成任何伤害,但会减轻一些负担。

<强>更新

我找到了read()方法必须抛出IOException的原因:因为为close()方法定义了契约。来自JavaDoc:

  

关闭流并释放与其关联的所有系统资源。关闭流后,进一步的read(),ready(),mark()或reset()调用将抛出IOException。关闭之前关闭的流无效。

答案 1 :(得分:3)

请查看StringReader#read()

查看StringReader#read()方法的源代码。它会调用实际抛出ensureOpen()的{​​{1}}方法,因为IOException会检查以确保该流尚未关闭。

如果读者已关闭,然后再次调用ensureOpen()后会发生什么?

源代码直接来自上面的链接(查看评论):

read()

答案 2 :(得分:1)

在类中实现接口方法时,不需要提供相同的异常参数。当您从超类覆盖方法的声明时,同样的情况适用。

public class MyReader implements Readable {

    @Override
    public int read(CharBuffer cb)  {
        return 0;
    }

}

但是你没有以正确的方式使用界面。如果您正在编写接口,则不会从中受益。

Readable readable = new MyReader();

        try {
            readable.read(null);
        } catch (IOException e) {
            e.printStackTrace();
        }

即使在MyReader中不公开IOException,您仍然必须使用try block。因此,如果您不抛出您实现的方法的异常,可能会指出您在该方法的实现中遗漏了某些内容。所以恕我直言,这样做并不是一个好习惯。

StringBuilder抛出IOException的原因并不是它实现了接口Readable。这样做的原因是验证方法ensureOpen()中的输入,当输入为空时抛出IOException。然后,当调用方法close()或将null传递给构造函数时,input可以为null。方法close是抽象的,它必须在子类中有一些效果。预期的是,在您调用close之后,您将无法再从中读取并且您将获得IOException。

这是完美,干净和可靠的实施,考虑到所有潜在的用例。