在Java中,如何确保可关闭接口的close()方法的幂等性?

在Java中,如何确保可关闭接口的close()方法的幂等性?,java,oracle,try-with-resources,idempotent,autocloseable,Java,Oracle,Try With Resources,Idempotent,Autocloseable,Java 5中引入了Closeable接口,而Java 7中引入了AutoCloseable接口以及try with resources语句可关闭扩展了(自Java 7以来)自动关闭接口 在《OCA/OCP Java SE 7-程序员I&II学习指南》一书中,第399页写道: 如果我们多次调用close()会发生什么?视情况而定。对于实现自动关闭的类,实现要求是幂等的。这意味着您可以整天调用close(),第二次及以后不会发生任何事情。[…]对于实现Closeable的类,没有这样的保证 因此,

Java 5中引入了
Closeable
接口,而Java 7中引入了
AutoCloseable
接口以及
try with resources
语句<代码>可关闭扩展了(自Java 7以来)自动关闭接口

在《OCA/OCP Java SE 7-程序员I&II学习指南》一书中,第399页写道:

如果我们多次调用
close()
会发生什么?视情况而定。对于实现
自动关闭的类
,实现要求是幂等的。这意味着您可以整天调用
close()
,第二次及以后不会发生任何事情。[…]对于实现
Closeable
的类,没有这样的保证

因此,根据本文,
AutoCloseable
的实现需要是幂等的,而
Closeable
的实现则不需要。现在,当我看一下的文档时,它说:

请注意,与
Closeable
close
方法不同,此close方法不要求是幂等的。换句话说,多次调用此
close
方法可能会产生一些明显的副作用,这与
Closeable.close不同,如果多次调用,则要求该方法无效

这与书中所写的相反。我有两个问题:

(1) 什么是正确的?docs.oracle.com上的文档还是这本书?这两个接口中的哪一个需要幂等性

(2) 不管哪一个需要是幂等的——Java实际上根本没有办法确保它是幂等的,这是对的吗?如果是这样的话,
close
方法的“要求”是幂等的,这是程序员应该做的事情,但我永远不能确定使用该接口的人是否真的做了,对吗?在这种情况下,幂等性只是oracle的一个建议,对吗

  • Oracle的Javadoc是正确的。这只是一个直观的解释-
    AutoCloseable
    对象在
    try(){}
    (所谓的try with resources)块中使用的原因,其中
    close()
    实际上是自动调用的,并且只调用一次;同时,
    close()
    Closeable
    接口方法,您总是手动调用,可以意外调用两次,或者使代码易于阅读。 另外-
    Closeable
    扩展了
    AutoCloseable
    ,它不应该使
    close()
    方法的契约从
    AutoCloseable
    中变弱,它只能增加需求。因此,当
    AutoCloseable
    要求
    close()
    为幂等且扩展接口取消了此要求时,这种抽象情况将是一种糟糕的设计

  • 是的,你的理解是对的。这只是一个程序员应该考虑的契约。就像
    equals()
    hashCode()
    之间的契约一样。您可以以不一致的方式实现它,编译器或其他任何东西都不会为您标记它。这个问题只有在运行时才会出现


  • 2) 你所说的“Java实际上根本没有办法确保它是幂等的”是什么意思。该语言会这样做,例如具有表示调用方法的最终布尔标志。另一方面,编译器不会对close实现进行某种验证,以验证实现是否为幂等。关于(1):这本书实际上在这里有一个错误,只是在这一页上找到了提到的勘误表:@John:我不明白你对布尔标志的意思。这里我只讨论幂等性。我的猜测是,没有执行幂等性属性的验证,即使这样也不可能做到。问题2中的第一句话表明,在java中实现幂等方法是不可能的。既然这是不可能的,我也不会那么过分。但是没有这样的检查。如果
    AutoCloseable
    要求
    close()
    是幂等的,而子类型
    Closeable
    不是,那就奇怪了。这意味着,只要它们同时实现
    Closeable
    ,就可能有
    AutoCloseable
    而没有幂等元的
    close()
    ,我喜欢与
    equals()
    hashCode()进行比较
    -这是一个很好的例子。这不仅仅是程序员应该做的事情-它还承诺JAVA API本身(由编写
    Closeable
    的同一组编写)将实现
    close()
    幂等。当然,如果您自己实现
    close()
    ,没有人能强迫您使其幂等。