source: JarkkoManty, via pixabay (CC0)

As a long-term developer and architect, I have mainly been focussed on Spring-based Java applications within the last years. This year, I had the chance to start over with Kotlin in one of my customer projects and fell in love with it right from the start. In this post I want to share some of the key aspects I appreciate most in Kotlin as a former Java developer.

Named Parameters

Let’s start with a simple, often underrated, difference between Java and Kotlin: named parameters. Java does not allow us to explicitly name parameters in function calls, relying solely on positional parameters instead. In addition to that, Java does not have a concept for dealing with default parameter values, not even null. Hence, you are always forced to supply all parameters in the correct order, making refactorings cumbersome. While most IDEs nowadays support us by highlighting the names of the underlying parameters, when calling functions from within our code, this cannot fully compensate the downsides.

In Kotlin parameters can either be passed by position or by name, but not both at the same time. When using named parameters, which I strongly suggest, the order of the parameters has no relevance, allowing for much easier refactorings in the long run. Moreover, Kotlin allows default value declaration (including null ), which enables callers to omit those parameters, if necessary.

In comparison to other languages, there are no limitations in Kotlin when using mixed style parameter definitions in the function declaration. However, when calling functions with alternating required and optional parameters, using positional parameters enforces us to provide all parameters up to the last required one, that is even those having default values. Accordingly, named parameters are highly preferable in Kotlin, since only required parameters can be supplied.

Immutability

While immutability is essential in (functional) programming to avoid side effects, Java only provides limited support for ensuring immutability during compile time. In fact, marking all fields as final is the only way to ensure an object cannot be modified after construction. Unfortunately, Java Bean style based frameworks, such as JPA, often expect object properties to be mutable via setters. Furthermore, dealing with multiple equally typed properties of an object is cumbersome and error-prone with respect to object construction or duplication, since Java only knows positional parameters in constructors. Finally, Java does not enforce a consistent concept of object equality, leaving it to the developer to implement both equals() and hashCode() , which is why frameworks such as Lombok are commonly in-use.

Code, which isn’t allowed to alter state outside of its scope, is inherently free of side effects

Kotlin introduces first class compiler support for distinguishing between mutable and immutable properties, values, and references:

Values (including references) marked as read-only cannot be altered after they have been assigned, which is why they should always be preferred in favor or mutable state. When combining multiple attributes, Kotlin provides so-called data classes, which support the concept of immutability at the class level. While these classes allow for mutability as well, their built-in equality functions and copy constructors make them and ideal candidate for representing immutable state in an object-oriented manner.

Accordingly, with Kotlin immutable state should be the first (if not only) choice when it comes to defining an object model representing the domain of your application. Modifying the state of existing objects can be restricted to copy constructors, bringing back control to the code really in charge of manipulating state.

Null Safety

When it comes to software quality the “much-loved” NullPointerException (NPE) is something every programmer has to cope with once in a while, although the exception itself is something the JVM actually uses to avoid program abortion by the operating system, which would be inevitable, if we really were to dereference null pointers. This prevention, however, is limited to the runtime of your software, while programmers most would prefer to prevent these kind of issues at compile time already. In fact, the Java language itself provides no means whatsoever to tell the compiler, whether a reference is null safe or not, leave aside simple checks for initial variable assignments along different execution paths in the code. Additional frameworks, such as Java Bean Validation, are often used to compensate for this, for instance at the REST API layer when using Spring MVC and appropriate @NotNull annotations. Still, there is no strict warning or even error, if programmers forget about these add-on validations.

“I call it my billion-dollar mistake. It was the invention of the null reference in 1965.” (Tony Hoare)