Once you compile Kotlin code to bytecode, you can use the .class files and JAR files created from Kotlin source files in Java projects. Alternatively, you may also intermix Kotlin source files, side by side, with Java source files and call Kotlin code from within Java code. We’ve already seen the mechanics to make this work. Let’s now focus on the issues with source code we may run into with such integration efforts.

Kotlin has a number of features that don’t exist in Java. Also, Kotlin is idiomatically different from Java in many ways. Thus, the Kotlin way of doing things that work elegantly and expressively when writing code in Kotlin won’t work when calling Kotlin code from Java.

If the Kotlin code you’re creating is for exclusive use with other Kotlin code, then don’t worry about calling from Java—for example, with code related to UI or controllers and services written to run within a framework. Since no Java code will directly call such code, there’s no reason to spend time and effort to make the code accessible from Java.

If you intend your Kotlin code to be used from Java code, then you have to take some extra steps for a smoother integration. If you’re working on a project where such integration is needed, then integrate early and often to make sure that the Kotlin compiler is generating bytecode that’s compatible with the needs of programmers using the code from Java. If you’re creating a library in Kotlin for third-party programmers to use from Java, then create test code in Java, in addition to creating test code in Kotlin, and run those tests using continuous integration. This will help you to both verify that your code works as intended, whether it’s called from Java or Kotlin, and also verify that your code integrates well when called from Java.

In spite of the idiomatic differences, the designers of the Kotlin language and the Kotlin standard library have provided many things to make the integration of Java code with Kotlin code as smooth as possible. When programming in Kotlin, we have to make use of some of these integration-related features so that our Kotlin code can be properly used from Java. Let’s take a look at various features that are geared toward Java to Kotlin integration.

We’ll create a Counter class in Kotlin, use it from a Kotlin script usecounter.kts and also from a UseCounter class written in Java. Using the Counter class from both Kotlin and Java will help us clearly see the extra steps we have to take for Java integration.

To practice along with the following examples, you’ll have to compile the Kotlin code and the Java code separately. Take note of the following commands. As we incrementally develop the code, you can use these commands to compile and run the code, to see the outputs.

The following commands can be used to run the files locally:

To compile the Kotlin code, use the following command:

kotlinc-jvm -d classes src/main/kotlin/com/agiledeveloper/Counter.kt

When you’re ready to execute the Kotlin script usecounter.kts, use this command:

kotlinc-jvm -classpath classes -script usecounter.kts

You can compile the Java code with this command:

javac -d classes -classpath classes:$KOTLIN_PATH/lib/kotlin-stdlib.jar \ src/main/java/com/agiledeveloper/UseCounter.java

In addition to including the path to where the bytecode generated from Kotlin source is located, we also add the Kotlin standard library to the classpath. Later, as we work on the examples, we’ll see why the Kotlin standard library is needed during compilation.

Finally, to run the Java class UseCounter, use the following command:

java -classpath classes:$KOTLIN_PATH/lib/kotlin-stdlib.jar \
com.agiledeveloper.UseCounter

Now that we’ve seen the commands to compile, let’s get down to the code. We’ll walk through several integration issues and find ways to resolve each one of them.

Using overloaded operators from Java

When programming in Kotlin we can make use of operator overloading to create concise and expressive code. Operator-overloaded functions are created using well-defined method-naming conventions, as we saw in Overloading Operators. Let’s create a Counter Kotlin data class with a plus() function to overload the + operator on instances of the class.

Get hands-on with 1200+ tech skills courses.