何となく実験してみたのでメモ。
[やりたいこと]
Kotlinのプロジェクトで、Javaのライブラリやクラスを呼び出すというのはよくある。公式ドキュメントでも相互運用性の話が書かれている。
import java.util.ArrayList fun main() { val list = ArrayList<Int>() list.add(0) println("list=${list}") // list=[0] list[0] = 1 println("list=${list}") // list=[1] }
反対に、JavaからKotlinのコードを呼び出すこともできる。その場合、例えばKotlinのファイル名がMyObject.kt
だった場合、Java側で呼び出す際はMyObjectKt
というクラス名になる。
// app.kt package org.example fun getTime() { /*...*/ } // App.java public static void main(String[] args) { System.out.println(org.example.AppKt.getTime()); }
ここまでは以前Kotlinを勉強した際に知っていたのだが、同じプロジェクト内にKotlinのソースコードとJavaのプロジェクトを同居させるのはできるのか?と思って気になって調べたら、ちゃんと公式ドキュメントに答えが書いてあった。
[やってみた]
公式ドキュメントによると、単にsrc/main/kotlin
というディレクトリの横にsrc/main/java
というディレクトリを作って、Javaのコードを置いておけば良いらしい。
というわけで実際にプロジェクトを作って試してみる。
$ mkdir kotlin-and-java $ cd kotlin-and-java $ gradle init Starting a Gradle Daemon (subsequent builds will be faster) Select type of project to generate: 1: basic 2: application 3: library 4: Gradle plugin Enter selection (default: basic) [1..4] 2 Select implementation language: 1: C++ 2: Groovy 3: Java 4: Kotlin 5: Scala 6: Swift Enter selection (default: Java) [1..6] 4 Split functionality across multiple subprojects?: 1: no - only one application project 2: yes - application and library projects Enter selection (default: no - only one application project) [1..2] 2 Select build script DSL: 1: Groovy 2: Kotlin Enter selection (default: Kotlin) [1..2] 2 Generate build using new APIs and behavior (some features may change in the next minor release)? (default: no) [yes, no] Project name (default: kotlin-and-java): Source package (default: kotlin.and.java): com.kdnakt.kotlin.and.java > Task :init Get more help with your project: https://docs.gradle.org/7.5.1/samples/sample_building_kotlin_applications_multi_project.html BUILD SUCCESSFUL in 47s 2 actionable tasks: 2 executed
これで以下のようなKotlinのコードが自動的に実装される。
// kotlin-and-java/app/src/main/kotlin/com/kdnakt/kotlin/and/java/app/App.kt package com.kdnakt.kotlin.and.java.app import com.kdnakt.kotlin.and.java.utilities.StringUtils import org.apache.commons.text.WordUtils fun main() { val tokens = StringUtils.split(MessageUtils.getMessage()) val result = StringUtils.join(tokens) println(WordUtils.capitalize(result)) }
この横に、MyObject
というJavaクラスを作ってみる。Kotlin側で出力結果を確認しやすいように、toString()
をオーバーライドしておく。
// kotlin-and-java/app/src/main/java/com/kdnakt/java/MyObject.java package com.kdnakt.java; public class MyObject { private String name; private String value; public MyObject(String name, String value) { this.name = name; this.value = value; } @Override public String toString() { return "MyObject{" + "name='" + name + '\'' + ", value='" + value + '\'' + '}'; } }
ファイル階層は次のようになる。
Javaで実装したMyObject
クラスをKotlin側で呼び出すと、以下のようになる。
// kotlin-and-java/app/src/main/kotlin/com/kdnakt/kotlin/and/java/app/App.kt package com.kdnakt.kotlin.and.java.app import com.kdnakt.java.MyObject fun main() { // Javaのクラスを呼び出す val obj = MyObject("key", "foo") println(obj) // MyObject{name='key', value='foo'} }
同じプロジェクトのKotlinのコードからJavaのクラスを問題なく呼び出すことができた。