The Kotlin language is gaining more and more popularity. It is widely used no longer just in mobile apps development, but also for server-side systems. As you probably know, it is a statically-typed programming language that runs on the JVM. That's why it is often compared with the Java language. One of the main reasons for Kotlin popularity is simplicity. It cleans and removes a lot of the code bloat from Java. However, it is also very similar to Java so that any experienced Java developer can pick up Kotlin in just a few hours.

In this article, I'm going to discuss some interesting Kotlin features used for server-side development in comparison to Java. Here's my personal list of favorite Kotlin features that are unavailable with the Java language.

1. Collections and Generics

I really like Java, but sometimes, working with generic collections may be an unpleasant experience, especially if you have to use wildcard types. The good news is that Kotlin doesn't have any wildcard types. Instead, it provides two other features called declaration-site variance and type projections. Now, let's consider the following class hierarchy.

Now, I would like to store all the vehicles in that repository, so I declare the Repository r = new Repository(). But, invoking the repository method addAll with List as a parameter will receive the following error:

Of course, this situation has a logical explanation. First, generic types in Java are invariant, which, in fact, means that Listis not a subtype of List, although Truck is a subtype of Vehicle. The addAll method takes the wildcard type argument and extends T as a parameter, which indicates that this method accepts a collection of objects of T or some subtype of T — not just T itself.

The List is a subtype of List<? extends Vehicle>, but the target list is still List. I don't want to get into details about this behavior — you can read more about it in Java specification. The important thing for us is that Kotlin is solving this problem using a feature called Declaration-site variance. If we add the out modifier to the MutableList parameter inside the addAll method declaration, the compiler will allow adding a list of Truck objects. The smart explanation of that process is provided on the Kotlin site: 'In "clever words," they say that the class C is covariant in the parameter T, or that T is a covariant type parameter. You can think of C as being a producer of T's, and NOT a consumer of T's."

2. Data Classes

You probably know Java's POJOs (Plain Old Java Object). If you are following the Java best practices, such a class should implement getters, setters, hashCode, and equals methods, as well as the toString method for logging needs. Such an implementation may take up a lot of space, even for a simple class with only four fields. This is also shown below (methods auto-generated using Eclipse IDE):

To avoid many additional lines of code inside your POJO classes, you may use project Lombok. It provides a set of annotations that can be used on the class to deliver implementations of getters/setters, equals, and hashCode methods. It is also possible to annotate your class with @Data, which bundles all the features of @ToString, @EqualsAndHashCode, @Getter/@Setter, and @RequiredArgsConstructor together. So, with Lombok's @Data, the POJO is going to look like as shown below — assuming you don't require a constructor with parameters.

Including and using Lombok with a Java application is quite simple and supported by all the main developer IDEs, but Kotlin solves this issue out-of-the-box. It provides functionality called data classes, which are enabled after adding the keyword data to the class definition. The compiler automatically derives the methods from all properties declared in the primary constructor:

toString() method

componentN() functions corresponding to the properties in their order of declaration

copy() function

Because Kotlin internally generates a default getter and setter for mutable properties (declared as var) and a getter for read-only properties (declared as val), the similar implementation of Person Java POJO in Kotlin will look as shown below.

What's worth mentioning here is that the compiler only uses the properties defined inside the primary constructor for the automatically generated functions. So, the field age, which is declared inside the class body, will not be used by toString, equals, hashCode, and copy implementations.

3. Names for Test Methods

Now, let's implement some test cases to prove that the features described in step twowork properly. The following three tests are comparing two objects with different values of age property, trying to add the same object to the Java HashSet twice and checking if the componentN method of the data class is returning properties in the right order.

As you can see on the fragment of code above, Kotlin is accepting to use method names with spaces enclosed in backticks. Thanks to that, I can set a descriptive form of test name, which is then visible during execution, and you know exactly what's going on.

4. Extensions

Let's consider the situation that we have a library that contains class definitions, which cannot be changed, and we need to add there some methods. In Java, we have some choices to implement such an approach. We can just extend the existing class, implement a new method, or, for example, implement it with the Decorator pattern.

Now, let's assume we have the following Java class containing the list of persons and exposing getters/setters.

Kotlin provides the ability to extend a class with a new functionality without having to inherit from the base class. This is done via special declarations called extensions. Here's the similar declaration to Organization Java class in Kotlin. Because Kotlin treats a simple Listclass as immutable, we need to define the MutableList.

class Organization(val persons: MutableList = ArrayList()) {
}

We can easily extend it with the addPerson method, as shown below. Extensions are resolved statically, and they do not modify extended classes.

5. String Templates

Conclusion

Of course, there are some other differences between Java and Kotlin. This is only my personal list of favorite features that are unavailable in Java. The sample source code with described samples is available on GitHub.