Kotlin and Java interoperability
This is the third post in the "Kotlin, the essence of Java" series. Click the link for the whole story or keep on reading about this particular topic.
Kotlin is a JVM language with strong ties to the Java language and v.v. Under normal circumstances Java and Kotlin classes can just be used without any extras. Some Kotlin features are not present in de Java language, but I will show you how to use those features from Java.
Setting up your project
I use Maven in my projects and Baeldung has a post on how to setup your project, so why copy it here? Read it here:
And you clone my project on Github containing the examples in this post and unit tests to see them in action:
I will use this Person
class in my examples:
class Person(
var name: String,
var birthDate: LocalDate,
val userID: String
) {
fun age(refDate: LocalDate = LocalDate.now()) =
Period.between(birthDate, refDate).years
}
Creating objects and interacting with them
Kotlin classes can be instantiated like a Java class. In Java, you can just write
Person kotlinPerson = new Person("Kotlin Person",
LocalDate.of(2000, 1, 1),
"kotlin");
Basic interaction is like you'd expect in Java:
kotlinPerson.getName();
kotlinPerson.setName("Sander");
kotlinPerson.getUserID();
kotlinPerson.setUserID(); // gives a compiler error, no setter because of 'val'
From the outside you can't tell if this is a Kotlin of Java object. Exactly why I think Kotlin is a great replacement for Project Lombok (see Kotlin, the essence of Java).
Default arguments
The age(...)
function in the Person class has a default argument. But if you have this class up in your IDE, you will see that code completion will only show an age(LocalDate)
function. This is because Java doesn't understand default arguments, just arguments.
The way Kotlin offers this in a usable way in Java is with the @JvmOverlads
annotation:
@JvmOverloads
fun age(refDate: LocalDate = LocalDate.now()) =
Period.between(birthDate, refDate).years
Now, if you use code completion on the object, you will see two overloaded functions, but without actually writing them.
Default arguments in constructors
Let's say you want the userID
to be generated if not supplied to the constructor. Because userID
is a parameter to the constructor, we can add a default argument (in this case a random UUID):
class Person(
var name: String,
var birthDate: LocalDate,
val userID: String = UUID.randomUUID().toString()
)
To use it from Java, you would probably expect a @JvmOverloads
annotation on the line above, same as with the age(...)
function in the previous example. Unfortunately that would annotate the class, not the constructor.
Kotlin's constructor in this example is implicit. To annotate it, we have to make it explicit using the constructor
keyword and then add the annotation to it:
class Person @JvmOverloads constructor(
var name: String,
var birthDate: LocalDate,
val userID: String = UUID.randomUUID().toString()
)
Now we can create a Person
from Java without supplying the userID
.
Next steps
This is the last part in the "Kotlin, the essence of Java" series. You now have enough examples to start using Kotlin in your project.
Of course there's much more to Kotlin than I've shown so far, so take a look at the topics to broaden your Kotlin knowledge:
- Inline functions
- Streams
- or follow the Kotlin tag