将方法参数的所有权传递给“尝试使用资源”块

Posted

技术标签:

【中文标题】将方法参数的所有权传递给“尝试使用资源”块【英文标题】:Pass ownership of method argument to 'try with resources' block 【发布时间】:2016-06-30 18:40:43 【问题描述】:

我对 Java 的“资源尝试”功能有疑问。大多数示例似乎都遵循在 try 语句中声明和实例化资源的模型,如下所示:

try (BufferedReader in =
        new BufferedReader(new InputStreamReader(socket.getInputStream())); ) 
  ...

我需要将可关闭资源传递给方法,我想知道是否可以或可取地将作为方法参数传递的可关闭资源的所有权传递给 try 块。例如:

void handleConnection(Socket clientSocket) 
    try (Socket socket = clientSocket;
         BufferedReader in =
             new BufferedReader(new InputStreamReader(socket.getInputStream())); ) 
        ...
    

这会正确清理 clientSocket 实例吗?我希望避免在我的代码中显式关闭 clientSocket 实例。

【问题讨论】:

如果您确实走这条路,请务必记录下来。通常,可关闭对象的所有者应负责关闭它。 我可以理解为什么它可能是危险的,因为其他一些代码可能会在套接字关闭后尝试使用它。我主要想知道它是否按我期望的方式工作。 我会非常强烈地建议不要这样做。套接字的创建者应该负责关闭它。 我明白你为什么不建议这样做。我想要这样做的原因是因为我将套接字传递给子线程以异步读取。看起来套接字无论如何都必须在子线程内关闭,我想使用更简洁的语法。 【参考方案1】:

虽然这在技术上是正确的,但它是危险的。许多AutoCloseable(包括Socket)一旦关闭就无法重新打开。因此,handleConnection 方法的用户必须知道传递给您的方法的对象不能再使用。让对象的所有者处理它的生命周期可能是一个更好的主意。例如,您可以通过创建一个包装器类来实现这一点,该包装器类本身实现AutoCloseable,如下所示。

public class SocketHandler implements AutoCloseable 
    private final Socket clientSocket;

    public SocketHandler(Socket clientSocket) 
        if (clientSocket == null) 
            throw new IllegalArgumentException("Socket cannot be null");
        
        this.clientSocket = clientSocket;
    

    public void handle() 

    

    @Override
    public void close() throws Exception 
        clientSocket.close();
    


【讨论】:

以上是关于将方法参数的所有权传递给“尝试使用资源”块的主要内容,如果未能解决你的问题,请参考以下文章

可以将 NULL 传递给块参数吗?

防止 Obj-C 代码将 `nil` 传递给具有非可选参数的 Swift 方法

将数组传递给 TypeScript 中的可变参数函数

你如何将参数传递给define_method?

无法将 1d 数组传递给方法,因为有 2d 数组参数

如何将实例成员的默认参数值传递给方法?