Kotlin 中有没有办法让多资源“尝试使用资源”?

问题描述 投票:0回答:3

我有java函数(取自here):

/**
 * Checks to see if a specific port is available.
 *
 * @param port the port to check for availability
 */
public static boolean available(int port) {
    if (port < MIN_PORT_NUMBER || port > MAX_PORT_NUMBER) {
        throw new IllegalArgumentException("Invalid start port: " + port);
    }

    ServerSocket ss = null;
    DatagramSocket ds = null;
    try {
        ss = new ServerSocket(port);
        ss.setReuseAddress(true);
        ds = new DatagramSocket(port);
        ds.setReuseAddress(true);
        return true;
    } catch (IOException e) {
    } finally {
        if (ds != null) {
            ds.close();
        }

        if (ss != null) {
            try {
                ss.close();
            } catch (IOException e) {
                /* should not be thrown */
            }
        }
    }

    return false;
}

我想用 Kotlin 重写它,而不需要丑陋的结构。

所以我找到了这个主题:

在 Kotlin 中尝试使用资源

据我所知,我必须首先创建对象,并在

use
lambda 内部创建对象,我必须调用可能抛出异常的方法,但在

的情况下
ServerSocket(port)
DatagramSocket(port)

构造函数中会抛出异常。所以看起来它不符合我的需求。

那么我怎样才能用 Kotlin 重写这段代码呢?

java kotlin exception try-with-resources resource-management
3个回答
0
投票

如果在构造函数中抛出异常,您将无法引用 close...我认为这可以用惯用的 kotlin 编写,如下所示:

return runCatching {
    ServerSocket(port).use { ss ->
        ss.reuseAddress = true
        DatagramSocket(port).use { ds ->
            ds.reuseAddress = true
        }
    }
}.isSuccess

0
投票

如果构造函数抛出异常,则没有对象可以“关闭”。

您发现的 Java 代码看起来像是在将 try-with-resources 语句添加到该语言之前编写的。在现代 Java 中,它看起来更像是这样的:

public static boolean available(int port) {
    if (port < MIN_PORT_NUMBER || port > MAX_PORT_NUMBER) {
        throw new IllegalArgumentException("Invalid start port: " + port);
    }

    try (var ss = ServerSocket(port)) {
        ss.setReuseAddress(true);
        try (var ds = new DatagramSocket(port)) {
            ds.setReuseAddress(true);
            return true;
        }
    } catch (IOException e) {
        return false;
    } 
}

将其转换为 Kotlin 可能看起来像这样:

fun available(port: Int): Boolean {
    require(port in MIN_PORT_NUMBER..MAX_PORT_NUMBER) { "Invalid start port: $port" }

    return try {
        ServerSocket(port).use { ss -> 
            ss.setReuseAddress(true)
            DatagramSocket(port).use { ds ->
                ds.setReuseAddress(true)
                true
            }
        }
    } catch (_: IOException) {
        false
    }
}

0
投票

kotlin 中的代码将如下所示

    import java.io.IOException
    import java.net.DatagramSocket
    import java.net.ServerSocket
    
    fun available(port: Int): Boolean {
        if (port < MIN_PORT_NUMBER || port > MAX_PORT_NUMBER) {
            throw IllegalArgumentException("Invalid start port: $port")
        }
    
        return try {
            createAndConfigureServerSocket(port)
            createAndConfigureDatagramSocket(port)
            true
        } catch (e: IOException) {
            false
        }
    }
    
    private fun createAndConfigureServerSocket(port: Int) {
        ServerSocket(port).use { ss ->
            ss.reuseAddress = true
            ss.close()
        }
    }
    
    private fun createAndConfigureDatagramSocket(port: Int) {
        DatagramSocket(port).use { ds ->
            ds.reuseAddress = true
        }
    }
    
    const val MIN_PORT_NUMBER = 0
    const val MAX_PORT_NUMBER = 65535
© www.soinside.com 2019 - 2024. All rights reserved.