kotlin vs java

Kotlin versus Java: Comparing and contrasting

High-level programming languages have been essential in software engineering and computer science. They allow developers and engineers to focus on business values and goals and less on the underlying hardware.

Both Java and Kotlin languages offer significant benefits to developers in their own way. For example, Java has a long history of successful enterprise applications and solutions. However, Kotlin tends to solve the often painful problem of debugging when it’s added to Java programs.

This article will explore Java and Kotlin as the two most notable high-level programming languages used to program the Java Virtual Machine (JVM). We’ll contrast the languages based on their features and their value for the developer experience. 

Programming JVM

The JVM is the platform that various high-level programming languages target when they compile. The JVM is responsible for reading the bytecode of the higher-level language and executing it on the operating system and hardware’s specific instruction set. Since the introduction of JVM, various languages have been created to support JVM development. Among these are Scala, Groovy, and the top choices, Java and Kotlin.

Let’s dive into Kotlin and Java.

Kotlin

Kotlin is a statically-typed language created by JetBrains, the makers and distributors of the famous IntelliJ IDEA IDE for Java. Kotlin aims to help improve the experience of developing with Java within IntelliJ IDEA. One of the ways Kotlin does this is by being compatible with the Java source code. The Kotlin code transpiles to Java, enabling developers to use Kotlin as needed within their larger Java projects.

Apart from this, Kotlin offers various benefits to the Java developers who require boilerplate code:

  • Null safety and support to avoid NullPointerException altogether
  • Data classes, where you don’t need to provide getter/setters or toString implementations
  • Advanced use cases and applications of streams
  • Coroutines to provide support for asynchronous programming
  • String interpolation
  • Operators for null safety, value checks, and Elvis operator

Kotlin either prevents the code from being compiled or prints warnings if it detects code smells, which can be configured by the developer. Code smells is a colloquial term coined in the engineering world for the bad design patterns in the program. 

For example, not checking whether or not the object being used is a null is considered a code smell. We can solve it by either adding a code that checks for nullness or by changing the type of the argument to a non-nullable. Kotlin addresses this by differentiating between nullable and non-nullable types. If a parameter is non-nullable, then it’s guaranteed to never have a null value. The Language will check if you are assigning a null value to it by mistake, and would show this error on compile time.

Java

As the name suggests, Java is the most widely used programming language for JVM. Java is a statically typed programming language and provides a robust type system with primitive and class-based types. It offers flexibility for developers to write object-oriented programs without manually managing memory. 

Software engineers love Java because it:

  • Offers object-oriented programming
  • Provides memory management out of the box
  • Supports most common APIs and SDKs, such as networking, file system operations, and I/O
  • Offers generics to support advanced programming

Each latest release of Java has offered several improvements and new features, such as the addition of Lambdas and Streams in Java 8.

However, although Java is advanced, it still lacks many features and language constructs required by software engineers in various cases. One example is operator overloading. Java doesn’t offer this, so Kotlin brings this feature to the JVM ecosystem.

Let’s more closely explore these two languages and see how they can benefit different areas of software development.

Differences between Java and Kotlin

Kotlin is a superset of the Java language and as such offers several benefits over existing Java features. To explore these benefits, we can use the online Kotlin playground to see the Kotlin features first-hand and test the code in the following sections.

Null safety

Java programs are famous for their NullPointerExceptions (NPEs). In Java, variables can be null when they aren’t initialized. A NullPointerException is raised if we attempt to read a null variable’s properties or a call method on it.

We can avoid the NPE in Java by checking if the variable is null or not:

if (variable == null) {
    // show the message in a safe manner
} else {
    // use the variable
}

We could also wrap the code in a try…catch block and show an error message if the NPE is raised. However, with this approach, we can’t easily debug when multiple variables are prone to NPE. The if…else block approach is a more precise test for null variables, but it makes the program too verbose with boilerplate code.

Kotlin helps avoid the NPE by adding nullability to the types. The variables can’t hold a null value by default. So, when we’re writing the code, Kotlin can easily find the variables or can have a null value and stop the compilation. For example:

var name: String = null

This wouldn’t compile, and the error message “Null can not be a value of a non-null type String” would be displayed. We would no longer need to write a conditional around our name variable, as Kotlin guarantees this variable to have a value defined on runtime.

Asynchronous programming

Another exciting feature that’s valuable for developers, especially for web applications, is asynchronous programming. In Java, we can use the background threads from the thread pool to run expensive operations. These operations can be calls to external services, resources, or CPU and I/O-bound operations. When we’re running web applications or UI applications, like mobile or desktop apps, running a long operation can decrease the user experience.

In Java, background threads can help us, as we can reuse the threads for our operations. Creating a new thread with a runner is straightforward:

Thread background = new Thread(() -> {
    // long running operation
});
background.start();

Every thread consumes memory and takes some time for the CPU to process. As the number of requests and operations grows, the thread pool starves. This starvation leads to degraded performance of the solution as a whole.

To handle asynchronous models without memory overloads, I/O blocking, or language construct limitations, Kotlin introduces the concept of coroutines. Coroutines offer:

  • Non-blocking constructs to prevent delays
  • Scopes to handle concurrency within a program
  • Enabling a function to be suspended

These simple options allow a program to be written in a non-blocking manner. Let’s see how that happens:

import kotlinx.coroutines.*

fun main() = runBlocking {
    launch {
        delay(2000)
        print("I am printed after.")
    }
    print("I am printed before. ")
}

We can run this code in the Kotlin playground to see what gets printed. We’ll notice that the print sequence is altered.

How can Java help?

As we saw in the previous sections, Java has a few problems. However, it has some advantages that Kotlin doesn’t. 

Java has fewer keywords and constructs, making it easier to learn. The fewer keywords and concepts we need to know, the fewer bugs we’ll have to handle—and avoid—in the future.

Java can be used directly on the JVM, and the compiler has excellent integration with all modern IDEs. We don’t need to buy a specific license to use Java or compile and deploy Java programs. Various open-source projects are written in Java, and enterprises have authored excellent support libraries. Google’s Guava is one such library that offers a lot of extensibility to the Java ecosystem.

How can Kotlin help?

Kotlin is the recommended language for Android development by Google because it helps minimize the number of runtime bugs by design. While Java compiles down to the Java bytecode for JVM, Kotlin can be compiled down to the JavaScript runtime and run in a web browser, making it a purely cross-platform language.

Kotlin has recently introduced a new UI framework called Compose. It provides a declarative programming approach to design and builds user interfaces using Google’s Material Design. Kotlin Compose can be significantly helpful in developing and releasing cross-platform applications if we create a front-end for our business.

The Pros and Cons of Java and Kotlin

In this article, we discussed and helped highlight the essential features of Kotlin and Java. Both are languages that we can use to program the Java virtual machine. Let’s break down the pros and cons of both Java and Kotlin.

Java

ProsCons
Checked exceptions

Easy to learn, due to its primitive types

Big community
Poor null handling

Less robust asynchronous programming

Boilerplate code

Kotlin

ProsCons
Asynchronous programming with coroutines

Null safety provided for types

True cross-platform compilation and execution
Less support in IDEs other than IntelliJ and Eclipse

Takes more time to learn due to many language features

Lack of checked exceptions

It’s pretty clear that Java and Kotlin both aim at solving different sets of problems. Java allows a more straightforward, neat, and concise way of writing JVM programs, while Kotlin brings additional language constructs to avoid common pitfalls in Java. We can always intermix both the languages to best use the JVM and IntelliJ IDEA platforms.

Software engineers prefer direct one-to-one communication instead of long-waiting email threads. The same goes for receiving messages and updates. For software engineers, quick and clear communication is key.

This blog post was created as part of the Mattermost Community Writing Program and is published under the CC BY-NC-SA 4.0 license. To learn more about the Mattermost Community Writing Program, check this out.

Read more about:

Java Kotlin

Afzaal Ahmad Zeeshan is a senior software engineer and cloud architect. He's the leader of several open-source communities in Pakistan and has been recognized as a MVP by Alibaba Cloud, Microsoft, CodeProject, and C# Corner. Afzaal is also experienced with .NET Core and Node.js frameworks. He currently builds cloud-native microservices for clients in the finance, education, and retail industry.