History and Reference
Kotlin has been around for quite a while; it was announced back in 2011 and the
first preview was released in 2012. Kotlin 1.0 was released in 2016, at which
point JetBrains committed to maintaining backwards compatibility for stable
features from 1.0 forward.
You can find excellent training material and references at https://kotlinlang.org/. The Android team has
found the Kotlin
Koans tutorial to be especially helpful as a quick way to get started
writing some Kotlin snippets. These tutorials range from the simple to the
sublime as the material progresses from the basics to more sophisticated Kotlin
idioms.
Why Kotlin?
Why did the Android team decide to support Kotlin? Most importantly, it was
because we think Kotlin is a great language that will make writing Android apps
easier and more enjoyable.
Kotlin is also a great match for the existing Android ecosystem. It is 100%
compatible with the Java programming language. You can add as little or as much
Kotlin into your existing codebase as you want and mix the two languages freely
within the same project. Calling out to Kotlin code from code written in the
Java programming language Just Works™. Going the other direction usually works
without any developer effort too via some automatically applied translation
conventions (for example, things like property getters and setters are created
for you). With the help of a few Kotlin annotations, you can also customize how
the translation is performed.
Finally, many, many developers have told us they love the Kotlin language. (Many
of our own developers on the Android team have also been saying similar things.)
There is already an enthusiastic
community
of Kotlin developers
for Android, and the Android team has been routinely peppered with questions
about Kotlin at public events. The Android community has spoken, and we
listened.
A Quick Tour
To help you get a sense of where all of the excitement around Kotlin is coming
from, here is a quick, very-much-not-comprehensive tour of some of the
particularly appealing aspects of Kotlin:
Nullable
The Kotlin compiler enforces that variables that can hold null values are
explicitly declared – thus no more NullPointerExceptions at runtime!
var neverNull: String = "something"
var mightBeNull: String? = null // "?" indicates this can be null
if (neverNull.length > 0) { // This is OK
…
}
if (mightBeNull.length > 0) { // Compiler catches this error for you
…
}
Named parameters and default arguments
We've all seen methods that have too many parameters to keep track of. For
example:
fun orderPizza(size: Size, pepperoni: Boolean, mushrooms: Boolean,
ham: Boolean, pineapple: Boolean, pickles: Boolean,
sausage: Boolean, peppers: Boolean, onion: Boolean)
{
...
}
// Wait… did I just order pickles on my pizza?
// Why do we even have that option?
orderPizza(Size.LARGE, true, false, false, false, true,
false, true, false)
Compare that to a similar scenario using named parameters and default arguments:
fun orderPizza(size: Size,
pepperoni: Boolean = false,
mushrooms: Boolean = false,
ham: Boolean = false,
pineapple: Boolean = false,
pickles: Boolean = false,
sausage: Boolean = false,
peppers: Boolean = false,
onion: Boolean = false)
{
...
}
orderPizza(Size.LARGE, ham = true, mushrooms = true)
In addition to helping to avoid tragic pizza outcomes, this is much easier to
read. It also reduces the number of variants of overloaded functions you need to
write.
When statement
Kotlin has a variation of a switch statement that allows matching on arbitrary
expressions.
// Please don't put this in your app!
when {
password.equals("password") -> println("Insecure password!")
password.length < 4 -> println("Too short!")
else -> {
println("Secure password!")
}
}
Smart Casts
Why should you have to cast something to a class right after you just tested
that it is an instance of that class? In Kotlin, you don't have to do that
anymore.
if (obj is String) {
// Compiler casts obj to a String for you.
// (Would work with && instead of nested ifs too.)
if (obj.length > 0) {
…
}
}
This generalizes to the when statement as well:
// Assume reasonable implementations of Cat and Dog
when (obj) {
is Cat -> obj.meow(...)
is Dog -> obj.woof(...)
else -> {
…
}
}
Extension functions
Kotlin lets you essentially retcon
new methods onto an existing type. If you, like many people, wish that the
String class had a toPigLatin
method, you can now add it yourself
without having to create a new helper class to wrap String or going through the
trouble of serving on a language committee:
// The "String." prefix indicates that this method should
// extend the existing String class
fun String.toPigLatin() : String {
...
}
val plainOldString : String = "some text"
// Can now call toPigLatin as if were a method on String
println(plainOldString.toPigLatin())
// Or:
println("some text".toPigLatin())
Destructuring Declarations
We have already seen how easy it is to define a simple data class:
data class Order(val itemCode: String, val quantity: Int,
val price: Float)
A function that uses one of these classes as the return type is very close to
supporting multiple return values:
fun getOrder(...): Order {
...
return Order(itemCode, quantity, price);
}
To get all the way there, you can use the destructuring declaration syntax. The
following statement takes the Order
object, extracts its three
properties, and then assigns them to the three variables what
,
howMany
and howMuch
— all courtesy of the Kotlin
compiler, which also infers the correct types for you.
val (what, howMany, howMuch) = getOrder(...)
Lambdas
Kotin has an extremely concise syntax for lambdas that makes is easy to express
powerful functional programming paradigms. Here's a simple example that uses a
lambda to test that everything in a collection is a String:
fun allStrings(collection: Collection)=
collection.all { it is String }
That lambda syntax is building block of one of Kotlin's coolest features: the
ability to create builders that use JSON-like syntax that also happens to be
syntactically valid Kotlin. This example is adapted from an extended discussion
here,
but you can get the flavor of what it possible with this snippet:
fun generatePage(withEmphasis : Boolean) {
val result =
html {
head {
title { +"Kotlin Builders" }
}
body {
h1 { +"Kotlin Builders" }
p {
+"This is "
if (withEmphasis) b { +"really " }
+"interesting"
a(href = "https://goo.gl/rHwJio") { +"More here" }
}
}
}
println(result)
}
There are a couple of interesting things going on here. First, this shows how
expressive Kotlin's functional syntax can be: in this example,
"html
", "head
", "body
, etc. are all just
functions written in Kotlin and the stuff in curly braces that follows are
functional parameters. (This snippet uses functions with names that match HTML
tags to build a representation of a web page, but of course you can use this
pattern to build any complex data structure with whatever names you want.) The
second interesting thing is the "withEmphasis
" conditional. This
may look like we are mixing code (if (withEmphasis)
…) with data
(all the HTML-esque tags), but the "data" here is actually just more code. Since
it is all really just code, this lets you build complex data structures using a
declarative syntax while also having inline access to the full capabilities of
the Kotlin language.
Getting Started
If you want to get started with Kotlin, you can start playing with code online
immediately here. Just hit the green
triangle to compile and run.
To try Kotlin in your app, follow these steps:
- Download
Android Studio 3.0
- Open one of your existing ".java" files
- Invoke "Code > Convert Java File to Kotlin File"
The IDE will then walk you through adding Kotlin dependencies into your project,
and then convert the code to functionally equivalent Kotlin code. (The IDE will
also offer to touch up all of the call sites to the converted class when
suitable to be more idiomatic Kotlin such as when static methods are moved to
companion objects.)
You can also find a lot more information on how to start using
Kotlin on developer.android.com.