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の object や companion 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の「チェック例外」という概念がありません。
@Throws は Java向けに 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から使えればOK | Kotlinを残しInterop対応 |
| 学習・理解目的 | Bytecode Decompile |
| コルーチン含む | 設計から見直す |
まとめ
- Kotlin→Javaの自動変換は 存在するが完成品ではない
- 多くの場合は Kotlinを残してJavaから使いやすくする方が合理的
- コルーチンや高度なKotlin構文は 設計変更が必要
- 「変換」と「移植」は別物として考えるべき
以上、KotlinからJavaに変換する方法についてでした。
最後までお読みいただき、ありがとうございました。










