Everything wrong with Kotlin | Java vs Kotlin | A hands-on comparison

Guneet Singh
6 min readOct 22, 2020

After everything so good with Kotlin, what’s wrong with it? Can Kotlin be the next java? It's quite a while now but after Google making Kotlin a first-class language for writing Android apps, shouldn’t the whole world just copy that? Here is a caveat…

If everything seems to be great, you are probably just getting started.

With no doubt, Kotlin is a very elegant language, and most importantly Kotlin extension functions have made the work of a developer a lot easier and faster that one can just build up the logic as he/she codes as extension functions like Any.apply() and Any.also() makes it possible to build up logic on the fly (What?). It actually means that you don't really need to declare variables before using it! Kotlin also keeps your code cleans removing boilerplates making it more readable and concise.

But even after a lot of great features, why is the world taking time to adopt it or why are people still writing in java? The reason is more than just the legacy java code!

1. Kotlin has no package-access-modifier

Although Kotlin has the internal keyword which it suggests as a replacement to package-visible access modifier, it doesn’t completely emit the same behaviour because members with internal visibility are visible within the same module and a module is defined as:

A module could be an IntelliJ IDEA module, a Maven project, a Gradle source set (with the exception that the test source set can access the internal declarations of main) or a set of files compiled with one invocation of the <kotlinc> Ant task.

When an application scales the line of code increases significantly hence for better code management, application developers look to cut out the unnecessary accesses between different parts of the code to make it more cohesive and reduce coupling the two general goals in software engineering towards high maintainability and package access is a desirable feature.

But what really makes package visibility a need for developers is while testing. Kotlin has no way to specify access limited only to test sources in one module leading to more public accessed resources whereas in java:

With package-visible classes you can write test cases in the same package in different source sets (e.g. test,androidTest,etc.) while hiding them completely with the rest of the world.

EDIT: Though Android lib has made an annotation @VisibleForTesting to relax visibility restrictions while testing, it's still not the same as the package access modifier in java but can be used as a workaround in kotlin.

It can be understood with the below comparison, Note that the access outside package fails to compile.:

Comparision within package and outside package visibility

2. Whereas Java 9+ has a robust module system

Java has gone one step further in making the visibility even more explicit with the introduction to modules in Java 9. According to Java’s own references, Java modules were built under the Project Jigsaw and Java development team took almost a decade to build the Java Platform Module System (JPMS). Although the time they took was mainly due to the acceptance process, the result really works for all. It provides fine-grained control over modularization which increase the scalability of an application at any time. With a module descriptor i.e. module-info.java at the root of the module (e.g. maven modules) one can specify directives like Exports, Exports … To, Uses, and much more. You can read more about it here.

3. No Checked exceptions

Some may argue that it’s a good thing to not catch every checked exception for the sake of less boilerplate and code readability which kotlin nevertheless provides. But checked exceptions are there for a reason and not handling them could lead to unexpected app crashes. Unfortunately, with ignored Checked Exceptions at compile-time, kotlin makes it difficult to handle unwanted behaviours.

One example of this is:

Kotlin:

val thread = Thread { Thread.sleep(100000) }
thread.start()
Thread{
Thread.sleep(1000)
thread.interrupt()
}.start()
// app crashes due to unandled exception but no error at compile //time

Java:

Thread thread=new Thread(()-> {
try {
Thread.sleep(100000);
} catch (InterruptedException e) {
System.out.println(e.getMessage());
}
});
thread.start();
new Thread(()-> {
try {
Thread.sleep(1000);
thread.interrupt();
// Exception must be handled before successful compile
} catch (InterruptedException e) {
System.out.println(e.getMessage());
}
}).start();

4. Null checks vs Optional in java

Again, this is also related to unwanted exceptions as asserting not-null can surely leave you without NullPointerException but with the other IllegalStateException:

var something:String?=null
val lenght=something!!.length
......java.lang.IllegalStateException: [...] must not be null

Whereas java’s Optional type checking system plays safer:

Optional.of("Something").ifPresent((a-> {
//do with something
}));

5. Most of the libraries/frameworks are made with java in mind and not kotlin

Last but an important limitation of using kotlin over java that one may realize eventually is the better support. Most of the frameworks or libraries are written for java is not intended to work with Kotlin and are better compatible with java. My own experience with Spring which itself has support for Kotlin still doesn’t go well as I had to include extra dependencies and plugins to make my code work e.g. kotlin-maven-allopen, kotlin-maven-noarg, kotlin-maven-plugin, etc. which otherwise would be pretty straightforward. So there might be a workaround if something fails and kotlin is officially supported but if not, the options you are left with is to either look for another similar library/framework that supports kotlin which in most cases, is not possible (e.g. using AWS SDK) or write code in java.

6. Kotlin is just a wrapping over Java

If you dig inside you will see that all the abilities that Kotlin has over Java are not fundamental but only provides a compile-time profit. One example of it is NonNullable fields in kotlin. I was working on a spring-boot application, when I found some of my non-nullable fields as null in the debugger because spring, for the most part, uses reflection to assign value to variable something that Kotlin has no control and one example of it was @Enitity fields on a @PrePersist hook (as I said even spring also fully supports kotlin but it was not actually designed for Kotlin and you can keep finding this unexpected behaviour everywhere). See the snippet below yourself:

Another behaviour that bothered me was when I used a not-null field in a @RequestBody object for a @RequestController argument and jacksonlibrary (spring uses jackson to convert between json and Java objects) gave me an kotlin.NullPointerException because it tried to assign a non-nullable property to not-found-hence-null. Although it was not unexpected, seeing it working for some section of the same framework is not something one might expect!

So, Why Kotlin became so popular?

What justifies Google’s action to make Kotlin it’s the first-class language for android is mainly due to its extension functions as Android has minimum API level restrictions to use the APIs of new Java releases e.g. most features of Java 8 (which itself was released in 2014) requires API level 23 (Marshmallow). Although now Google itself has come up with a recent alternative as Android Studio now has built-in support for Desugaring that makes it possible to use Java 8 APIs for apps that support older versions of Android. With that said, using Java for android development was basically using a 9-year-old library APIs (which is 2011, when Java 7 was first released) if one doesn’t count the compile-time optimization that Android Studio provides since always.

Whereas the comparison of kotlin just with java won’t be justified itself as Kotlin also lets you write in JavaScript, C, Swift/Objective-C and even more projects. It also brings Multiplatform projects which aims to reduce time spent writing and maintaining the same code for different platforms (currently in alpha).

Conclusion

While comparing Java with Kotlin, apart from Android development, where kotlin is surely better than the rest, it's always about whether to go for a sweet-syntactic-sugar no-boilerplate code with kotlin with all the caveats we just talked about or look for high-level robustness that Java always provide.

Although the scope of Kotlin seeing its rapidly increasing popularity can’t be seen as a replacement to Java.

--

--