Codementor Events

Interoperability between Java and Kotlin

Published Jan 24, 2019

Learn about interoperability between Java and Kotlin in this article by Abid Khan, an application developer and test engineer with over 10 years of experience, and Igor Kucherenko, an Android developer at Techery, a software development company that uses Kotlin as the main language for Android development.

Interoperability

Interoperability refers to the ability to use both the Java and Kotlin languages in a single project. You can call Kotlin functions in Java as well as Java methods and variables in Kotlin code. This gives you the advantage of code reusability. For example, if you have an existing Java project with classes and functions, then you do not need to rewrite everything in Kotlin from scratch. Instead, you can use each and every line of Java code in Kotlin and start writing new functionalities here. Similarly, you can call Kotlin code in Java.

You’ll start by calling Java static variables and functions in Kotlin, then move onto the Java collections, and explore some examples of calling Java classes in Kotlin. You’ll then see how to handle the Kotlin reserve words and utilize Kotlin written code in Java with variables, functions, extension functions, and the Kotlin class. You’ll also see the replacement of Kotlin filenames and function names using a Kotlin-provided JVM annotation. Finally, you’ll have a quick look at how to call Kotlin's object class in Java.

Technical requirements

Other than IntelliJ IDEA, this article does not require any specific installations. The code for this article can be downloaded from the GitHub repository: https://github.com/PacktPublishing/Hands-On-Object-Oriented-Programming-with-Kotlin/tree/master/src/main/kotlin/Chapter08.

Calling Java code in Kotlin

In this section, you’ll learn how to use Java code in a Kotlin file. For the sake of simplicity, begin by creating a package and adding both Java and Kotlin files in one place, as you know that Kotlin makes it possible to keep both Java and Kotlin files in one project. So, you have two Java classes, called CallJava and Shape, and in the same folder you have one Kotlin file, called FromKotlin:

1.png

Start with the Java static variable and function.

Calling static variables and functions

Open the CallJava file and add one static variable message:
public static String message = "Hello from Java";
Include one static method, add, which adds two variables and displays a message on the screen:

public static void add(int i, int j){
    System.out.println(i + " + " + j + "=" + (i + j));
}

Calling a static function or variable from Java to Kotlin is very simple. To do this, use the Java filename as a reference and call the required function or variable. Look at the following Kotlin example to call the Java static variable:

fun callStaticFromJava() {
    var message = CallJava.message
    println("Java Message : ${message}")

    CallJava.add(4,5)
}

To call the static variable, use the Java class name as a reference along with the CallJava.message variable name. This value can be assigned to a local variable and used as a normal Kotlin variable. Similarly, call the Java static function using the class name as a reference along with the function name. Call the add method from Java using CallJava.add(4,5) and pass two integer variables as parameters.

Calling the Java collection in Kotlin
Create a method in Java that returns an arrayList of integers:

public static ArrayList<Integer> getIntList(){

    ArrayList<Integer> integers = new ArrayList<>();
    integers.add(1);integers.add(2);integers.add(3);

return integers;
}

getIntList returns an array that contains three elements. Call this function in Kotlin to access the list and add more elements in it:

var list = CallJava.getIntList()
//var list: ArrayList<Int> = CallJava.getIntList()

list.add(4)
for (element in list) {
println("Element $element")
}

CallJava.getIntList() returns ArrayList, which can be assigned to a list type of variables. You can explicitly declare the type of the list using the ArrayList<Int> name:

var list: ArrayList<Int> = CallJava.getIntList()

Alternatively, you can directly assign a list to the variable, and Kotlin will figure out the list type by itself:

var list = CallJava.getIntList()

You can treat this as a normal immutable list and add or remove elements.

Reserve words in Kotlin
There are a number of keywords that are used by Kotlin for its internal purposes and these cannot be used as variable names and function declarations. Some of the reserve words are as follows:

in, is, as, object, val, var, for, fun, interface, when 

There are reserve words that Kotlin has reserved for itself, but when it comes to Java, most of Kotlin's reserved keywords are normal variables for Java. See the following example:

public static void is(){
    System.out.println("is is a reserved keyword in Kotlin :-) ");

}

public static void var(){
    System.out.println("var is a reserved keyword in Kotlin :-) ");
} 

var and is are normal keywords for Java but not for Kotlin. If you need to call a function with Kotlin's reserved words, you need to use a backtick operator. See the following Kotlin example:

CallJava.`is`()
CallJava.`var`()

Use the backtick (``) operator to call Java functions whose names are reserved keyword words for Kotlin. Here’s a look at more examples to see how to use Java functions whose names contain Kotlin's reserved keywords.

Write a function in Kotlin that takes input from the user and displays a message on the screen. Kotlin uses a Java-provided Scanner class to take input from the keyboard, as follows:

fun inputFromKeyboard() {
println("Enter Your name .... ")
val scanner = Scanner(System.`in`)
println("My name is ${scanner.nextLine()}")
}

The Scanner class takes System.in as an input stream in order to scan input. As you can see, in is a reserved keyword but you can use this using backticks operator. Similarly, you can use all reserved keywords as a function or variable name in this way:

fun `in`(){
println("I am in function")
}

fun `as`(){
println("I am as function")
}

fun `object`(){
println("I am object function")
}  

var `var` = "Reserved keyword var"
var `object` = "Reserved keyword object"

Java classes in Kotlin

Now, explore how to create a Java class object in Kotlin. To do this, create a Shape.java file with three properties: height, width, and name with getters and setters:

public class Shape {

private int width;
private int height;
public static final double PI = 3.1415;
private final String name;

public Shape(int width, int height, String name) {
this.width = width;
this.height = height;
this.name = name;
    }
public final int getHeight() {
return this.height;
    }

public final void setHeight(int value) {
this.height = value;
    }

public final String getName() {
return this.name;
    }
public final void shapeMessage() {
        System.out.println("Hi i am " + this.name + ", how are you doing");
    }
}

Creating an instance of the Java class in Kotlin is similar to creating an instance of the Kotlin class. See the following example:

val shape = Shape(5,10,"Square")

shape is an instance of the Shape class, which can access functions and update the class properties:

shape.shapeMessage()
shape.height = 10
println("name ${shape.name} height = ${shape.height}")

Calling Kotlin code in Java
Calling Kotlin code in Java is similar to calling Java code in Kotlin, except for a few things that must be considered before beginning. Start with a function call. To do this, create a new folder and add both Java and Kotlin files in one place:

2.png

Calling the Kotlin function

Now, create two functions in Kotlin, add and addAndReturn. The add function takes two integer variables, adds them, and prints them on the screen, while addAndReturn adds two values and returns the result:

fun add(a : Int, b : Int) {
println("Result of $a + $b is ${a+b}")
}


fun addAndReturn(i: Int, j: Int): Int {
return i + j
}

You can call each Kotlin function using the filename as a reference. CallKotlin.kt is a file that contains a Kotlin function. When calling a Kotlin function in the Java file, it is important to remember that you must add the kt keyword with the Kotlin filename to call your desired function. For example, you can call the add function using CallKotlinKt.add. See the following example of the Java file:

public static void main(String args[]) {

    CallKotlinKt.add(5,5);

int result = CallKotlinKt.addAndReturn(5,5);
    System.out.print("From Kotlin: result = " + result);

}

Execute this code and it will display the following output:

Result of 5 + 5 is 10
From Kotlin: result = 10

Extension functions

It is also possible to call Kotlin's extension function in Java. In Kotlin, create an extension function that takes one parameter, multiplies the value by 2, and returns the result. See the following Kotlin extension function:

fun Int.doubleTheValue() = this * 2

Create this extension function in the Kotlin class and call this function into Java's main function using the CallKotlinKt.doubleTheValue function. See the following example:

public static void main(String args[]) {
int i = 5;
int result = CallKotlinKt.doubleTheValue(i);
    System.out.print("Kotlin's Extension function, Multiply "+ i +" with 2 = "+ result);
}

As a result, the output will be as expected:

Kotlin's Extension function, Multiply 5 with 2 = 10

Functions with mutable collections

Create a mutable list in the getMutableList function and return the list, as follows:

fun getMutableList() : MutableList<Int> {
val list = mutableListOf(1,2,3,4,5)
return list
}

Create a listFromKotlin variable in Java and assign a list to this variable using the CallKotlinKt.getMutableList function from Kotlin. See the following example:

public static void main(String args[]) {

    System.out.print("Kotlin mutable list");
//List<int> listFromKotlin = KotlinToJavaKt.mutableList();

List<Integer> listFromKotlin = CallKotlinKt.getMutableList();
    listFromKotlin.add(6);
for (int i = 0; i < listFromKotlin.size(); i++) {
        System.out.println("Element " +  listFromKotlin.get(i));
    } 
}

Notice that Kotlin is not familiar with primitive data types. As a result, you must provide a list of Integer classes:

//List<int> listFromKotlin = KotlinToJavaKt.mutableList(); // list of int
List<Integer> listFromKotlin = CallKotlinKt.getMutableList(); // List of Integers

Functions with immutable collections

Now, see how to get an immutable list from the Kotlin function to Java. Create an immutable list in the getImmutableList function and return the list:

fun getImmutableList() : List<Int> {
val list = listOf(1,2,3,4,5)
return list
}

Get a Kotlin list by calling the getImmutableList function and displaying list elements. See the following example:

public static void main(String args[]) {
    System.out.println("Kotlin immutable list");

    List<Integer> listFromKotlin = CallKotlinKt.getImmutableList();

for (int i = 0; i < listFromKotlin.size(); i++) {
        System.out.println("Element " +  listFromKotlin.get(i));
    }
}

Since you know that the immutable list cannot be updated, you can read the list but cannot add or update elements. Once the immutable list is called in Java, it is the programmer's responsibility to verify the type of list before updating it because the Java compiler could not catch the error at compile time. If you try to add an element to the immutable list of Kotlin, you’ll get the following result:

List<Integer> listFromKotlin = KotlinToJavaKt.getImmutableList();
listFromKotlin.add(6);

This shows that Java will throw the java.lang.UnsupportedOperationException exception at runtime and the application will crash.

Functions with the JVM annotation

You can call the Kotlin function in Java using the filename as a reference. You also need to add the kt keyword with the filename; for example, KotlinToJavakt. However, Kotlin makes it possible to assign different names to your file and function names. Create a new class named CallKotlinUtil.kt and add the following code:

@file:JvmName("KotlinUtil")
package Chapter08.CallKotlinFromJava

fun addition (a: Int, b : Int){

println("Result of $a + $b is ${a+b}")

}

Use the @file:JvmName("KotlinUtil") annotation at the beginning of the file. Now, you can call the addition function using KotlinUtil.addition instead of CallKotlinUtilkt.addition. See the following example:

public static void main(String args[]) {
    KotlinUtil.addition(4,4);
}

This is a much better and cleaner approach. You can now specify the Kotlin filename for the Java class to use as a reference. Kotlin also makes it possible to specify the name of the Kotlin function for Java. Create an addition function in the Kotlin file and add the @JvmName annotation with a new function name, as follows:

@file:JvmName("KotlinUtil")
package CallKotlinFromJavaPackage

@JvmName ("addDouble")
fun addition (a: Double, b : Double){
println("Result of $a + $b is ${a+b}")
}

Now, you can call the addition function using addDouble. See the following example:

public static void main(String args[]) {
    KotlinUtil.addDouble(5.0, 5.0);
}

Calling the Kotlin class

In this section, you’ll see how to call the Kotlin class in Java. Create a Shape class in Kotlin with three properties, height, width, and area, and two functions, shapeMessage and draw:

class Shape(var width : Int, var height : Int , val shape: String) {

var area : Int = 0
fun shapeMessage(){
println("Hi i am $shape, how are you doing")
    }
fun draw() {
println("$shape is drawn")
    }

fun calculateArea(): Int {
area = width * height
return area
}
}

You can create an instance of the Kotlin class in the same way as you create an instance of a normal Java class. See the following example:

class FromKotlinClass {

public void callShpaeInstance() 
    {
        Shape shape = new Shape(5,5,"Square");

        shape.shapeMessage();
        shape.setHeight(10);
        System.out.println(shape.getShape() + " width " + shape.getWidth());
        System.out.println(shape.getShape() + " height " + shape.getHeight());
        System.out.println(shape.getShape() + " area " + shape.calculateArea());

        shape.draw();
    }
}

Create a shape instance by adding constructor parameters. You can use the shape instance to access all class properties using getter and setter methods. You can also call the shapeMessage or draw functions of the Shape class using the shape instance.

Calling the Kotlin singleton class

You can also call the Kotlin singleton class in Java. Create a singleton class in Kotlin using the object keyword:

object Singleton {
fun happy() { 
println("I am Happy")
    }
}

Furthermore, call the Singleton class and the happy function in Java using the INSTANCE keyword:

public static void main(String args[]) {
    Singleton.INSTANCE.happy();
}

Notice that you do not need to use a Kotlin filename as a reference, but the object class name, Singleton, is sufficient. You can skip the INSTANCE keyword as well. Add the @JvmStatic annotation at the beginning of the function signature:

object Singleton {

fun happy() {
println("I am Happy")
    }

@JvmStatic fun excited() {
println("I am very Excited")
    }
}

Once this is done, call the excited function directly without using the INSTANCE keyword in Java:

public static void main(String args[]) {
    Singleton.INSTANCE.happy();
    Singleton.excited();
}

Execute the Java program and verify the output, as follows:

I am Happy
I am very Excited

If you found this article interesting, you can explore Hands-On Object-Oriented Programming with Kotlin to learn everything you need to know about object-oriented programming with the latest features of Kotlin 1.3. Hands-On Object-Oriented Programming with Kotlin provides you with a thorough understanding of programming concepts, object-oriented programming techniques, and design patterns.

Discover and read more posts from PACKT
get started