KOTLIN
BETTER JAVA
Dariusz Lorenc
MY KOTLIN
JOURNEY
WHY DO I CARE?
JAVA IS EVOLVING SLOWLY
▸ Java 5 - 2005
▸ for each, autoboxing, generics, better concurrency
▸ Java 6 - 2006
▸ Java 7 - 2011
▸ Java 8 - 2014
▸ lambdas, streams
▸ Java 9 - 2017?
” MOST PEOPLE TALK ABOUT JAVA THE LANGUAGE,
AND THIS MAY SOUND ODD COMING FROM ME, BUT
I COULD HARDLY CARE LESS. AT THE CORE OF THE
JAVA ECOSYSTEM IS THE JVM. “
James Gosling,

Creator of the Java Programming Language
OTHER JVM LANGUAGES
▸ Groovy
▸ dynamic language
▸ Scala
▸ too many features / steeper learning curve
▸ slow compilation time
▸ too much emphasis on FP?
▸ Clojure
▸ dynamic language, dynamically typed
▸ different syntex, too LISPy?
KOTLIN - KEY FEATURES
▸ Statically typed, statically compiled
▸ Built on proven solutions, but simplified
▸ Great Java inter-op
▸ OO at core
▸ FP-friendly
▸ function types
▸ immutability
▸ lets you program in functional style but does not force you
ANY BETTER?
▸ Fixes some basic java problems
▸ Draws inspiration from Effective Java
▸ Provides more modern syntax & concepts
▸ Avoids (java’s) boilerplate
▸ Focuses on pragmatism
SYNTAX
IN 3 SLIDES
VARIABLES / PROPERTIES
var greeting: String
private val hello: String = “hello”
*no static fields/properties
FUNCTIONS
fun greet(name: String): String {
return “hello $name”
}
private fun print(name: String) {
println(greet(name))
}
*no static functions
CLASSES
class Hello : Greeting {
private val greeting: String = “hello”
override fun greet() {
print(greeting)
}
}
WHY DO I CARE
Comparing to Java, Kotlin allows me to write
▸ safer
▸ concise and readable
code, so I can be
‣ more productive
but can still leverage
‣ java’s rich ecosystem
‣ JVM platform
SAFER
JAVA - WHAT COULD POSSIBLY GO WRONG
public class JavaGreeting {
private String greeting;
public JavaGreeting(String greeting) {
this.greeting = greeting;
}
public String getGreeting() {
return this.greeting;
}
}
JMM
CAN TRICK YOU
KOTLIN - FINAL PROPERTIES
class KotlinGreeting(val greeting: String)
JAVA - WHAT COULD POSSIBLY GO WRONG
public class JavaGreeting {
private final String greeting;
public JavaGreeting(String greeting) {
this.greeting = greeting;
}
public int length() {
return this.greeting.length();
}
}
NPE
#1 EXC. IN PROD
KOTLIN - NULL SAFETY
class KotlinGreeting(val greeting: String) {
fun length() = greeting.length
}
class KotlinGreeting(val greeting: String?) {
…
greeting?.length //enforced by compiler
greeting!!.length //enforced by compiler
}
JAVA - WHAT COULD POSSIBLY GO WRONG
public class JavaGreetings {
private final List<String> greetings;
public JavaGreetings(List<String> greetings) {
if (greetings == null)
throw new NullPointerException();
this.greetings = greetings;
}
public void addGreeting(String greeting) {
this.greetings.add(greeting);
}
}
KOTLIN - IMMUTABLE COLLECTIONS
class KotlinGreetings(
private val greetings: List<String>) {
fun addGreeting(greeting: String) {
greetings.add(“hola”) //doesn’t compile
}
}
class KotlinGreetings(
private val greetings: MutableList<String>)
JAVA - WHAT COULD POSSIBLY GO WRONG
interface Greeting { }
public class Hello extends Greeting {
public String say() {
return “hello”;
}
}
if (greeting instanceOf Greeting) {
Hello hello = (Hello) greeting
hello.say()
}
CLASS CAST
#7 EXC. IN PROD
KOTLIN - SMART CAST
if (greeting is Hello) {
greeting.say()
}
JAVA - WHAT COULD POSSIBLY GO WRONG
public String say() { return “hello”; }
say() == “hello”
KOTLIN - REFERENTIAL EQUALITY
fun say() = “hello”
say() == “hello” //true
say() === “hello” //false
say() !== “hello” //true
JAVA - WHAT COULD POSSIBLY GO WRONG
public class JavaGreeting {
private final String greeting;
public JavaGreeting(String greeting) {
this.greeting = greeting;
}
public boolean equals(Object aGreeting) {
//some ide-generated code
}
}
EQUALS-HASHCODE
CONTRACT
KOTLIN - DATA CLASSES
data class KotlinGreeting(val greeting: String)
JAVA - WHAT COULD POSSIBLY GO WRONG
public class JavaGreeting {
private final String greeting;
public JavaGreeting(String greeting) {
this.greeting = greeting;
}
public boolean equals(JavaGreeting aGreeting) {
//some ide-generated code
}
public int hashCode() {
//some ide-generated code
}
}
KOTLIN - OVERRIDE
class KotlinGreeting(val greeting: String) {
//computer says NO!
override fun equals(aGreeting: KotlinGreeting):
Boolean {
…
}
override fun hashCode(): Int {
…
}
}
JAVA - WHAT COULD POSSIBLY GO WRONG
public class JavaGreeting {
protected void sayHi() { … }
protected void sayHello() {
}
}
public class HelloGreeting extends JavaGreeting {
protected void sayHi() {
sayHello();
}
}
sayHi();
FRAGILE
BASE CLASS
KOTLIN - FINAL CLASSES & FUNCTIONS
class KotlinGreeting {
fun sayHi() { … }
fun sayHello() { … }
}
//computer says NO!
class HelloGreeting : KotlinGreeting {
}
OTHER SAFETY FEATURES
▸ Serialisable & inner classes
▸ No statics
▸ Functional code
▸ Safer multithreading
▸ More testable code
CONCISE &
READABLE
CONCISE & NOT READABLE
String one, two, three = two = one = "";
boolean a = false, b = one==two ? two==three : a
EXPRESSION BODY
fun greeting(): String {
return “Hello Kotlin”
}
fun greeting(): String = “Hello Kotlin”
TYPE INFERENCE
val greeting: String = “Hello Kotlin”
val greeting = “Hello Kotlin”
fun greeting(): String = “Hello Kotlin”
fun greeting() = “Hello Kotlin”
CLASS DECLARATION + CONSTRUCTOR + PROPERTIES
class KotlinGreeting(val greeting: String)
public class JavaGreeting {
private final String greeting;
public JavaGreeting(String greeting) {
this.greeting = greeting;
}
public String getGreeting() {
return this.greeting;
}
}
NAMED ARGUMENTS - SAY NO TO BUILDERS
class LangGreeting(
val greeting: String,
val lang: String
)
LangGreeting(greeting = “Hello”, lang = “Kotlin”)
LangGreeting(lang = “Java”, greeting = “bye, bye!”)
DEFAULT VALUES
class LangGreeting(
val greeting = “Hello”,
val lang: String
)
LangGreeting(lang = “Kotlin”)
LangGreeting(lang = “Java”, greeting = “bye, bye!”)
DATA CLASS
data class KotlinGreeting(val greeting: String)
‣ equals()
‣ hashCode()
‣ toString()
‣ copy()
‣ componentN()
DATA CLASSES & IMMUTABILITY
data class LangGreeting(
val greeting: String,
val lang: String
)
val kotlinGreeting = LangGreeting(
greeting = “Hello”,
lang = “Kotlin”
)
val javaGreeting = kotlinGreeting.copy(
lang = “Java”
)
DATA CLASSES & DESTRUCTURING
data class LangGreeting(
val greeting: String,
val lang: String
)
val (greeting, lang) = kotlinGreeting
LAMBDAS
val ints = 1..10
val doubled = ints.map { value -> value * 2 }
val doubled = ints.map { it * 2 }
DELEGATION
interface Greeting {
fun print()
}
class KotlinGreeting(val greeting: String) :
Greeting {
override fun print() { print(greeting) }
}
class DecoratedGreeting(g: Greeting) : Greeting by g
WHEN EXPRESSION
when (x) {
0, 1 -> print("x == 0 or x == 1")
else -> print("otherwise")
}
val y = when (x) {
0, 1 -> true
else -> false
}
CONCISE & READABLE - OTHER FEATURES
▸ Better defaults: final, public?, nested classes are not inner
▸ Extension functions
▸ Default imports
▸ Sealed classes
AND THERE IS MORE …
▸ Coroutines - experimental in Kotlin 1.1
▸ Better Kotlin support in Spring 5
▸ Spek
▸ Kotlin/Native
▸ Kotlin to JavaScript
▸ Gradle Kotlin Script
JAVA INTEROP & GOTCHAS
▸ Using Java libs in Kotlin is straightforward
▸ Using Kotlin libs in Java
▸ Understand how Kotlin compiles to Java
▸ Final classes - spring, mockito …
▸ mockito-kotlin wrapper
▸ kotlin-allopen & spring plugin
▸ `when` is a keyword
▸ “$” is used for string interpolation
REFERENCES
▸ http://kotlinlang.org/docs/reference/
▸ Kotlin in Action [Book]
▸ https://github.com/Kotlin/kotlin-koans
▸ https://try.kotlinlang.org/
▸ https://github.com/KotlinBy/awesome-kotlin
Q&A

Kotlin - Better Java

  • 1.
  • 2.
  • 3.
    WHY DO ICARE?
  • 4.
    JAVA IS EVOLVINGSLOWLY ▸ Java 5 - 2005 ▸ for each, autoboxing, generics, better concurrency ▸ Java 6 - 2006 ▸ Java 7 - 2011 ▸ Java 8 - 2014 ▸ lambdas, streams ▸ Java 9 - 2017?
  • 5.
    ” MOST PEOPLETALK ABOUT JAVA THE LANGUAGE, AND THIS MAY SOUND ODD COMING FROM ME, BUT I COULD HARDLY CARE LESS. AT THE CORE OF THE JAVA ECOSYSTEM IS THE JVM. “ James Gosling,
 Creator of the Java Programming Language
  • 6.
    OTHER JVM LANGUAGES ▸Groovy ▸ dynamic language ▸ Scala ▸ too many features / steeper learning curve ▸ slow compilation time ▸ too much emphasis on FP? ▸ Clojure ▸ dynamic language, dynamically typed ▸ different syntex, too LISPy?
  • 7.
    KOTLIN - KEYFEATURES ▸ Statically typed, statically compiled ▸ Built on proven solutions, but simplified ▸ Great Java inter-op ▸ OO at core ▸ FP-friendly ▸ function types ▸ immutability ▸ lets you program in functional style but does not force you
  • 8.
    ANY BETTER? ▸ Fixessome basic java problems ▸ Draws inspiration from Effective Java ▸ Provides more modern syntax & concepts ▸ Avoids (java’s) boilerplate ▸ Focuses on pragmatism
  • 9.
  • 10.
    VARIABLES / PROPERTIES vargreeting: String private val hello: String = “hello” *no static fields/properties
  • 11.
    FUNCTIONS fun greet(name: String):String { return “hello $name” } private fun print(name: String) { println(greet(name)) } *no static functions
  • 12.
    CLASSES class Hello :Greeting { private val greeting: String = “hello” override fun greet() { print(greeting) } }
  • 13.
    WHY DO ICARE Comparing to Java, Kotlin allows me to write ▸ safer ▸ concise and readable code, so I can be ‣ more productive but can still leverage ‣ java’s rich ecosystem ‣ JVM platform
  • 14.
  • 15.
    JAVA - WHATCOULD POSSIBLY GO WRONG public class JavaGreeting { private String greeting; public JavaGreeting(String greeting) { this.greeting = greeting; } public String getGreeting() { return this.greeting; } }
  • 16.
  • 17.
    KOTLIN - FINALPROPERTIES class KotlinGreeting(val greeting: String)
  • 18.
    JAVA - WHATCOULD POSSIBLY GO WRONG public class JavaGreeting { private final String greeting; public JavaGreeting(String greeting) { this.greeting = greeting; } public int length() { return this.greeting.length(); } }
  • 19.
  • 20.
    KOTLIN - NULLSAFETY class KotlinGreeting(val greeting: String) { fun length() = greeting.length } class KotlinGreeting(val greeting: String?) { … greeting?.length //enforced by compiler greeting!!.length //enforced by compiler }
  • 21.
    JAVA - WHATCOULD POSSIBLY GO WRONG public class JavaGreetings { private final List<String> greetings; public JavaGreetings(List<String> greetings) { if (greetings == null) throw new NullPointerException(); this.greetings = greetings; } public void addGreeting(String greeting) { this.greetings.add(greeting); } }
  • 22.
    KOTLIN - IMMUTABLECOLLECTIONS class KotlinGreetings( private val greetings: List<String>) { fun addGreeting(greeting: String) { greetings.add(“hola”) //doesn’t compile } } class KotlinGreetings( private val greetings: MutableList<String>)
  • 23.
    JAVA - WHATCOULD POSSIBLY GO WRONG interface Greeting { } public class Hello extends Greeting { public String say() { return “hello”; } } if (greeting instanceOf Greeting) { Hello hello = (Hello) greeting hello.say() }
  • 24.
  • 25.
    KOTLIN - SMARTCAST if (greeting is Hello) { greeting.say() }
  • 26.
    JAVA - WHATCOULD POSSIBLY GO WRONG public String say() { return “hello”; } say() == “hello”
  • 27.
    KOTLIN - REFERENTIALEQUALITY fun say() = “hello” say() == “hello” //true say() === “hello” //false say() !== “hello” //true
  • 28.
    JAVA - WHATCOULD POSSIBLY GO WRONG public class JavaGreeting { private final String greeting; public JavaGreeting(String greeting) { this.greeting = greeting; } public boolean equals(Object aGreeting) { //some ide-generated code } }
  • 29.
  • 30.
    KOTLIN - DATACLASSES data class KotlinGreeting(val greeting: String)
  • 31.
    JAVA - WHATCOULD POSSIBLY GO WRONG public class JavaGreeting { private final String greeting; public JavaGreeting(String greeting) { this.greeting = greeting; } public boolean equals(JavaGreeting aGreeting) { //some ide-generated code } public int hashCode() { //some ide-generated code } }
  • 32.
    KOTLIN - OVERRIDE classKotlinGreeting(val greeting: String) { //computer says NO! override fun equals(aGreeting: KotlinGreeting): Boolean { … } override fun hashCode(): Int { … } }
  • 33.
    JAVA - WHATCOULD POSSIBLY GO WRONG public class JavaGreeting { protected void sayHi() { … } protected void sayHello() { } } public class HelloGreeting extends JavaGreeting { protected void sayHi() { sayHello(); } } sayHi();
  • 34.
  • 35.
    KOTLIN - FINALCLASSES & FUNCTIONS class KotlinGreeting { fun sayHi() { … } fun sayHello() { … } } //computer says NO! class HelloGreeting : KotlinGreeting { }
  • 36.
    OTHER SAFETY FEATURES ▸Serialisable & inner classes ▸ No statics ▸ Functional code ▸ Safer multithreading ▸ More testable code
  • 37.
  • 38.
    CONCISE & NOTREADABLE String one, two, three = two = one = ""; boolean a = false, b = one==two ? two==three : a
  • 39.
    EXPRESSION BODY fun greeting():String { return “Hello Kotlin” } fun greeting(): String = “Hello Kotlin”
  • 40.
    TYPE INFERENCE val greeting:String = “Hello Kotlin” val greeting = “Hello Kotlin” fun greeting(): String = “Hello Kotlin” fun greeting() = “Hello Kotlin”
  • 41.
    CLASS DECLARATION +CONSTRUCTOR + PROPERTIES class KotlinGreeting(val greeting: String) public class JavaGreeting { private final String greeting; public JavaGreeting(String greeting) { this.greeting = greeting; } public String getGreeting() { return this.greeting; } }
  • 42.
    NAMED ARGUMENTS -SAY NO TO BUILDERS class LangGreeting( val greeting: String, val lang: String ) LangGreeting(greeting = “Hello”, lang = “Kotlin”) LangGreeting(lang = “Java”, greeting = “bye, bye!”)
  • 43.
    DEFAULT VALUES class LangGreeting( valgreeting = “Hello”, val lang: String ) LangGreeting(lang = “Kotlin”) LangGreeting(lang = “Java”, greeting = “bye, bye!”)
  • 44.
    DATA CLASS data classKotlinGreeting(val greeting: String) ‣ equals() ‣ hashCode() ‣ toString() ‣ copy() ‣ componentN()
  • 45.
    DATA CLASSES &IMMUTABILITY data class LangGreeting( val greeting: String, val lang: String ) val kotlinGreeting = LangGreeting( greeting = “Hello”, lang = “Kotlin” ) val javaGreeting = kotlinGreeting.copy( lang = “Java” )
  • 46.
    DATA CLASSES &DESTRUCTURING data class LangGreeting( val greeting: String, val lang: String ) val (greeting, lang) = kotlinGreeting
  • 47.
    LAMBDAS val ints =1..10 val doubled = ints.map { value -> value * 2 } val doubled = ints.map { it * 2 }
  • 48.
    DELEGATION interface Greeting { funprint() } class KotlinGreeting(val greeting: String) : Greeting { override fun print() { print(greeting) } } class DecoratedGreeting(g: Greeting) : Greeting by g
  • 49.
    WHEN EXPRESSION when (x){ 0, 1 -> print("x == 0 or x == 1") else -> print("otherwise") } val y = when (x) { 0, 1 -> true else -> false }
  • 50.
    CONCISE & READABLE- OTHER FEATURES ▸ Better defaults: final, public?, nested classes are not inner ▸ Extension functions ▸ Default imports ▸ Sealed classes
  • 51.
    AND THERE ISMORE … ▸ Coroutines - experimental in Kotlin 1.1 ▸ Better Kotlin support in Spring 5 ▸ Spek ▸ Kotlin/Native ▸ Kotlin to JavaScript ▸ Gradle Kotlin Script
  • 52.
    JAVA INTEROP &GOTCHAS ▸ Using Java libs in Kotlin is straightforward ▸ Using Kotlin libs in Java ▸ Understand how Kotlin compiles to Java ▸ Final classes - spring, mockito … ▸ mockito-kotlin wrapper ▸ kotlin-allopen & spring plugin ▸ `when` is a keyword ▸ “$” is used for string interpolation
  • 53.
    REFERENCES ▸ http://kotlinlang.org/docs/reference/ ▸ Kotlinin Action [Book] ▸ https://github.com/Kotlin/kotlin-koans ▸ https://try.kotlinlang.org/ ▸ https://github.com/KotlinBy/awesome-kotlin
  • 54.