From Java to Kotlin - The good, the bad and the misunderstood

During 2019 I started coding in Kotlin, our team had several reasons to try it out:

  • My TL has used it and had a positive experience
  • We were creating a new set of services so had a chance to embed some new languages, techniques and frameworks
  • I also heard some positive reviews

Java and I

I’ve been coding in Java for many years and it has become my main programming language in 2008. I like Java, I enjoy coding in Java, but I have to keep up. I tried Scala, but after trying to learn it I came to the realization that it is not my style. So I tried Kotlin.

Our services

We have small Spring + boot applications, implementing REST Controllers and a lot of I/O (disk and database), the services themselves are quite isolated and can be considered micro, so far we’ve written 4 of them.

Some meta about Kotlin

Kotlin is a JVM language, it is statically-typed and object-oriented. Kotlin was developed by Jetbrains, which to me shows some promise because who’s better in understanding the programmers’ needs then the ones that develop the IDE.

By describing what I liked (or disliked) I will try to give you an overview of what it’s like to program in Kotlin.

The good

Nulls

In Kotlin a variable or a method’s returned value is not necessarily nullable, in fact the intuitive code would make a variable not nullable.

var s: String = "foo"

Trying to assign null to the variable s will not compile.

However, this does compile.

var s: String? = null

Now, try to use the variable and your compiler alerts you that value may be null.

The chances of you getting a NullPointerException are limited to:

s!!.<do something>

Meaning, you are telling the compiler that you are (pretty) sure there is no null, so you’d like to use the value.

In my opinion, this approach to null and nullable variables is a lot better then the Optional object (which I really liked). My code is a lot safer because I have to think about the possible values of each variable.

Extensions!

Kotlin added functionality that allows you to extend classes by adding:

  • Methods
  • Properties

Relax, this is not a rebarnding of the inheritance. Inheritance is still there were you left it, but sometimes you have a final class and you’d like to add some functions and properties to it, right? Or even better, use a helpful method that someone else wrote. If you are like me you probably wrote many utility classes and static methods, and also used libraries like apache-commons, Guava and other popular utility libraries. But, that is a bit ugly, right?

Kotlin introduces a different approach to it, it allows you to extend classes without inheriting from them, and adding the methods and properties you just need. The following code:

fun MutableList<Int>.swap(index1: Int, index2: Int) {
    val tmp = this[index1] // 'this' corresponds to the list
    this[index1] = this[index2]
    this[index2] = tmp
}

Will allow you to do the following:

val list = mutableListOf(1, 2, 3)
list.swap(0, 2)

You are probably wondering at this point: “How it is even possible?”. You are right, it isn’t. The extension methods are compiled to static methods. But, in my opinion, this results in nicer and more readble code.

Extension properties work similarly, but note that you can only ready from them and not set their values.

The bonus is that the Kotlin distribution already contains some very useful extensions that you will enjoy without even being aware of them being extensions.

The bad

I could not find something to label has bad, but I did find some frustration.

Generics

Working with Java I would often use the wildcard types, some might say it is tricky but I find it very useful. Wildcards solve a specific problem - in Java this is not allowed:

interface Source<T> {
  T nextT();
}

void demo(Source<String> strs) {
  Source<Object> objects = strs;
}

To solve that most programmers would say that T extends Object, Kotlin came to solve this issue with a different approach but that made the wildcards not neccessary.

Out

T is not a parameter in any method, so declaring it as an out variant makes the assignment legal. This translates in Kotling to:

interface Source<out T> {
    fun nextT(): T
}

fun demo(strs: Source<String>) {
    val objects: Source<Any> = strs
}

In

On the other hand if T is only a parameter it can be declared as In making this valid:

interface Comparable<in T> {
    operator fun compareTo(other: T): Int
}

fun demo(x: Comparable<Number>) {
    x.compareTo(1.0) // 1.0 has type Double, which is a subtype of Number
    // Thus, we can assign x to a variable of type Comparable<Double>
    val y: Comparable<Double> = x // OK!
}

So, why did I catalogue generics as bad? The examples are very simple, but my classes can’t always be simple. When I had classes that are not so clean I started to get flustered with all the tutorials. Perhaps it is easier if you start with Kotlin, but transitioning from Java to Kotlin left me frustrated with generics.

The missunderstood

Mutability or Immutability?

Not so missunderstood but more “I prefer the Java style”. Variables in Kotlin have two types:

  • val - Value meaning immutable
  • var - Variable meaning the value can change

I find myself confusing these two, I prefered using Java’s final.

Varargs

I normally don’t use varargs, though it is a nice feature. But when you have generated code in your application your code may have some varargs in it without your control. Our application uses JOOQ, which generates some Java classes and apparently by default your code would have varargs usages.

No problemo my friend, all we needed was to send the array values. In Java, arrays are perfectly legal for varargs method signatures. The compiler just knows.

Not in Kotlin, I do not know why but it just doesn’t. If you really need it you have to tell the compile to expand/spread the array.

So, what we though would be:

myVarArgsMethod(myArray);

Does not compile, we had to change it to:

myVarArgsMethod(*myArray);

Yes, the asterisk (‘*’) sign means expand/spread an array. To us it just looked ugly, so we configured JOOQ to not generate varargs signatures with the property:

varargSetters = false

Well, that was a waste of half a day.

I am aware of the fact that this kind of feature is available in other languages, for example JavaScript ES6 (3 dots). But, when transitioning from Java to Kotlin it was just plain confusing.

Summary

In hindsight I look at my Kotlin experience has very positive and I find myself going to Kotlin instead of Java, when working on my projects.

We were told that we can put the Java and Kotlin classes in the same module under different directories. However, we had some difficulties with the Intellij plugin for Gradle and we ended up separating modules for code in different languages.

Following this experience, I recommend starting to use Kotlin for backend programming.

Thank you for your interest!

We will contact you as soon as possible.

Want to Know More?

Oops, something went wrong
Please try again or contact us by email at info@tikalk.com
Thank you for your interest!

We will contact you as soon as possible.

Let's talk

Oops, something went wrong
Please try again or contact us by email at info@tikalk.com