Kotlin is great language that makes Android development easier, faster, and much more pleasant. In this chapter, we will discuss what Kotlin really is and look at many Kotlin examples that will help us build even better Android applications. Welcome to the amazing journey of Kotlin, that will change the way you think about writing code and solving common programming problems.
In this chapter, we will cover the following topics:
- First steps with Kotlin
- Practical Kotlin examples
- Creating new Kotlin project in Android Studio
- Migrating existing Java project to Kotlin
- The Kotlin standard library (stdlib)
- Why Kotlin is a good choice to learn
Kotlin is a modern, statically typed, Android-compatible language that fixes many Java problems, such as null pointer exceptions or excessive code verbosity. Kotlin is a language inspired by Swift, Scala, Groovy, C#, and many other languages. Kotlin was designed by JetBrains professionals, based on analysis of both developers experiences, best usage guidelines (most important are clean code and effective Java), and data about this language's usage. Deep analysis of other programming languages has been done. Kotlin tries hard to not repeat the mistakes from other languages and take advantage of their most useful features. When working with Kotlin, we can really feel that this is a mature and well-designed language.
Kotlin takes application development to a whole new level by improving code quality and safety and boosting developer performance. Official Kotlin support for the Android platform was announced by Google in 2017, but the Kotlin language has been here for some time. It has a very active community and Kotlin adoption on the Android platform is already growing quickly. We can describe Kotlin as a safe, expressive, concise, versatile, and tool-friendly language that has great interoperability with Java and JavaScript. Let's discuss these features:
Safety: Kotlin offers safety features in terms of nullability and immutability. Kotlin is statically typed, so the type of every expression is known at compile time. The compiler can verify that whatever property or method we are trying to access of a particular class instance actually exists. This should be familiar from Java which is also statically typed, but unlike Java, Kotlin type system is much more strict (safe). We have to explicitly tell the compiler whether the given variable can store null values. This allows making the program fail at compile time instead of throwing a
NullPointerException
at runtime:

- Easy debugging: Bugs can be detected much faster during the development phase, instead of crashing the application after it is released and thus damaging the user experience. Kotlin offers a convenient way to work with immutable data. For example, it can distinguish mutable (read-write) and immutable (read-only) collections by providing convenient interfaces (under the hood collections are still mutable).
- Conciseness: Most of the Java verbosity was eliminated. We need less code to achieve common tasks and thus the amount of boilerplate code is greatly reduced, even comparing Kotlin to Java 8. As a result, the code is also easier to read and understand (expressive).
- Interoperability: Kotlin is designed to seamlessly work side by side with Java (cross-language project). The existing ecosystem of Java libraries and frameworks works with Kotlin without any performance penalties. Many Java libraries even Kotlin-specific versions that allow more idiomatic usage with Kotlin. Kotlin classes can also be directly instantiated and transparently referenced from Java code without any special semantics and vice versa. This allows us to incorporate Kotlin into existing Android projects and use Kotlin easily together with Java (if we want to).
- Versatility: We can target many platforms, including mobile applications (Android), server-side applications (backend), desktop applications, frontend code running in the browser, and even build systems (Gradle).
Any programming language is only as good as its tool support. Kotlin has outstanding support for modern IDEs such as Android Studio, IntelliJ Idea, and Eclipse. Common tasks such as code assistance or refactoring are handled properly. The Kotlin team works hard to make the Kotlin plugin better with every single release. Most of the bugs are quickly fixed and many of the features requested by the community are implemented.
Note
Kotlin bug tracker: https://youtrack.jetbrains.com/issues/KTKotlin slack channel: http://slack.kotlinlang.org/
Android application development becomes much more efficient and pleasant with Kotlin. Kotlin is compatible with JDK 6, so applications created in Kotlin run safely even on old Android devices that precede Android 4.
Kotlin aims to bring you the best of both worlds by combining concepts and elements from both procedural and functional programming. It follows many guidelines as described in the book, Effective Java, 2nd Edition, by Joshua Bloch, which is considered a must-read book for every Java developer.
On top of that, Kotlin is open sourced, so we can check out the project and be actively involved in any aspect of the Kotlin project such as Kotlin plugins, compilers, documentation, or the Kotlin language itself.
Kotlin is really easy to learn for Android developers because the syntax is similar to Java and Kotlin often feels like a natural Java evolution. At the beginning, a developer usually writes Kotlin code by having in mind habits from Java, but after a while, it is very easy to move to more idiomatic Kotlin solutions. Let's look at some cool Kotlin features and see where Kotlin may provide benefits by solving common programming tasks in an easier, more concise, and more flexible way. We have tried to keep examples simple and self-explanatory, but they utilize content from various parts of this book, so it's fine if they are not fully understood at this point. The goal of this section is to focus on the possibilities and present what can be achieved by using Kotlin. This section does not necessarily need to fully describe how to achieve it. Let's start with a variable declaration:
Notice that Kotlin does not require semicolons. You can still use them, but they are optional. We also don't need to specify a variable type because it's inferred from the context. Each time, the compiler can figure out the type from the context; we don't have to explicitly specify it. Kotlin is a strongly typed language, so each variable has an adequate type:
The variable has an inferred String
type, so assigning a different value (integer) will result in a compilation error. Now, let's see how Kotlin improves the way to add multiple strings using string templates:
We need no more joining strings using the +
character. In Kotlin, we can easily incorporate single variable or even whole expressions, into string literals:
In Java, any variable can store null values. In Kotlin, strict null safety forces us to explicitly mark each variables, that can store nullable values:
By adding a question mark to a data type (string versus string?), we say that the variable can be nullable (can store null references). If we don't mark the variable as nullable, we will not be able to assign a nullable reference to it. Kotlin also allows us to deal with nullable variables in proper ways. We can use the safe call operator to safely call methods on potentially nullable variables:
The method doSomething
will be invoked only if savedInstanceState
has a non-null value, otherwise the method call will be ignored. This is Kotlin's safe way to avoid null pointer exceptions that are so common in Java.
Kotlin also has several new data types. Let's look at the Range
data type that allows us to define end inclusive ranges:
Kotlin introduces the Pair
data type that, combined with infixnotation, allows us to hold a common pair of values:
We can deconstruct it into separate variables using destructive declarations:
We can even iterate through a list of pairs:
Alternatively, we can use the forEach
function:
Note that Kotlin distinguishes between mutable and immutable collections by providing a set of interfaces and helper methods (List
versus MutableList
, Set
versus Set
versus MutableSet
, Map
versus MutableMap
, and so on):
Immutable collection means that the collection state can't change after initialization (we can't add/remove items). Mutable collection (quite obviously) means that the state can change.
With lambda expressions, we can use the Android framework build in a very concise way:
The Kotlin standard library (stdlib) contains many functions that allow us to perform operations on collections in a simple and concise way. We can easily perform stream processing on lists:
Notice that we don't have to pass parameters to a lambda. We can also define our own lambdas that will allow us to write code in a completely new way. This lambda will allow us to run a particular piece of code only in Android Marshmallow or newer:
We can make asynchronous requests easily and display responses on the main thread using the doAsync
function:
Smart casts allow us to write code without performing redundant casting:
The Kotlin compiler knows that the variable x
is of the type String
after performing a check, so it will automatically cast it to the String
type, allowing it to call all methods and access all properties of the String
class without any explicit casts.
Sometimes, we have a simple function that returns the value of a single expression. In this case, we can use a function with an expression body to shorten the syntax:
Using default argument syntax, we can define the default value for each function argument and call it in various ways:
The only limitation is that we need to supply all arguments without default values. We can also use named argumentsyntax to specify function arguments:
This also increases readability when invoking the function with multiple parameters in the function call.
The data classes give a very easy way to define and operate on classes from the data model. To define a proper data class, we will use the data
modifier before the class name:
Notice that we have a really nice, human readable string representation of the class instance and we do not need the new
keyword to instantiate the class. We can also easily create a custom copy of the class:
The preceding constructs make working with immutable objects very easy and convenient.
One of the best features in Kotlin are extensions. They allow us to add new behavior (a method or property) to an existing class without changing its implementation. Sometimes when you work with a library or framework, you would like to have an extra method or property for a certain class. Extensions are a great way to add those missing members. Extensions reduce code verbosity and remove the need to use utility functions known from Java (for example, the StringUtils
class). We can easily define extensions for custom classes, third-party libraries, or even Android framework classes. First of all, ImageView
does not have the ability to load images from a network, so we can add the loadImage
extension method to load images using the Picasso
library (an image loading library for Android):
We can also add a simple method displaying toasts to the Activity
class:
There are many places where usage of extensions will make our code simpler and more concise. Using Kotlin, we can fully take advantage of lambdas to simplify Kotlin code even more.
Interfaces in Kotlin can have default implementations as long as they don't hold any state:
In Android, there are many applications where we want to delay object initialization until it is needed (used). To solve this problem, we can use delegates:
Retrofit (a popular Android networking framework) property initialization will be delayed until the value is accessed for the first time. Lazy initialization may result in faster Android application startup times, since loading is deferred to when the variable is accessed. This is a great way to initialize multiple objects inside a class, especially when not all of them are always needed (for certain class usage scenarios, we may need only specific objects) or when not every one of them is needed instantly after class creation.
All the presented examples are only a glimpse of what can be accomplished with Kotlin. We will learn how to utilize the power of Kotlin throughout this book.