KotlinからJavaに変換する方法について

採用はこちら

KotlinからJavaへ「変換したい」という要望はよくありますが、実務では 「何を目的に変換するのか」 を整理しないと、不要なコストや品質低下を招きがちです。

まず結論から言うと、

  • Kotlin → Javaへの完全自動変換は可能だが、最終成果物としてそのまま使えることは少ない
  • 多くのケースでは 「変換しないでJavaから使いやすくする」方が合理的
  • 本当にJavaへ移植する場合は、IDE変換+人手による整理が前提

になります。

以下、方法と注意点を正確に説明します。

目次

IntelliJ / Android Studioによる Kotlin→Java 自動変換

概要

IntelliJ IDEA や Android Studio(Kotlinプラグイン有効)には、KotlinコードをJavaコードへ変換する機能があります。

一般的には以下の操作で利用できます。

  • Kotlinファイル(.kt)を開く
  • Code → Convert Kotlin File to Java File
  • もしくは アクション検索(Convert Kotlin と入力)

※ メニューの位置や表示有無は IDE やバージョンによって異なるため、「アクション検索を使う」のが最も確実です。

何ができるか

この変換は、Kotlinコードを Javaとしてコンパイル可能な形に展開します。

  • data class → フィールド/コンストラクタ/getter/equals/hashCode 等を生成
  • 拡張関数 → staticメソッドとして変換
  • when / ?. / ?: → Javaの条件分岐に展開

注意点(重要)

この変換は 「移植のたたき台」を作るものです。

  • Javaとしては 冗長・読みにくいコード になりやすい
  • Kotlinの null安全の意図が Java側では見えにくくなる
  • 拡張関数は <FileName>Kt クラスの static メソッドになり、構造が不自然になりがち
  • !! は単なる NPE発生ポイントとして残る

つまり、

自動変換 = 完成ではない。必ず人手でのリファクタが必要

という前提で使うべき機能です。

「変換しない」という選択肢(Javaとの相互運用)

目的が「JavaプロジェクトからKotlinコードを使いたい」だけであれば、KotlinをJavaへ変換しない方が安全かつ低コストです。

KotlinはJavaとの相互運用を前提に設計されており、以下のアノテーションでJava側の使い勝手を大きく改善できます。

@JvmStatic

Kotlinの objectcompanion object の関数をJavaから static メソッドのように呼べるようにします。

class Foo {
    companion object {
        @JvmStatic fun hello() = "hi"
    }
}

Java側

String s = Foo.hello();

@JvmOverloads(デフォルト引数対応)

Kotlinのデフォルト引数はJavaから直接使えません。

@JvmOverloads を付けると、Java向けのオーバーロードが生成されます。

@JvmOverloads
fun greet(name: String = "Guest", times: Int = 1) { }

※ 注意

  • オーバーロードが増えるため、API公開時はメソッド数増加や互換性に注意が必要

@file:JvmName

トップレベル関数は、Javaから見ると <FileName>Kt クラスに入ります。

これを調整するための指定です。

@file:JvmName("StringUtils")
fun isBlank(s: String?) = s == null || s.isBlank()

Java側

boolean b = StringUtils.isBlank(str);

@Throws

KotlinにはJavaの「チェック例外」という概念がありません。

@ThrowsJava向けに throws 宣言を付与するためのものです。

@Throws(IOException::class)
fun load() { }

※ Java利用者に「この例外が飛ぶ」ことを明示するためのアノテーションです。

Kotlin構文ごとのJava変換イメージ

data class

Kotlinの data class は以下を自動生成します。

  • equals / hashCode / toString
  • componentN
  • copy

Javaでは IDE変換により同等のコードが生成されますが、Java 16+ の record完全互換ではありません(copy や componentN はない)。

→ recordが使える場合でも、用途を確認してから置き換える必要があります。

拡張関数

Kotlin

fun String.lastChar(): Char = this[length - 1]

Java

  • <FileName>Kt.lastChar(String) という static メソッドになる

→ Java的には Utilクラスとして再設計する方が自然なことが多い。

null安全(?. ?: !!)

Kotlin

val len = s?.length ?: 0

Java

int len = (s != null) ? s.length() : 0;

!! は Java側では 単なるNPEポイントになるため、Objects.requireNonNull 等への置き換えを検討すべきです。

when

Javaでは if-else または switch に展開されます。

Java 14+ の switch式が使える場合、可読性はかなり改善します。

コルーチン(suspend)

suspend 関数は Javaへ直接変換できません。

  • CompletableFuture
  • コールバック
  • Executor + Thread
  • Reactive(Rx等)

などへ 設計レベルで置き換えが必要です。

→ ここは「変換」ではなく「移植」です。

Kotlin Bytecode → Decompile

IDEの

  • Tools → Kotlin → Show Kotlin Bytecode → Decompile

を使うと、Kotlinが Javaからどう見えるか を確認できます。

ただし、

  • 可読性は低い
  • 保守用Javaコードとして使うものではない

ため、挙動理解専用と考えるのが正解です。

目的別の正しい選択

目的推奨
Kotlinを完全にJavaへ移植IDE変換 → 人手リファクタ
Javaから使えればOKKotlinを残しInterop対応
学習・理解目的Bytecode Decompile
コルーチン含む設計から見直す

まとめ

  • Kotlin→Javaの自動変換は 存在するが完成品ではない
  • 多くの場合は Kotlinを残してJavaから使いやすくする方が合理的
  • コルーチンや高度なKotlin構文は 設計変更が必要
  • 「変換」と「移植」は別物として考えるべき

以上、KotlinからJavaに変換する方法についてでした。

最後までお読みいただき、ありがとうございました。

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!
目次