Why Kotlin?

A language focused on developer delight

Kotlin

  • Built by Jetbrains (Intellij, Android Studio)
  • Java bytecode (Full Interop)
  • OO or Functional
  • Concise
  • Developer Focused
  • First class citizen (Spring and Android)
  • Non-nullable and immutable focus

Usage

  • Built by Jetbrains, but still open source
  • Almost 6 million users in last year. 13th most popular language, top 5 most loved
  • Used in Gradle, Spring
  • Used by Twitter, Reddit, Netflix, Pinterest, Uber, Coursera, Evernote, Slack, Trello, Tinder, Kickstarter
  • Google’s preferred language for Android App Development
  • Google Home reduced Null Pointer Exceptions by 33% by using more Kotlin

My Story

Why Kotlin?

Kotlin is Concise

Data Classes - Java

final class Pixel {
   private final float x;
   private final float y;
   private int index;

   public Pixel(float x, float y, int index){
       this.x = x;
       this.y = y;
       this.index = index;
   }

  ...
}

Data Classes - Java

final class Pixel {   
...
   public float getX(){
       return this.x;
   }

   public float getY(){
       return this.y;
   }

   public int getIndex(){
       return this.index;
   }

   public void setIndex(int newIndex){
       this.index = newIndex;
   }
}

Data Classes - Kotlin

class Pixel(val x: Float, val y: Float, var index: Int)
  • Name before Type
  • Constructor
  • Val vs Var

Property Access

Java

float x = pixel.getX();
pixel.setIndex(10);

Kotlin

val x = pixel.x
pixel.index = 10

Data Classes

data class Pixel(val x: Float, val y: Float, val index: Int)
  • equals(), hashCode(), toString() with all fields, copy() and more

A Quick Note on Functions

public boolean doThing(Pixel pixel) {
fun doThing(pixel: Pixel) : Boolean {

When Statements

public String evaluate(int number, boolean specialCase) {
   if (number <= 0){
       return "Bad Value";
     } else {
       return "Default";
   }
}

When Statements

public String evaluate(int number, boolean specialCase) {
   if (number <= 0){
       return "Bad Value";
   } else if (number == 2){
       return "Double";
   } else {
       return "Default";
   }
}

When Statements

public String evaluate(int number, boolean specialCase) {
   if (number <= 0){
       return "Bad Value";
   } else if (number == 1){
       if (specialCase){
           return "Special number one!";
       }
   } else if (number == 2){
       return "Double";
   } else {
       return "Default";
   }
}

When Statements

public String evaluate(int number, boolean specialCase) {
   if (number <= 0){
       return "Bad Value";
   } else if (number == 1){
       if (specialCase){
           return "Special number one!";
       } else {
           return "Single";
       }
   } else if (number == 2){
       return "Double";
   } else {
       return "Default";
   }
}

When Statements

fun evaluate(number: Int, specialCase: Boolean): String {
   return when {
       number <= 0 -> "Bad Value"
       number == 1 && specialCase -> "Special number one!"
       number == 1 -> "Single"
       number == 2 -> "Double"
       else -> "Default"
   }
}

When Statements

fun evaluate(number: Int): String {
   return when (number) {
       1 -> "Single"
       2 -> "Double"
       else -> "Default"
   }
}

Why Kotlin?

Kotlin is Interoperable

Interoperability

/*
Use any existing library on the JVM, as there’s 100% compatibility, including SAM support.
*/

import io.reactivex.Flowable
import io.reactivex.schedulers.Schedulers

Flowable
   .fromCallable {
       Thread.sleep(1000) //  imitate expensive computation
       "Done"
   }
   .subscribeOn(Schedulers.io())
   .observeOn(Schedulers.single())
   .subscribe(::println, Throwable::printStackTrace)

Interoperability

  • Java Bytecode
  • Java + Kotlin in the same project (strangler pattern)
  • Copy Java from Stack Overflow, get Kotlin
  • IDE Integration suggests better code

Why Kotlin?

Kotlin can be Non-Nullable

The Billion Dollar Mistake

var output: String
output = null   // Compilation error

The Billion Dollar Mistake

var output: String
output = null   // Compilation error

// Kotlin protects you from mistakenly operating on nullable types

val name: String? = null    // Nullable type
println(name.length())      // Compilation error

The Billion Dollar Mistake

var output: String
output = null   // Compilation error

// Kotlin protects you from mistakenly operating on nullable types

val name: String? = null    // Nullable type
println(name.length())      // Compilation error
println(name?.length ?: "None")

The Billion Dollar Mistake

var output: String
output = null   // Compilation error

// Kotlin protects you from mistakenly operating on nullable types

val name: String? = null    // Nullable type
println(name.length())      // Compilation error
println(name?.length ?: "None")


// And if you check a type is right, the compiler will auto-cast it for you

fun calculateTotal(obj: Any) {
   if (obj is Game)
       obj.calculateTotal()
}

Why Kotlin?

Kotlin can be Functional

Maps and Filters

@Test
fun mapFilterTest() {
   val list = listOf(1, 2, 3, 4, 5)

//    list.map { number -> number + 1 }
//    list.map { it + 1 }
//    assertEquals(listOf(2,3,4,5,6), list.map { it + 1 })

//    val expected = listOf(4, 5, 6)
//    val actual = list.map { it + 1 }.filter { it > 3 }

//    assertEquals(expected, actual)
}

Maps and Filters

@Test
fun mapFilterTest() {
   val list = listOf(1, 2, 3, 4, 5)

   list.map { number -> number + 1 }
//    list.map { it + 1 }
//    assertEquals(listOf(2,3,4,5,6), list.map { it + 1 })

//    val expected = listOf(4, 5, 6)
//    val actual = list.map { it + 1 }.filter { it > 3 }

//    assertEquals(expected, actual)
}

Maps and Filters

@Test
fun mapFilterTest() {
   val list = listOf(1, 2, 3, 4, 5)

   list.map { number -> number + 1 }
   list.map { it + 1 }
//    assertEquals(listOf(2,3,4,5,6), list.map { it + 1 })

//    val expected = listOf(4, 5, 6)
//    val actual = list.map { it + 1 }.filter { it > 3 }

//    assertEquals(expected, actual)
}

Maps and Filters

@Test
fun mapFilterTest() {
   val list = listOf(1, 2, 3, 4, 5)

   list.map { number -> number + 1 }
   list.map { it + 1 }
   assertEquals(listOf(2,3,4,5,6), list.map { it + 1 })

//    val expected = listOf(4, 5, 6)
//    val actual = list.map { it + 1 }.filter { it > 3 }

//    assertEquals(expected, actual)
}

Maps and Filters

@Test
fun mapFilterTest() {
   val list = listOf(1, 2, 3, 4, 5)

   list.map { number -> number + 1 }
   list.map { it + 1 }
   assertEquals(listOf(2,3,4,5,6), list.map { it + 1 })

   val expected = listOf(4, 5, 6)
   val actual = list.map { it + 1 }.filter { it > 3 }

   assertEquals(expected, actual)
}

First Class Functions

  • No need for classes if you don’t want them
  • Write functions outside of classes, and import and call them elsewhere
  • Pass functions as params to other functions
fun transformList(list: List<String>, transformation: (String) -> String) : List<String> {
   return list.map { transformation(it) }
}
val presentTenses = listOf("Jump", "Leap", "Hammer")
val makePastTense: (String) -> String = {present -> present + "ed"}
val pastTenses = transformList(presentTenses, makePastTense)

Why Kotlin?

Kotlin is Productive

Other Features

  • Lambdas
  • Extension functions
  • DSLs
  • Smart Cast
  • Objects (essentially singletons)
  • Coroutines (easier* concurrency)
  • Default Arguments
  • Named Arguments

Summary

  • Concise
  • Clean
  • Flexible

Thank you!