web-dev-qa-db-ja.com

スレッド/実行可能実装をJavaからKotlinに変換する

次のようなメソッドThreadUtilsを持つ既存のJavaクラスeveryがあります。

public class ThreadUtil {

    public static Thread every(int seconds, Runnable r) {
        Thread t = new Thread(() -> {
            while(true) {
                r.run();
                try {
                    Thread.sleep(1000 * seconds);
                } catch (InterruptedException e) {
                    return;
                }
            }
        });
        t.start();
        return t;
    }
}

そして、私はそれをKotlinに変換しようとしています。 Runnableクロージャーに少しこだわっています。これは悪いreturnで失敗します:

fun every(seconds: Int, r: Runnable): Thread {
    val t = Thread({
        while (true) {
            r.run()
            try {
                Thread.sleep((1000 * seconds).toLong())
            } catch (e: InterruptedException) {
                return // ERROR: This function must return a value of type Thread
            }
        }
    })
    t.start()
    return t
}

私はまた、自分自身が物事を分離するのを助けるためにRunnableを引き出しようとしましたが、これも同じように失敗します:

fun every(seconds: Int, r: Runnable): Thread {
    val internalRunnable = Runnable {
        while (true) {
            r.run()
            try {
                Thread.sleep((1000 * seconds).toLong())
            } catch (e: InterruptedException) {
                return // ERROR: This function must return a value of type Thread
            }
        }
    }
    val t = Thread(internalRunnable)
    t.start()
    return t
}

定義されているreturn関数からを試行しない@FunctionalInterfaceまたは同様のスタイルのクロージャ/ラムダを実装するにはどうすればよいですか?

8
Craig Otis

Kotlinでは、ラムダ内のreturnステートメントはJavaのステートメントとは動作が異なります。 returnだけを書くと、キーワードfunで宣言された最も内側の関数から戻ることを意味し、ラムダを無視します。コードでは、「everyから戻る」を意味します。 。

ラムダから戻るには、修飾されたreturn@label--を使用します。この場合、次の簡略化されたスニペットのように、return@Thread(および2番目の例ではreturn@Runnable)です。

for (i in 1..4) {
    Thread { 
        if (i % 2 == 0)
            return@Thread
        println("Thread $i")
    }.run()
}

(このコードの実行可能なデモ)

また、thread { ... }には kotlin-stdlib 関数があります(同様に、ラムダのreturnステートメントはreturn@threadです)。

より詳細な説明は 言語リファレンス および この回答 にあります。

10
hotkey