Open In App

Java Interoperability – Calling Kotlin from Java

Last Updated : 02 Aug, 2019
Improve
Improve
Like Article
Like
Save
Share
Report

When Kotlin was developed, it worked solely on JVM, hence it provides a complete set of features that makes calling Kotlin from Java, quite easy. For example, objects of Kotlin classes can be easily created and their methods can be invoked in Java methods. However, there are some rules about how Kotlin code can be used in Java.

Kotlin Properties –

A property in Kotlin is defined in Java as a private field with the same name as that of the property, and a getter and setter function, with get and set prefixed to the property name. This private field exists in the java class generated from the kotlin file.
For example, the property var age: Int, gets compiled to the following code in Java –




private int age;
  
public int getAge(){
  return age;
}
public void setAge(int age){
  this.age = value;
}


These properties can be accessed using the object of the class, in the same way as done in Java. However, if the property name begins with is, then the get keyword is skipped in the name of the getter function.

Package-level Functions –

All the functions defined in a Kotlin file, within a package are compiled into static methods in Java within a class whose classname is a combination of package name and the filename.

For example, if there is package named as kotlinPrograms and a Kotlin file named as firstProgram.kt with the following contents.




// Kotlin file
  
package kotlinPrograms
  
class myClass {
  
  fun add(val a:Int, val b:Int): Int {
   return a+b;
 }
}


This function can be invoked in Java using the following syntax:

// Java
new kotlinPrograms.firstProgram.myClass()
kotlinPrograms.FirstProgramkt.add(3, 5);

We can change the name of the generated Java class using @JvmName annotation.




// Kotlin file
@file : Jvmname("Sample")
  
package kotlinPrograms
  
class myClass {
  
  fun add(val a:Int, val b:Int): Int {
   return a+b;
 }
}


This function can be invoked in Java using the following syntax:

// Java
new kotlinPrograms.firstProgram.myClass()
kotlinPrograms.Sample.add(3, 5);

However, having multiple files with the same name is logically an error. To overcome this problem, Kotlin provides its compiler the ability to create a facade class that has a particular name and contains all the declarations from all the files with have the same name. To enable the creation of such a facade class, the annotation @JvmMultiFileClass annotation in all of the files.

Example




// Kotlin code
@file:JvmName("Sample")
@file:JvmMultiFileClass
  
package sample.example
  
fun print(){.......}


Another Kotlin file –




// Kotlin code
@file:JvmName("Sample")
@file:JvmMultiFileClass
  
package sample.example
  
fun printString(){.......}


Both these functions can be invoked in Java using the following syntax:

// Java calling statements
sample.example.Sample.print()
sample.example.Sample.printString()

Static fields –

Properties in Kotlin that are declared within a named object or a companion object, are used as static fields in Java. To access these fields in Java, these must be annotated with @JvmField annotation , lateinit modifier or must be declared with a const modifier.

Example:




// filename Program.kt
  
// Property in a companion object
class abc{
 companion object{
      @JvmField
      val x = 5;
  }
}
  
// A constant property
const val y = 5;


//Java Usage
abc.x
Programkt.y

Static methods –

The methods defined at the package level are always generated as static methods in the Java file. Also the methods defined in named objects and companion objects if annotated with @JvmStatic annotation are generated as static methods. This annotation declares the following function to be a class function.

Example for the companion object




// filename Programs.kt
class abc {
  companion object {
     @JvmStatic fun add(val a:Int, val b:Int):Int{
        return a+b;
      }
     fun sub(val a:Int, val b:Int):Int{
        return a-b;
      }
   }
}


//Java usage
abc.add(); // works fine
abc.sub(); // error: not a static method
abc.Companion.add(); // instance method remains
C.Companion.sub(); // the only way it works

Similarly, it works for named object.

Instance Fields –

Kotlin provides a feature to use a property as an instance field in Java. To do this annotate the property with @JvmField annotation. These instance fields have the same visibility as the Kotlin property. However, the property must have a backing field and must not be declared with private, open, const and override modifiers.

Example




// Kotlin code
class ABC(c: Int){
 @JvmField val id = c
}


This property now can be accessed in Java as

ABC obj = new ABC(5);
System.out.println(obj.id);

Checked Exceptions

All the exceptions in Kotlin are unchecked. Thus, Java signatures of the Kotlin functions neither declare nor handle the exceptions thrown. To overcome this problem, the Kotlin function must be annotated with the @Throws annotation specifying the exception that will be thrown. In this case, the Java signature will also declare the function to be thrown.

Example




// A sample Kotlin function
  
// filename program.kt
package Sample
  
fun print(){
 throws IOException()
}


// Java code trying to call the above  function
try {
    Sample.Program.print(); 
    }
   // This statement causes error because does not declare IOexception in throws list
   catch(IOException e) { 
}

So, to resolve error we declare @Throws annotation in the top.




// Overcoming the problem with @Throws annotation
package Sample
  
@Throws(IOException::class)
fun print()
{
throws IOException()
}




Like Article
Suggest improvement
Previous
Next
Share your thoughts in the comments

Similar Reads