From Java to Kotlin, with Love – Part 1

Started learning Kotlin and will be writing about my initial impressions as someone who spent almost twenty years doing Java. Java has often been criticized for its verbosity and this is exactly one of the things that Kotlin is avoiding. The Kotlin language constructs allow writing very compact and expressive code, while maintaining the benefits of strong-typing.

This post discusses one simple example of that: setting a listener on a widget, which is something everyone has written in one language or another.

In Java, one would typically write:

class ClickListener implements View.OnClickListener {
    @Override
    public void onClick(View v) {
        callSomeHandler();
    }
}
widget.setListener(new ClickListener());

With that background, I started writing equivalent Kotlin code that initially looked like this:

class ContinueListener : View.OnClickListener {
    override fun onClick(v: View) {
        callSomeHandler()
    }
}
widget.setListener(ContinueListener())

This is already shorter than the corresponding Java code in a number of ways:

  1. No semi-colons are required in Kotlin.
  2. Shorter form of object construction without “new”
  3. Method return type can be omitted if it can be inferred.
  4. Instead of “implements” Kotlin uses “:”
  5. “override” is a method modifier instead of an annotation.
  6. No need to specify “public” as it is the default.

However, this is only a start. In what follows we will use Kotlin constructs to write more idiomatic Kotlin code.

First, Kotlin provides a neat shorthand for “Single-Expression Functions”. Functions composed of a single expression can be written using the “=” notation as follows:

class ContinueListener : View.OnClickListener {
    override fun onClick(v: View) = callSomeHandler()
}
widget.setListener(ContinueListener())

Lambda expressions are first-class citizens in Kotlin and there are some very interesting uses for them. This one is pretty cool: Kotlin allows passing a lambda expression to a function that accepts a single-method interface like the one at hand. So the bit of code can be greatly simplified as follows:

widget.setListener( { v: View -> callSomeHandler() } )

Now we are down to a single line!

It gets better: we are allowed to omit the parameter type as we did with omitting the function return type:

widget.setListener( { v -> callSomeHandler() } )

But we are not using the parameter? We are allowed to use the Python-like “don’t care” notation and replace the parameter with an underscore:

widget.setListener( { _ -> callSomeHandler() } )

Even better we can eliminate the left hand:

widget.setListener( { callSomeHandler() } )

One last nicety is that since the lambda expression is the only argument to the function we can eliminate the parenthesis:

widget.setListener { callSomeHandler() } 

Pretty neat!

Leave a comment