After just a few months in Beta, JetBrains has announced the first stable release of Kotlin, their new JVM-based language compatible with Android. As the maker indicates, the language is meant to be a "good tool", idea that has driven design decisions towards pragmatism and interoperability. The language promises to address many of the issues that can only be fixed in Java through libraries and external tools, while providing the chance of a smooth and gradual transition.
First conceived in 2010, JetBrains decided to create Kotlin as a way to increase productivity while developing their own products (Kotlin is now used in JetBrains products like IntelliJ IDEA). Considering that many other users would have to face the same problems, JetBrains decided to open-source Kotlin and encourage participation and contributions. Due to the fact that it targets Java 1.6, Kotlin quickly became popular among Android developers, giving them access to a set of modern features available in other versions and languages; proof of this popularity is the fact that new tools for Android development, like JRebel for Android, include support for Kotlin.
Although the advantage of Kotlin over Java in the area of Android development may be less significant once Android finishes its transition to OpenJDK, there are many other areas where developers can benefit from. Some of these areas are:
- Getter/Setter boilerplate: writing code to access properties in Java is typically performed through IDE-assisted code generation, bytecode manipulation like Project Lombok, or simply by making the internal fields public (which would go against the principle of encapsulation). In Kotlin, the creation of a data class provides getters and setters to all properties by default.
- toString, hashCode, equals: Java provides default implementations for these three methods, but these are rarely useful, meaning developers usually have to override the default and create their own. In many cases, the needed implementation is simple enough so as to be provided by libraries like Apache Commons Lang or Google Guava. Kotlin's data classes provide a default implementation for these based on the fields of the class, akin to what most developers need, meaning there is no need to override methods. Moreover, the operator '==' does not compare references in Kotlin, it works as the equals method.
- Partial building of objects: in many occasions, an object needs to be built in a way that only some of its parameters are provided, while the rest keep a default value. This is usually accomplished through the builder pattern, which creates the need to create a builder class together with the target class. Kotlin solves this through supporting named arguments.
- Null checks: avoiding nulls is a common headache for Java developers, typically addressed through IDE inspection (detection of values that will always be null), assertions by the plurals classes (Objects.requireNotNull()), implicit validation through annotations like @NotNull or @NonNull, Google's Optional or, later, Java 8's Optional. In Kotlin the concept of null has been moved to the language itself, meaning variables are aware of their own nullability on compile time:
val x: String? = "Hi" // Declaring x as a nullable String
x.length // Does not compile, x could be null, null check needs to happen first
if (x != null) {
x.length // Compiles, Kotlin understands that x is not null by this point
}
val y: String = null // Does not compile, y is not declared as nullable
- String building: In Java, one can build String by using the concatenation operator ("a " + variable + " b"), the String.format() method for more readability (String.format("a %s b", variable)), or a StringBuilder/StringBuffer if performance is a concern (new StringBuilder().append("a ").append(variable).append(" b").build()). Kotlin supports string interpolation much in the way of Ruby and other languages, meaning developers can simply type "a ${variable} b".
- Lambdas in pre-Java 8 environments: Lambdas were only introduced in the latest version of Java and, although older versions are no longer supported, they are still widely used. In order to use lambdas in previous versions users had to make use of tools like Retrolambda. Kotlin provides lambda support but, since it targets Java 6, it makes this feature available in older environments.
There are several other everyday problems that are easily addressed with Kotlin. However, despite the many benefits, adopting a new language brings its own risks and challenges. On one hand, adopting Kotlin in an existing project might require Java and Kotlin code to coexist for a significant period of time. JetBrains tries to address this by making interoperability as transparent as possible, and by providing a Java-to-Kotlin translator.
On the other hand, long-term support is needed for users to safely invest in any new tool. JetBrains has indicated its commitment to Kotlin by assigning a significant amount of resources (over 20 full-time developers) and by promising a standardisation process through community contributions. JetBrains has also committed to make every new version of Kotlin backwards compatible. These principles remind the governance of Java itself, with its reference platform being open source (OpenJDK), the standardisation process being community-lead (the JCP), and the commitment to make every new version also backwards compatible.
It remains to be seen whether Kotlin will stand out among the increasing population of JVM-languages (over 50 so far); for the moment, there are already 2 million lines of Kotlin code in GitHub (excluding JetBrains projects) and nearly 700 questions in StackOverflow.