Kotlin is a statically typed programming language for modern multi-platform applications. It is 100 per cent interoperable with Java. Existing libraries and frameworks in Java can directly be run on Kotlin, which also happens to be open source and freely distributed under the Apache licence.
Kotlin is a statically typed open source modern programming language targeting JVM, Android and even JavaScript. It is named after the Russian island called Kotlin, just as Java is named after the Indonesian island. It works everywhere where Java works – on the server side, the desktop, Android, and other places.
The biggest selling point of Kotlin is its 100 per cent interoperability with Java. So instead of throwing away or re-writing all your libraries in Kotlin, you can use all your existing Java libraries and frameworks directly with it. Due to this characteristic, you can gradually adopt Kotlin in your Java code base.
Kotlin has been created by JetBrains, the maker of IntelliJ, Android Studio and other amazing IDEs.
It is open source and has been released under the Apache licence.
Why you should use Kotlin
The biggest reason to learn Kotlin is that at Google I/O 17, Google announced first-class support for Kotlin for Android. So now you can expect full support from Google, like documentation to write Android apps in Kotlin.
Another reason is that it’s an amazing language and many developers (especially Android developers like me) are in love with it and have fun writing code in it. People who are tired, or in some cases irritated with Java, will definitely find Kotlin concise and fun to work with.
Problems and issues with Java and the Android platform
Let’s start with the current problems with Java that are usually faced by developers coming from other languages.
Java is extremely old. It’s been around for more than 20 years. It doesn’t have the modern higher order functions and features that newer languages like Swift or Golang ship with. Though Java 8 is trying to bring out some good stuff, it still is verbose, which means that to perform even small tasks, we end up writing a lot (seriously, a lot) of code. It also ships with NullPointerException, which I’m pretty sure scares you and your customers.
Let’s dive deeper into the problems in the Java-Android world, which are much worse.
- Android developers are stuck between Java 6 and 7. This means that we don’t have features like Lambdas, higher order functions, and Java Time APIs. We can get these features by targeting higher versions of Android, which is not a feasible solution. This problem can also be solved using third party libraries like RetroLambda, RxJava, etc, which is acceptable.
- There are also restrictions to adding functionality to Android APIs. I’m sure you might have felt like adding a particular feature such as being able to check if a string is an email or not, but you were restricted from doing so. Due to such restrictions, we end up making lots of ‘Util’ classes to solve the problem.
- Moreover, Android loves inheritance; it requires extending things like Activity, etc, which is not totally bad but limits flexibility.
- In Android, we need to write a lot of boilerplate code to achieve something. For example, if you want to write a model POJO class, you end up writing 40-50 lines of code, depending upon the number of attributes you add.
- In Java, all the empty values are set as null for efficiency. Android tries to be efficient by setting ‘null’ as the default value everywhere, which again comes with NPEs and more instances of the app crashing.
- And there’s a lot more.
Some big players using Kotlin in production
JetBrains is already using Kotlin to build its IDEs. Its new IDE Rider is completely written in Kotlin while new features in older IDEs are also written in it. Pinterest, Coursera, Atlassian, Evernote, Basecamp and many more players are using Kotlin in their Android apps, either partially or fully. Gradle is introducing Kotlin as a language for writing build scripts, instead of Groovy.
Syntax of Kotlin
Let’s take a crash course in the basic syntax of Kotlin. We won’t cover all of it; hence, I recommend going to the Kotlin website and reading the documentation, which is pretty good, and also trying out the Kotlin Koans — they are very interesting and help you learn faster.
Declaring variables
Declaring variables in Kotlin is simple; you either write ‘val’ or ‘var’ and the name of the variable. Then the type of the variable which is optional provided that the compiler is able to figure it out.
// String (Implicitly inferred) val spell = “Lumos” // Int val number = 74
The type can be explicitly specified after the variable name with a colon (:).
// Explicit type var spells: List<String> = ArrayList()
Did you notice there is no ‘new’ keyword? That is because there is no ‘new’ keyword in Kotlin.
As we discussed earlier, there are two ways to declare variables in Kotlin:
1. val
2. var
In Kotlin, immutable values are preferred whenever possible. The fact that most parts of our program are immutable provides lots of benefits, such as a more predictable behaviour and thread safety.
Functions
fun add(a: Int, b: Int): Int { return a + b }
This is how we write functions in Kotlin. The functions start with a ‘fun’ keyword (expecting the function to be fun to write for you), the parameters are reversed, and the return is typed at the end after the colon ‘:’. Pretty simple, right?
You can even cut the code of the function to this, as follows:
fun add(a: Int, b: Int) = a + b
And you can add default values to the function, as shown below:
fun add(a: Int = 0, b: Int = 0) = a + b
You also get a named argument! Did you notice that there is no semi-colon in the return statement? That’s because Kotlin is a semi-colon free language.
Some amazing features of Kotlin
Let’s look at what makes Kotlin so interesting.
Null safety
One of the common reasons for Android apps to crash is ‘NullPointerException’. A lot of time is wasted debugging an issue and solving it. The great thing about Kotlin is that it comes with null safety, which helps in catching nulls at the compile time rather than during a runtime crash. The following code shows how this is done:
// Compile time error val spell: String = null // OK val spell: String? = null
In Kotlin, by default, all variables are marked as ‘not null’ unless you explicitly tell the compiler that the variable can be null with a question mark (?) operator. This means that in order to declare a null variable, you need to add ‘?’ at the end of the variable type.
Even if you try to set a non-null variable to null, the compiler will ‘yell’ at you.
// Compile time error var spell: String = “Lumos” spell = null // OK var spell: String? = “Lumos” spell = null
Using null variables
Directly accessing null variables results in compile time error, unless protection has been cast before using these variables. If the null is safely handled then the compiler is smart enough to know that the variable (the ‘spell’ variable, in our case) won’t show an error on using it further in the if block.
// Compile time error val spell: String? = null val length = spell.length // OK val spell: String? = null if (spell != null) { // Smart cast val length = spell.length }
The idiomatic way is as follows:
// Safe val spell: String? = null val length = spell?.length // Safe with else val length = spell?.length ?: -1
In the first case, if the value for spell exists then the length will be returned, else null will be returned without any exception. A point to note over here is the ‘val length’ will be a nullable value, which means the compiler will force you to check for null value in case of the ‘length’ variable.
The second case is pretty straightforward. Unlike the first case, the ‘val length’ won’t be nullable over here because we have handled it using the else condition.
String interpolation
String interpolation is a nifty feature, which makes your code cleaner. It makes it easier to build long strings.
fun sayHello(message: String) { println(“Welcome $message”) } fun sayTime() { println(“Time: ${System.currentTimeMillis()}”) }
Using $ allows you to avoid String concat or StringBuilder. You can execute a small piece of code using ${}. Internally, it uses StringBuilder for performance on the JVM level.
Lambda expressions
Lambda expressions are anonymous functions, which can be passed as arguments to other functions. For people who are not aware about Lambda expressions, I recommend they read more about them.
// Java mButton.setOnClickListener(new OnClickListener() { public void onClick(View v) { // Your logic } }); // Kotlin mButton.setOnClickListener { // Your logic } mButton.setOnClickListener { // Using the view parameter v -> v.visibility = GONE }
Higher order functions
Kotlin supports Higher order functions which means functions can be passed to another function as parameters.
An example is given below:
fun consume(f: () -> Unit): Boolean { f() return true }
The ugly part of receiving functions as arguments is that the compiler needs to create classes for them, which can impact performance. But in Kotlin, this can be easily solved by using the keyword inline. An inline function will have less impact on performance, because it will substitute the call to the function with its code in compilation time. So it won’t require the use of an extra object for this.
inline fun consume(f: () -> Unit): Boolean { f() return true }
Extension functions
All of us, at some stage, want to add a new function to an existing class but this means modifying the original class and doing some more work on the code. This is where extension functions come to our rescue. As the name suggests, they are used to inject functionality to already existing classes without modifying the original class. People who know C# may be aware of this feature. These functions eliminate the need for creating ‘Util’ classes.
Here is an example:
fun String.isEmail(): Boolean { return Patterns.EMAIL_ADDRESS.matcher(this).matches() }
The usage is as follows:
val email = “go.kotlin@android.com” if (email.isEmail()) { // Do login }
Extension function with receiver
This feature is unique to Kotlin, and is like a combination of an extension function and a higher order function whereby you pass an extension function as a parameter to another extension function.
inline fun SharedPreferences.edit(func: SharedPreferences.Editor.() -> Unit) { val editor = edit() editor.func() editor.apply() } //Usage val pref = PreferenceManager.getDefaultSharedPreferences(con text) pref.edit{ putString(“first_name”, “A”) putString(“last_name”, “J”) remove(“last_name”) }
Smart cast
Smart casting is done by the Kotlin compiler on our behalf. It even handles the negative scenario, like if the ‘view’ is not a TextView.
// Java way if (view instanceof TextView) { ((TextView) view).setText(“Avifors”); } // Kotlin way if (view is TextView) { // Smart casting view.text = “Avifors” }
There are however a few, minor issues with Kotlin. These are:
- Slightly increased build time
- Adds Dex Count (6K) to your app
Difficult to use the power of functional programming as most of us come from object-oriented programming
That said, if you find Kotlin an awesome language, then these issues won’t be a deal breaker for you.
With Kotlin, we can enjoy writing the code. It shrinks the code base and even reduces the number of crashes. There is so much more about Kotlin that hasn’t been covered here. For instance, Kotlin v1.1 has more new treats for asynchronous programming.
So go on, get your hands dirty with Kotlin! And have lots of fun writing code. There is great tooling support for Kotlin in IntelliJ and Android Studio (from v3).