Hello, Kotlin!
Java ecosystem is growing each year. It gave us many good languages such as Groovy, Scala, Closure, Kotlin.
What is Kotlin?
Kotlin is an evolution of Java programming language developed by JetBrains, one of the world leaders in IDEs. The project emerged from the idea to make developers more efficient by writing concise, pragmatic, safe and interoperable code. It grew over the years and from May 2017 it became Google’s official programming language for Android development. With Google standing by JetBrains side, Kotlin’s popularity expanded. But Kotlin is not constrained to mobile development, it can be used everywhere where Java is used today.
How to start?
To get started with Kotlin you can jump to try.kotlinlang.org website. It offers a lot of examples which you can try out, modify and run. So let’s start with the basics, I’ll use analogies with Java as it emerged from it.
Variables
Kotlin provides two types of variables: mutable and immutable. Mutable means that the variable CAN be changed, and immutable means that it CANNOT be changed, once when it’s initialized.
val age = 56 // immutable variable
age = 120 // Compiler error: val cannot be reassignedvar protocol = “ssh” // mutable variable
protocol = “https” // OK
String templates
String concatenation is a common thing in most Java programs. Sometimes string concatenation should include some kind of format. To solve this issue Kotlin introduced string templates, which gave us the opportunity to use variable(s) inside double quotes by prefixing variable name with $
.
val name = “Tom”
val age = 56
println(“User: $name with age: $age has entered details”) // prints “User: Tom with age: 56 has entered details”
Type inference
There is no need to declare type of variable anymore, Kotlin will infer it for us automatically. If there is a need to explicitly do so, you still have the ability to do it.
val name = “Tom” // type inferred to string
val money: Double = 123.4 // type declared explicitly
Functions
Functions are enhanced with ability to declare default values and named arguments to eliminate the need for builders. Having this feature in, the code becomes more concise and cleaner.
fun assignWorker(fabric: String, supervisor: String, totalWorkingHours: Int = 40) {
// …
}assignWorker(“Denim”, “Supervisor”) // totalWorkingHours is 40
assignWorker(fabric = “Denim”, supervisor = “Supervisor”) // same as above
assignWorker(supervisor = “Supervisor”, fabric = “Denim”) // same as aboveassignedWorker("Denim", "Supervisor", 10) // totalWorkingHours is 10
Classes and properties
To declare a class Kotlin removes boilerplate code and express it in a concise way. To declare property, you use the same way like declaring variable: use val
for read-only and var
for writable properties.
class Car(val type: String, var isMoving: Bool)// usage
var bmw = Car(“BMW”, false)
bmw.isMoving = true
Kotlin adds another feature, which is custom properties. There is no need to write boilerplate get/set pairs for exposing fields; with custom properties there is no need to store information.
class Frame(val height: Int, val width: Int) {
val area: Int
get() = {
return height * width
}
}// usage
val frame = Frame(2, 2)
println(frame.area) // prints “4”
Simple POJOs
Kotlin provides data
class which is a replacement for Java POJO. By declaring a class as data
class, Kotlin automatically generates getters
, setters
, equals
, hashCode
, toString
and copy
.
data class Boat(val loadCapacity: Int, val type: String)
When expression
Switch
statement is replaced with more powerful when
. Unlike in Java, you don’t need to write break statement for each case. If the condition matches, only the corresponding case will be executed.
when (number) {
1 -> println(“only one”)
2 -> println(“a pair”)
12 -> println(“a dozen”)
101..999 -> println(“more than a hundred, but less then thousand”)
}
But when has more ability than switching on constants (like Java: enums, strings or numbers), it allows switching on objects.
enum class Color {
RED, YELLOW, BLUE
}when (setOf(color1, color2)) { // switch on set
setOf(RED, YELLOW) -> println(“orange”)
setOf(RED, BLUE) -> println(“purple”)
setOf(YELLOW, BLUE) -> println(“green”)
}
Also when can be used without an argument.
func countryByType(car1: Car, car2: Car) = {
when {
(car1.type == “BMW” && car2.type == “Audi”) ||
(car1.type == “Audi” && car2.type == “BMW”) -> “Germany” (car1.type == “Renault” && car2.type == “Peugeout”) ||
(car1.type == “Peugeout” && car2.type == “Renault”) -> “France” (car1.type == “Ferrari” && car2.type == “Lamborghini”) ||
(car1.type == “Lamborghini” && car2.type == “Ferrari”) -> “Italy” else -> throw Exception(“Unknown type”)
}
}
Smart casts
The Kotlin compiler tracks your logic and auto-casts types if possible, which means no more instanceof
checks followed by explicit casts.
if (obj is Car) {
obj.move()
}
Nullability
In most languages, when you declare a class variable it automatically gets default value of null
. This default value can lead to nasty NullPointerException
s in Java. Kotlin eliminates this by introducing optional ?
.
var name = “Tom”
name = null // compiler errorvar secretName: String? = “Agent X”
secretName = null // OK
To support optionals and nullability Kotlin introduced three new operators: (1) ?.
safe call operator which will either get the value or return null, (2) ?:
Elvis operator which will return default value if null
is found and (3) !!
operator which will throw NullPointerException
if null
is found.
val length = secretName?.length // returns null, as secretName is null
val defaultLength = secretName?.length ?: 0 // returns zero
val error = secretName!!.length // throws NullPointerException
Ranges and progressions
Kotlin does not provide a concept of regular Java for
loop. Instead of it, Kotlin uses a concept of ranges. A range is essentially an interval between two values. To define a range just use ..
operator. Note that ranges are closed and inclusive.
val oneToHundred = 1..100for (i in 1..100) { … }
for (i in 1 until 100) { … } // same as above
for (i in oneToHundred) { … } // same as abovefor (i in 100 downTo 1) { … } // reversefor (i in 10..100 step 10) { … } // only tens
Statically initialize collections
To initialize a collections inline, there is no need to use 3rd party library. Kotlin provides concise way by using listOf
, setOf
and mapOf
.
val wheels = listOf(2, 4, 6, 8, 12)
val cars = setOf(“BMW”, “Renault”, “Peugeout”, “Lamborghini”)
val agentNames = mapOf(1 to “The Boss”, 2 to “Left Hand”, 5 to “Agent X”)
Kotlin also provides deconstruction syntax to split map key/value pairs for easier access in iteration.
for ((rank, name) in agentNames) {
println(“Agent ${name} ranks as #${rank}”)
}
Extension functions and properties
A method or property defined outside of class, but called as a member of a class.
fun String.lastChar(): Char = this.get(this.length — 1)fun String.prefix(val value: String): String {
return value + this
}