Blog Infos
Author
Published
Topics
,
Published
Topics
,
How Kotlin compares to Java and what features I would love to see added to Java

This is an updated version of an old post I wrote some years ago. I have been professionally working with Kotlin for the last 4–5 years in which I never really cared about Java. I am still a Kotlin fanboy but let me be clear here: This post is not intended to bash Java. Java is great and it has improved a lot in the last years.

My life as a Java developer back in the days

When I started supporting the Kotlin programming language in 2016 (oh wow, EIGHT years ago 😱), I was still doing quite a lot of Java development in the role I was working in back then. I remember that whenever I had to leave Kotlin and go back to Java, there were quite a few things I missed immediately. The good news is that a few of these things are not true anymore which is because Java has caught up quite a bit since I first wrote this article. Let’s find out what is still true and what has been improved!

The no-brainers: The new keyword and semicolons

Ever since I started with Kotlin, there were two things I always forgot when coding in Java: the new keyword for constructor calls and the slightly annoying ; that Java requires you in order to complete statements. Kotlin doesn’t have new and semicolons are optional, you will hardly ever see them used. I like that part of Kotlin as it reduces “syntactic noise“.

Data classes

In Kotlin, data classes are used for things like data containers, representing JSON objects, or returning compound objects from functions. When writing this article, Java wasn’t supporting this special type of class yet. With Java 14, record types were introduced into the language which makes this argument obsolete.

Local Functions

When we try to tidy up certain functions in our code, we tend to extract certain login into private functions that live next to the original one. Kotlin provides a simple tool we can use for this purpose and it’s called local functions. Local functions are functions that live inside other functions, which allows us to reduce the scope of helper functions quite a bit. This tends to be a much cleaner approach as those local functions can only be accessed from within the function that wraps it. Here’s an example:

This code defines a local function that is reused twice in its surrounding function. A great way to simplify your code.

fun deployVerticles() {
fun deploy(verticleClassName: String) {
vertx.deployVerticle(verticleClassName)
}
deploy("ServiceVerticle")
Single Expression Functions

In Kotlin, we can make use of a feature called single expression function. A single expression function is a function that doesn’t have a regular body. Instead, the function content is just a single expression placed behind an equals sign:

fun trueOrFalse() = Random().nextBoolean()
view raw singleexp.kt hosted with ❤ by GitHub

We can’t do that in Java. Instead, we would always have to use a function body enclosed in {}, which ranges over at least three lines. This can be considered syntactic noise but does it really make such a big difference? You decide for yourself.

To show the complete picture here, let me also mention that in fact with Java 1.8 it is possible to define lambdas that in theory can serve the same purpose. It is slightly less readable in my opinion though:

public class SingleExpFun {
private BooleanSupplier trueOrFalse = new Random()::nextBoolean;
private boolean getNext(){
return trueOrFalse.getAsBoolean();
}
}
Default Parameters

For me, one very exciting feature of Kotlin has always been the fact that you can define default parameters for functions. While in Java you need to use overloaded functions which means overall a lot more code for the same problem. Let’s look at an example:

public class Overloader {
public void test(int a, boolean printToConsole) {
if (printToConsole) {
System.out.println("int a: " + a);
}
}
public void testWithoutPrint(int a) {
test(a, false);
}
public void test(int a) {
test(a, true);
}
public static void main(String[] args) {
Overloader o = new Overloader();
o.testWithoutPrint(2);
o.test(2);
}
}
view raw overloader.java hosted with ❤ by GitHub

Job Offers

Job Offers

There are currently no vacancies.

OUR VIDEO RECOMMENDATION

Jobs

In this one, we can see a class that has a method test(int, boolean) which is overloaded for the default case of supplying no boolean argument. This becomes more relevant with an increasing number of parameters. Here’s Kotlin’s approach:

fun test(a: Int, printToConsole: Boolean = true) {
if (printToConsole) println("int a: " + a)
}
fun testWithoutPrint(a: Int) = test(a, false)
fun main(args: Array) {
testWithoutPrint(2)
test(2)
}
Calling multiple methods on an object instance using the with operator

I don’t recall why I wrote this particular part back in the days, Having worked with Kotlin for many years now, I hardly ever use the with scope function 🥲

You could say that Kotlin is a more functional language than Java. It makes heavy use of higher-order functions in many situations and provides various standard library functions for these purposes. One of my favorites is (read: was) the with function that I miss a lot whenever I can’t use Kotlin. The with function can be used to create scopes and increase the readability of code. For instance, it’s useful when sequentially calling multiple functions on a single object.

class Turtle {
fun penDown()
fun penUp()
fun turn(degrees: Double)
fun forward(pixels: Double)
}
with(Turtle()) {
penDown()
for(i in 1..4) {
forward(100.0)
turn(90.0)
}
penUp()
}
view raw withscope.kt hosted with ❤ by GitHub
Null-Safety

This is probably one of my top arguments for Kotlin. Nullability being part of the language’s type system makes so many things much more pleasant. Kotlin did a very good job by distinguishing nullable types from non-nullable ones. If you make strict use of the nullability tools provided, you may never see any null pointer exceptions again.

Lambdas and Collection Processing

Kotlin loves its higher-order functions and lambdas. As shown in the with example earlier, it is straightforward to use lambdas in your Kotlin code as Kotlin considers function first-class citizens of the language. I want to emphasize that in my humble opinion lambdas in Kotlin are much easier to work with than in Java. Let’s look at a simple example of Java’s Streams API that was introduced along with lambdas many years ago.

List list = people.stream().map(Person::getName).collect(Collectors.toList());

This is a pretty simple example of a Stream that extracts a list of names from a list of persons. Compared to what we had to write before Java 1.8, this is awesome. However, it’s too noisy compared to a real functional approach as pursued by Kotlin:

val list = people.map { it.name }
view raw kotlinmap.kt hosted with ❤ by GitHub

And another example that shows how to sum up the salaries of employees to a total amount:

int total = employees
.stream()
.collect(Collectors.summingInt(Employee::getSalary)));

And simpler in Kotlin:

val total = employees.sumBy { it.salary }
view raw kotlinsum.kt hosted with ❤ by GitHub

The Kotlin examples show how simple it can be. Java isn’t a functional language and has a hard time trying to adopt functional features like lambdas and streams as we can observe in the snippets. It can be tough to go back to Java if you ever experienced the beauty of Kotlin. It’s similar to when you need to use Eclipse after knowing JetBrain’s IntelliJ.

Let’s come to an end

I love Kotlin. I used to love Java before I knew Kotlin. I do still prefer Kotlin, but honestly can cope with both. 🚀

Java has improved quite a bit in the past few years and many features have been added to the language. Those are improved collection APIs, string APIs, switch expressions / pattern matching, records and more. I presented seven things to you that make it hard to go back from Kotlin to Java. Some of these things will never make it into the Java language, others may in the near future. Both languages are great and I am happy to have good experience working with both of them. If I can choose, I will always go with Kotlin as it’s more to the point, more intuitive and more powerful.

If you liked this article please clap below 👏🏼 and feel free to follow me fire more awesome content 🙏🏼😌

This article was originally published on proandroiddev.com on September 03, 2022

YOU MAY BE INTERESTED IN

YOU MAY BE INTERESTED IN

blog
It’s one of the common UX across apps to provide swipe to dismiss so…
READ MORE
blog
Hi, today I come to you with a quick tip on how to update…
READ MORE
blog
Automation is a key point of Software Testing once it make possible to reproduce…
READ MORE
blog
Drag and Drop reordering in Recyclerview can be achieved with ItemTouchHelper (checkout implementation reference).…
READ MORE

Leave a Reply

Your email address will not be published. Required fields are marked *

Fill out this field
Fill out this field
Please enter a valid email address.

Menu