关闭与 System.in 相关的 Scanner。

47

我有一个与System.in相关联的Scanner。现在,在使用完Scanner后,应该关闭它,因为将其保持打开状态是糟糕的编码实践。但是,如果我关闭Scanner,也会关闭System.in! 有人可以告诉我如何在不关闭System.in的情况下关闭Scanner吗(如果有任何方法)。


4
请注意,您可以使用修饰器来保护流。 - McDowell
@pauljerman System.in 是一个 InputStream,因此实现了 AutoClosable,请参阅文档 - jlordo
不要关闭你的扫描器,撤销那个操作。我会发布答案。 - paul jerman
可能是Closing BufferedReader and System.in的重复。 - Raedwald
5
“医生,我这样做会疼!”……“那就别这样做了。” - kaya3
显示剩余4条评论
5个回答

30

如果您不想关闭底层流,请不要关闭Scanner,这是最简单的方法。

理想情况下,您应该只创建一个Scanner并在整个程序的生命周期中使用它。无论如何,似乎您没有充分的理由去关闭它。


4
这是通过要求代码知道它正在与系统或至少不应关闭的某些内容进行交互来实现的。Paul Jermans推荐使用'CloseShieldInputStream',使代码可以忽略这一事实,并将其视为任何其他InputStream,并在完成后尝试关闭它。这里的简单实际上取决于上下文。 - candied_orange
2
@candied_orange,你不应该关闭一个你没有拥有的流(鉴于Java缺乏强烈的所有权概念,这大致意味着你没有打开)。如果你从其他地方获取了流,请不要关闭Scanner。 - Andy Turner
@AndyTurner 那个方法可行。如果你想遵循这个规则,同时仍然有广泛的使用自由,请查看“中间空洞模式”。(https://www.google.com/amp/s/jbergmanster.wordpress.com/2007/09/12/a-simple-example-of-the-hole-in-the-middle-pattern/amp/) - candied_orange

27

你也可以为 System.in 流创建自己的自定义不可关闭包装器。 - paul jerman

10

不要添加盾牌类之类的东西,只需要添加一个好的注释和一个

        @SuppressWarnings("resource")

这已经足够好了。我似乎没有看到很多缺点,不要忘记评论。


1
这可能会抑制警告,但在关闭Scanner后尝试使用System.in时仍然会导致“IOException:Stream closed”。 - derHugo
6
@derHugo 我认为他们的意思是不要关闭 Scanner 并使用注释来抑制有关那个的警告,并添加解释性注释。 - bkis

0

我有模糊的记忆,很久以前使用相同的ScannerSystem.in两次会出现奇怪的、无法诊断的问题,所以这就是我使用的方式(尽管你应该在整个程序的生命周期内只使用一个扫描器):

static String input() {
    try {
        return new Scanner(System.in).nextLine();
    } catch (NoSuchElementException e) {
        throw e;
    }
}

出于某种原因,如果我不使用catch-throw,Eclipse会抱怨资源泄漏:'<未分配的可关闭值>'从未关闭,而使用它却没有警告。


1
你只是在这里混淆Eclipse代码分析,以避免警告 :) 扫描器仍然没有关闭(虽然你不应该这样做 :)) - john16384

-11
根据InputSteam API的说明,“InputStream的close方法不执行任何操作”,因此由于System.in是InputStream的一个实例,您无需担心是否会调用close()方法。

2
显然情况并非如此。如果我在System.in上打开一个Scanner,关闭它,然后再打开另一个并尝试使用它(例如nextLine()),我会得到NoSuchElementException - H.v.M.
7
虽然在抽象类 InputStream 的默认实现中,close() 方法确实不起作用,但并不意味着所有子类也是如此!如果这是真的,那么这个方法就没有用处了。 - Jiri Tousek
3
InputStream 是一个抽象类。当其子类表示需要在使用后关闭的资源(如 stdin)时,它们可以和应该执行“某些操作”。虽然 InputStream.close() 可能需要更清晰的说明,但你的结论是不正确的。 - dimo414
2
这个回答完全是错误的,我认为它需要被删除。 - aristotll
如果我们看一下InputStream的其他方法,比如mark,它也说“InputStream的mark方法什么都不做”。但是如果我们看一下reset方法,它说“InputStream类的reset方法除了抛出IOException之外什么都不做”。所以上面关于“什么都不做”的句子指的是例如抛出异常。 - Erwin

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接