Kotlin boost yourproductivity

nklmish
nklmishSoftware engineer
Kotlin - Boost Your
Productivity
By Nklmish
@nklmish
Jetbrains
• Develops tools dedicated for
software developers.

• Large code base written in
Java (IDE and server side
tools). 

• E.g. IntelliJ-Community
edition, 3M+ lines of Java
code.
@nklmish
Back in 2010, Jetbrains were
looking for a language…
Java Interoperability
Can use existing Java code base & eco system
Reduce boilerplate code
Concise
Expressive
Easy tooling
Should be easy to prepare tooling for the language
Pragmatic
Solve real world problem
@nklmish
Why not X language ?
• “Most languages did not have the features we were
looking for, with the exception of Scala” - Dmitry Jemerov

• So why not Scala?

• Slow compilation time

• Tooling
@nklmish
Kotlin
• Open source programming language.

• Targets : Server side, client side web, mobile and
native.

• First commit - 8 Nov 2010, First release - 15 Feb
2016

• Gaining momentum - 20K+ repos and millions of lines
of code

• Google officially support it for android development.
@nklmish
Why Kotlin ?
Java Interoperability
We can use existing Java code & libraries as well

As call Java code from Kotlin and vice-versa
Null safety baked into type system
Safe
Statically Typed Easy tooling Pragmatic
Reduce boilerplate code
Concise
Expressive Small Learning Curve
Java developers can leverage there existing knowledge
Support Both
Let’s Get Started!
@nklmish
Hello
fun main(args: Array<String>) {
println("Hello")
}
@nklmish
Hello - source code level
fun main(args: Array<String>) {
println("Hello")
}
kotlin.Array
@nklmish
Hello - source code level
fun main(args: Array<String>) {
println("Hello")
}
kotlin.String
@nklmish
Hello - source code level
fun main(args: Array<String>) {
println("Hello")
}
kotlin.io.println
@nklmish
Hello- bytecode level
public final class com/nklmish/presentation/demo/s/_00Kt {
// access flags 0x19
public final static main([Ljava/lang/String;)V
@Lorg/jetbrains/annotations/NotNull;() // invisible, parameter 0
L0
ALOAD 0
LDC "args"
INVOKESTATIC kotlin/jvm/internal/Intrinsics.checkParameterIsNotNull (Ljava/lang/Object;Ljava/lang/String;)V
L1
LINENUMBER 7 L1
LDC "Hello"
ASTORE 1
L2
GETSTATIC java/lang/System.out : Ljava/io/PrintStream;
ALOAD 1
INVOKEVIRTUAL java/io/PrintStream.println (Ljava/lang/Object;)V
L3
L4
LINENUMBER 8 L4
RETURN
L5
LOCALVARIABLE args [Ljava/lang/String; L0 L5 0
MAXSTACK = 2
MAXLOCALS = 2
@Lkotlin/Metadata;(mv={1, 1, 7}, bv={1, 0, 2}, k=2,
d1={"u0000u0014nu0000nu0002u0010u0002nu0000nu0002u0010u0011nu0002u0010u000enu0002u0008u0002u001au0019u0010u0000u0
01au00020u00012u000cu0010u0002u001au0008u0012u0004u0012u00020u00040u0003u00a2u0006u0002u0010u0005u00a8u0006u0006"},
d2={"main", "", "args", "", "", "([Ljava/lang/String;)V", "production sources for module kotlin-presentation_main"})
// compiled from: 00.kt
// debug info: SMAP
00.kt
Kotlin
*S Kotlin
*F
+ 1 00.kt
com/nklmish/presentation/demo/s/_00Kt
*L
1#1,8:1
*E}
@nklmish
But how?
Let’s understand build process
@nklmish
Variable
@nklmish
List<Integer> list = new ArrayList<>(Arrays.asList(1, 2, 3));
val list: List<Int> = listOf(1, 2, 3)
Java Kotlin
Variable
@nklmish
List<Integer> list = new ArrayList<>(Arrays.asList(1, 2, 3));
val list: List<Int> = listOf(1, 2, 3)
Java Kotlin
Why Opposite ?
Variable
@nklmish
List<Integer> list = new ArrayList<>(Arrays.asList(1, 2, 3));
val list = listOf(1, 2, 3)
Java Kotlin
Type inference
Variable
@nklmish
List<Integer> list = new ArrayList<>(Arrays.asList(1, 2, 3));
val list = listOf(1, 2, 3)
Java Kotlin
IntelliJ view!
Function
@nklmish
Function
fun calculateBonus(base : Int, factor : Double) : Double {
return base * factor
}
@nklmish
Function
fun calculateBonus(base : Int, factor : Double) : Double {
return base * factor
}
Single Expression ?
@nklmish
Function
fun calculateBonus(base : Int, factor : Double) : Double {
return base * factor
}
Single Expression ?
Can be omitted
@nklmish
Function
fun calculateBonus(base : Int, factor : Double) : Double = base * factor
@nklmish
Function
fun calculateBonus(base : Int, factor : Double) : Double = base * factor
Type Inference
@nklmish
Function
fun calculateBonus(base : Int, factor : Double) = base * factor
@nklmish
Useful ?
Function
fun calculateBonus(base : Int, factor : Double) = base * factor
@nklmish
Concise +
refactor
Infix function == function
prefixed with “infix”
Must be a member/

extension function
@nklmish
Must take only one parameter
class Stack {
infix fun push(num : Int) {
//
}
}
fun main(args: Array<String>) {
val stack = Stack()
stack push 1
}
class Stack {
fun push(num : Int) {
//
}
}
fun main(args: Array<String>) {
val stack = Stack()
stack.push(1)
}
Infix function - real life
@nklmish
"should assign a default state for a newly launched game" {
game.states.count() shouldBe 1
}
val map = mapOf("Bob" to "123 North Avenue")
kotlintest
Kotlin
Extension functions ==
replace utility classes
@nklmish
fun LocalDateTime.toDate(): Date = Date.from(this.toInstant(OffsetDateTime.now().offset))
Higher order function
@nklmish
fun calculateTotal(amount : Double, exchange: (Double) -> Double) : Double {
val convertedAmount = exchange(amount)
return convertedAmount + (convertedAmount * 0.23)
}
Higher order function
@nklmish
fun calculateTotal(amount : Double, exchange: (Double) -> Double) : Double {
val convertedAmount = exchange(amount)
return convertedAmount + (convertedAmount * 0.23)
}
calculateTotal(100.00) {
amount -> amount * 4.5
}
calculateTotal(100.00) {
amount -> amount * 3.7
}
Invocation
Higher order function
fun calculateTotal(amount : Double, exchange: (Double) -> Double) : Double {
val convertedAmount = exchange(amount)
return convertedAmount + (convertedAmount * 0.23)
}
calculateTotal(100.00) {
amount -> amount * 4.5
}
calculateTotal(100.00) {
amount -> amount * 3.7
}
Lambda, extra cost (Wrapper Function), worried about runtime overhead ?
@nklmish
Inline function == avoid
runtime overhead
@nklmish
inline fun calculateTotal(amount : Double, exchange: (Double) -> Double) : Double {
val convertedAmount = exchange(amount)
return convertedAmount + (convertedAmount * 0.23)
}
Inline function == avoid
runtime overhead
@nklmish
inline fun calculateTotal(amount : Double, exchange: (Double) -> Double) : Double {
val convertedAmount = exchange(amount)
return convertedAmount + (convertedAmount * 0.23)
}
Compiler will replace this call with inline
(copy and paste) code
Inline function lambda
bytecode
@nklmish
inline fun calculateTotal(amount : Double, exchange: (Double) -> Double) : Double {
val convertedAmount = exchange(amount)
return convertedAmount + (convertedAmount * 0.23)
}
calculateTotal(100.00) {
amount -> amount * 4.5
}
calculateTotal(100.00) {
amount -> amount * 3.7
}
Inline function - time
measurement
@nklmish
val elapsedTime = measureTimeMillis { //execute the given code & returns elapsed time in ms.
calculateTotal(100.00) {
amount -> amount * 4.5
}
}
val elapsedTime = measureNanoTime { //execute the given block & returns elapsed time in ns.
...
}
Inline functions
Inline + reified == access
generic type info
@nklmish
@Suppress("UNCHECKED_CAST")
fun <T> Node.parent(clazz: Class<T>): T? {
var tmp = parent
while (tmp != null && !clazz.isInstance(tmp)) tmp = tmp.parent
return tmp as T?
}
//invocation
node.parent(Node::class.java)
Without reified
inline fun <reified T> Node.parent(): T? {
var tmp = parent
while (p != null && p !is T) tmp = tmp.parent
return p as T?
}
//invocation
node.parent<Node>()
Reified
Function literal with
receiver == recipe for DSL
@nklmish
class Delivery {
fun person(function: Person.() -> Unit) : Person {
...
}
fun address(function: Address.() -> Unit) : Address {
...
}
}
fun delivery(function: Delivery.() -> Unit): Delivery {
...
}
Extension fun on Delivery
Function literal with
receiver == recipe for DSL
@nklmish
class Delivery {
fun person(function: Person.() -> Unit) : Person {
...
}
fun address(function: Address.() -> Unit) : Address {
...
}
}
fun delivery(function: Delivery.() -> Unit): Delivery {
...
}
Extension fun on Delivery => we can access
Function literal with
receiver == recipe for DSL
@nklmish
delivery({ })
Syntactic sugar (if lambda is last argument)
delivery() { }== delivery { }==
Calling function “delivery” passing lambda as argument
Function literal with
receiver == recipe for DSL
@nklmish
Function literal with
receiver == recipe for DSL
@nklmish
class Delivery {
fun person(function: Person.() -> Unit) : Person {
...
}
fun address(function: Address.() -> Unit) : Address {
...
}
}
fun delivery(function: Delivery.() -> Unit): Delivery {
...
}
fun onTransit(function: () -> Unit) : TransitInfo {
…
}
fun sendSMS(message: String) {
...
}
Extension fun on Delivery
Extension fun on Address
Extension fun on Person
Higher Order Function
Function literal with
receiver == recipe for DSL
@nklmish
delivery {
person {
name = "Bob"
surname = "Smith"
}
address {
city = “paris"
street = "abc street"
postalCode = "12345"
onTransit {
sendSMS("...")
}
}
}
Final Result
Real life DSL - Anko
verticalLayout {
val name = editText()
button("Say Hello") {
onClick { toast("Hello, ${name.text}!") }
}
}
https://github.com/Kotlin/anko @nklmish
Real life DSL - GradleKotlinDSL
https://github.com/gradle/kotlin-dsl @nklmish
Overloading - Java
@nklmish
Overloading - Java
Which argument is which ?
@nklmish
Overloading - Kotlin
fun print(firstName : String, middleName: String = "", lastName : String = "") = { println("$firstName $middleName $lastName”) }
fun main(args: Array<String>) {
print(firstName = "john")
print(firstName = "john", lastName = "smith")
print(firstName = "john", middleName = "mac", lastName = "smith")
}
Default value Default value
@nklmish
Overloading - Kotlin
fun print(firstName : String, middleName: String = "", lastName : String = "") = println("$firstName $middleName $lastName")
fun main(args: Array<String>) {
print(firstName = "john")
print(firstName = "john", lastName = "smith")
print(firstName = "john", middleName = "mac", lastName = "smith")
}
Named arguments can further improve readability
Classes
@nklmish
Class - Java
public class Schedule {
private final LocalDateTime start;
private final LocalDateTime end;
private String notes;
public Schedule(LocalDateTime start, LocalDateTime end) {
this.start = start;
this.end = end;
}
public LocalDateTime getStart() {
return start;
}
public LocalDateTime getEnd() {
return end;
}
public String getNotes() {
return notes;
}
public void setNotes(String notes) {
this.notes = notes;
}
}
@nklmish
Class - Kotlin
class Schedule(val start: LocalDateTime, val end: LocalDateTime, var note : String)
@nklmish
Class - Kotlin
class Schedule(val start: LocalDateTime, val end: LocalDateTime, var note : String)
Default: public and final
@nklmish
Class - Kotlin
class Schedule(val start: LocalDateTime, val end: LocalDateTime, var note : String)
Properties
@nklmish
Class - Kotlin
class Schedule(val start: LocalDateTime, val end: LocalDateTime, var note : String)
Immutable Immutable
@nklmish
Class - Kotlin
class Schedule(val start: LocalDateTime, val end: LocalDateTime, var note : String)
Mutable
@nklmish
Data class == data holders
data class Schedule(val start : LocalDateTime, val end : LocalDateTime)
@nklmish
Data class
data class Schedule(val start : LocalDateTime, val end : LocalDateTime)
Autogenerate: meaningful toString(), copy(), equals(), hashcode()
@nklmish
Data class - copy()
val schedule = Schedule(LocalDateTime.now(), LocalDateTime.now().plusSeconds(1))
val copy = schedule.copy()
val copyWithModifiedEndDate = schedule.copy(end = schedule.end.plusSeconds(1)) // we
can change specific fields during copy, comes handy during unit testing
@nklmish
Data class - validation
data class Schedule(val start : LocalDateTime, val end : LocalDateTime) {
init {
if (end.isBefore(start)) throw IllegalArgumentException("end $end should be after start $start")
}
}
@nklmish
String interpolation
Note: String interpolation comes handy when dealing with JSON strings. e.g.
private val expectedServerContent = """
{"name":"$canonicalName","json":"{"id":"$expectedGameProviderId"}","data":{"@foo":".bar","number":"123"},"policy":"","password":""}
""".trimIndent()
Sealed class ~ extension of
enum classes
sealed class Bonus {
data class Yearly(val amount : BigDecimal) : Bonus()
data class Monthly(val amount : BigDecimal, val factor : BigDecimal) : Bonus()
}
@nklmish
Each enum constant exists only as 

a single instance
Enum
Subclass of a sealed class can have
multiple instances which can contain
state
Sealed class
Sealed class ~ extension of
enum classes
sealed class Bonus {
data class Yearly(val amount : BigDecimal) : Bonus()
data class Monthly(val amount : BigDecimal, val factor : BigDecimal) : Bonus()
}
fun evaluate(bonus: Bonus) = when(bonus) {
is Yearly -> bonus.amount
is Monthly -> bonus.amount.multiply(bonus.factor)
}
Abstract class
@nklmish
Delegation
@nklmish
Delegation
class NetworkChaosSimulator{
private ChaosSwitch chaosSwitch = new DefaultSwitch();
public void enableActivationChaos() {
chaosSwitch.enableActivationChaos();
}
public void disableActivationChaos() {
chaosSwitch.disableActivationChaos();
}
public void enableDeactivationChaos() {
chaosSwitch.enableDeactivationChaos();
}
public void disableDeactivationChaos() {
chaosSwitch.disableDeactivationChaos();
}
public boolean isActivationChaosEnabled() {
return chaosSwitch.isActivationChaosEnabled();
}
public boolean isDeactivationChaosEnabled() {
return chaosSwitch.isDeactivationChaosEnabled();
}
}
@nklmish
class NetworkChaosSimulator(switch: ChaosSwitch = DefaultSwitch())
: ChaosSwitch by switch
Java Kotlin
Delegated properties
• Wrap objects with custom behaviour.
@nklmish
Lazy
• Create a new instance only when an object get accessed
for the very first time.
@nklmish
Lazy
class GameRound(val player : String) {
val bets by lazy { fetchBets(this) }
private fun fetchBets(gameRound: GameRound): Int {
...
}
}
@nklmish
Lazy - thread safety ?
class GameRound(val player : String) {
val bets by lazy(mode = LazyThreadSafetyMode.SYNCHRONIZED) { fetchBets(this) }
private fun fetchBets(gameRound: GameRound): Int {
...
}
}
Only a single thread can initialise the Lazy instance.
@nklmish
Lazy - thread safety ?
class GameRound(val player : String) {
val bets by lazy(mode = LazyThreadSafetyMode.PUBLICATION) { fetchBets(this) }
private fun fetchBets(gameRound: GameRound): Int {
...
}
}
Concurrent access permissible but only first returned value will be used.
@nklmish
Lazy - thread safety ?
class GameRound(val player : String) {
val bets by lazy(mode = LazyThreadSafetyMode.NONE) { fetchBets(this) }
private fun fetchBets(gameRound: GameRound): Int {
...
}
}
multiple threads == undefined behaviour
@nklmish
There are more builtin delegated properties like notNull, observable, etc.
We can also create our own.
Lambda
@nklmish
players.filter({p -> p.score > 70})
@nklmish
players.filter({p -> p.score > 70})
players.filter() {p -> p.score > 70}
players.filter {p -> p.score > 70}
players.filter {it.score > 70}
syntactic sugar
Implicit name for a single parameter
@nklmish
• Allows to invoke methods of different object (w/o any
qualifiers) inside there body.
@nklmish@nklmish
with receiver
@nklmish
@nklmish@nklmish@nklmish
public String toCSVFormat(List<Integer> list) {
StringBuilder sb = new StringBuilder("[");
for (Integer integer : list) {
sb.append(integer).append(“;");
}
sb.deleteCharAt(sb.length() - 1);
sb.append("]");
return sb.toString();
}
Java
Kotlin : with (returns result of last call)
fun toCSVFormat(list: List<Int>) =
with(StringBuilder()) {
append("[")
for (i in list) {
append(i).append(";")
}
deleteCharAt(length - 1)
append("]")
toString()
}
with receiver - with
@nklmish@nklmish@nklmish
public String toCSVFormat(List<Integer> list) {
StringBuilder sb = new StringBuilder("[");
for (Integer integer : list) {
sb.append(integer).append(“;");
}
sb.deleteCharAt(sb.length() - 1);
sb.append("]");
return sb.toString();
}
Java Kotlin : apply (returns the receiver)
fun toCSVFormat(list: List<Int>) =
StringBuilder().apply {
append("[")
for (i in list) {
append(i).append(";")
}
deleteCharAt(length - 1)
append("]")
}.toString()
with receiver - apply
Safety
@nklmish
Null safety - baked into type
system
@nklmish
var message : String = "hello"
message = null // compile time error
var message : String? = "hello"
message = null // ok
println(message?.length) //safe operator, if not null then invoke length
Java
message?.let {
process(it)
}
Kotlin
if (message != null) {
process(message);
}
Null safety - using Java API
from Kotlin?
• Annotate Java code with nullability annotations.

• Kotlin can understand annotations from:

• Jetbrains (org.jetbrains.annotations)

• JSR-305 (javax.annotation)

• Android (android.support.annotation)
@nklmish
Misc
@nklmish
For loop - Java
for (int i = 0; i < 10; i++) {
System.out.println(i);
}
@nklmish
For loop - Kotlin
Progressions - to rescue
for (i in 0..9) println(i)
@nklmish
Progressions - to rescue
for (i in 0..9) println(i)
Lots of useful methods : downTo(), stepTo(), until…
@nklmish
Collection
• No Kotlin specific collections.

• Kotlin Collection == Java collection classes + enrichment.
@nklmish
Collection
Immutable
Mutable
@nklmish
Typealias
• Synonyms for pre-existing types
Typealias - without
fun main(args: Array<String>) {
val map : Map<String,String> = mapOf("Bob" to "North Avenue")
}
@nklmish
Less semantics
Typealias - with
typealias FirstName = String
typealias Street = String
fun main(args: Array<String>) {
val map : Map<FirstName, Street> = mapOf("Bob" to "North Avenue")
}
@nklmish
Better Semantics
Casting - Java
Object obj = "Any"
if (obj instanceof String) {
String str = (String) obj;
str.toUpperCase();
}
@nklmish
Casting - Kotlin (smartcast)
val obj:Any = "Any"
if (obj is String) {
obj.toUpperCase() // compiler smartness, auto cast to String
// Works only, if obj is immutable or 

// haven’t changed after check
}
@nklmish
Deprecation
@Deprecated(level = DeprecationLevel.WARNING,
message = "we are going to replace with StringUtils",
replaceWith = @ReplaceWith(
expression = "StringUtils.isEmpty(input)",
imports = {"org.apache.commons.lang3.StringUtils"})
)
public static boolean isEmpty(String input) {
...
}
@nklmish
Deprecation
@Deprecated(level = DeprecationLevel.WARNING,
message = "we are going to replace with StringUtils",
replaceWith = @ReplaceWith(
expression = "StringUtils.isEmpty(input)",
imports = {"org.apache.commons.lang3.StringUtils"})
)
public static boolean isEmpty(String input) {
...
}
level: Warning, Error, Hidden
@nklmish
Deprecation
@Deprecated(level = DeprecationLevel.WARNING,
message = "we are going to replace with StringUtils",
replaceWith = @ReplaceWith(
expression = "StringUtils.isEmpty(input)",
imports = {"org.apache.commons.lang3.StringUtils"})
)
public static boolean isEmpty(String input) {
...
}
Method to replace with
@nklmish
Deprecation
@Deprecated(level = DeprecationLevel.WARNING,
message = "we are going to replace with StringUtils",
replaceWith = @ReplaceWith(
expression = "StringUtils.isEmpty(input)",
imports = {"org.apache.commons.lang3.StringUtils"})
)
public static boolean isEmpty(String input) {
...
}
Which class to import
@nklmish
Deprecation - final result
@nklmish
when == powerful switch
fun playerPrivileges(rank : Int) = when(rank) {
in 1..3 -> "VIP"
in 4..50 -> "Elevated"
in 51..1000 -> "Classic"
else -> "Regular"
}
@nklmish
when == powerful switch
fun playerPrivileges(rank : Int) = when(rank) {
in 1..3 -> "VIP"
in 4..50 -> "Elevated"
in 51..1000 -> "Classic"
else -> "Regular"
}
Can be any type, no limitations
@nklmish
when == powerful switch
fun playerPrivileges(rank : Int) = when(rank) {
in 1..3 -> "VIP"
in 4..50 -> "Elevated"
in 51..1000 -> "Classic"
else -> "Regular"
}
No need to type break
@nklmish
Operator overloading -
Java?public class Wallet {
public Wallet(Integer amount) {
this.amount = amount;
}
private final Integer amount;
public Wallet plus(Wallet w) {
return new Wallet(this.amount + w.amount);
}
public Wallet minus(Wallet w) {
return new Wallet(this.amount - w.amount);
}
public Wallet multiply(Wallet w) {
return new Wallet(this.amount * w.amount);
}
}
Wallet walletA = new Wallet(100);
Wallet walletB = new Wallet(200);
walletA.plus(walletB);
walletA.subtract(walletB);
walletA.multiply(walletB);
@nklmish
Operator overloading -
Kotlin
data class Wallet(val amount : Int) {
operator fun plus(w : Wallet) = Wallet(amount.plus(w.amount))
operator fun minus(w : Wallet) = Wallet(amount.minus(w.amount))
operator fun times(w : Wallet) = Wallet(amount.minus(w.amount))
}
val walletA = Wallet(100)
val walletB = Wallet(200)
walletA + walletB
walletA - walletB
walletA * walletB
@nklmish
Operator overloading -
Kotlin
Naming Convention Syntax
plus walletA + walletB
unaryPlus +walletA
minus walletA - walletB
unaryMinus -walletA
inc ++walletA
dec — walletA
times walletA * walletB
div walletA / walletB
mod walletA % walletB
not !walletA
@nklmish
Co-routines == asyn
programming made simple
@nklmish
val jobs = List(1_000_000) {
async(CommonPool) {
delay(10L)
1.0
}
}
runBlocking {
println(jobs.sumByDouble { it.await() })
}
Co-routines == asyn
programming made simple
@nklmish
val jobs = List(1_000_000) {
async(CommonPool) {
delay(10L)
1.0
}
}
runBlocking {
println(jobs.sumByDouble { it.await() })
}
Lightweight
TODO
@nklmish
Kotlin + Spring
@nklmish
Kotlin + Spring
@nklmish
Kotlin + Spring -
build.gradle
@nklmish
dependencies {
classpath("org.jetbrains.kotlin:kotlin-allopen:$kotlinVersion")
}
Kotlin + Spring -
build.gradle
@nklmish
dependencies {
classpath("org.jetbrains.kotlin:kotlin-allopen:$kotlinVersion")
}
Before plugin
After Plugin
@SpringBootApplication
open class PhoneBookApplication {
@Bean
open fun passwordEncoder(): PasswordEncoder {
return BCryptPasswordEncoder()
}
}
@SpringBootApplication
class PhoneBookApplication {
@Bean
fun passwordEncoder(): PasswordEncoder {
return BCryptPasswordEncoder()
}
}
Kotlin + Spring -
build.gradle
@nklmish
dependencies {
classpath("org.jetbrains.kotlin:kotlin-allopen:$kotlinVersion")
}
@Document
data class Contact(@Id val id: String = UUID.randomUUID().toString(),
val firstName: String,
var lastName: String,
val phones: List<String> = emptyList()
)
Kotlin + Spring - controller
@nklmish
Kotlin + Spring - controller
@nklmish
Constructor injection(no @Autowired required)
Kotlin + Spring - controller
@nklmish
Type Inference
Kotlin + Spring - 

null safety?
@nklmish
@GetMapping("/schedule")
fun getSchedule(@RequestParam id: Long): Mono<ScheduleDto> =
scheduleService.findOne(id).map { it.get().dto() }
@GetMapping("/schedule")
fun getSchedule(@RequestParam id: Long?): Mono<ScheduleDto> =
scheduleService.findOne(id).map { it.get().dto() }
Kotlin + Spring - null safety
@nklmish
Kotlin + Spring
@nklmish
@GetMapping(path = arrayOf("/schedules"), produces = arrayOf(TEXT_EVENT_STREAM_VALUE))
fun getSchedules(): Flux<ScheduleDto> = scheduleService.findAll().map { it.dto() }
route(
path(“/schedules”).and(accept(TEXT_EVENT_STREAM_VALUE)),
)
Same thing expressed in Kotlin
Who uses Kotlin…
• Amazon

• Uber

• Netflix

• Foursquare

• Expedia

• HSBC

• Goldman Sachs

• Trello

• Casumo

• …
@nklmish
Useful links
• http://slack.kotlinlang.org/

• https://kotlin.link/
@nklmish
Questions?
https://tinyurl.com/y9lgkpc8
@nklmish
Review
1 of 119

Recommended

Introduction to kotlin for android app development gdg ahmedabad dev fest 2017 by
Introduction to kotlin for android app development   gdg ahmedabad dev fest 2017Introduction to kotlin for android app development   gdg ahmedabad dev fest 2017
Introduction to kotlin for android app development gdg ahmedabad dev fest 2017Hardik Trivedi
1.8K views45 slides
2017: Kotlin - now more than ever by
2017: Kotlin - now more than ever2017: Kotlin - now more than ever
2017: Kotlin - now more than everKai Koenig
1.8K views48 slides
Taking Kotlin to production, Seriously by
Taking Kotlin to production, SeriouslyTaking Kotlin to production, Seriously
Taking Kotlin to production, SeriouslyHaim Yadid
1.1K views33 slides
Coding for Android on steroids with Kotlin by
Coding for Android on steroids with KotlinCoding for Android on steroids with Kotlin
Coding for Android on steroids with KotlinKai Koenig
1.3K views55 slides
Introduction to kotlin by
Introduction to kotlinIntroduction to kotlin
Introduction to kotlinNAVER Engineering
5.6K views73 slides
Kotlin Developer Starter in Android projects by
Kotlin Developer Starter in Android projectsKotlin Developer Starter in Android projects
Kotlin Developer Starter in Android projectsBartosz Kosarzycki
5.1K views29 slides

More Related Content

What's hot

eMan Dev Meetup: Kotlin - A Language we should know it exists (part 02/03) 18... by
eMan Dev Meetup: Kotlin - A Language we should know it exists (part 02/03) 18...eMan Dev Meetup: Kotlin - A Language we should know it exists (part 02/03) 18...
eMan Dev Meetup: Kotlin - A Language we should know it exists (part 02/03) 18...eMan s.r.o.
412 views110 slides
Anko - The Ultimate Ninja of Kotlin Libraries? by
Anko - The Ultimate Ninja of Kotlin Libraries?Anko - The Ultimate Ninja of Kotlin Libraries?
Anko - The Ultimate Ninja of Kotlin Libraries?Kai Koenig
1.5K views54 slides
Building microservices with Kotlin by
Building microservices with KotlinBuilding microservices with Kotlin
Building microservices with KotlinHaim Yadid
4.1K views56 slides
Kotlin a problem solver - gdd extended pune by
Kotlin   a problem solver - gdd extended puneKotlin   a problem solver - gdd extended pune
Kotlin a problem solver - gdd extended puneHardik Trivedi
201 views43 slides
The Kotlin Programming Language by
The Kotlin Programming LanguageThe Kotlin Programming Language
The Kotlin Programming Languageintelliyole
9.4K views52 slides
Kotlin - Better Java by
Kotlin - Better JavaKotlin - Better Java
Kotlin - Better JavaDariusz Lorenc
1.5K views54 slides

What's hot(20)

eMan Dev Meetup: Kotlin - A Language we should know it exists (part 02/03) 18... by eMan s.r.o.
eMan Dev Meetup: Kotlin - A Language we should know it exists (part 02/03) 18...eMan Dev Meetup: Kotlin - A Language we should know it exists (part 02/03) 18...
eMan Dev Meetup: Kotlin - A Language we should know it exists (part 02/03) 18...
eMan s.r.o.412 views
Anko - The Ultimate Ninja of Kotlin Libraries? by Kai Koenig
Anko - The Ultimate Ninja of Kotlin Libraries?Anko - The Ultimate Ninja of Kotlin Libraries?
Anko - The Ultimate Ninja of Kotlin Libraries?
Kai Koenig1.5K views
Building microservices with Kotlin by Haim Yadid
Building microservices with KotlinBuilding microservices with Kotlin
Building microservices with Kotlin
Haim Yadid4.1K views
Kotlin a problem solver - gdd extended pune by Hardik Trivedi
Kotlin   a problem solver - gdd extended puneKotlin   a problem solver - gdd extended pune
Kotlin a problem solver - gdd extended pune
Hardik Trivedi201 views
The Kotlin Programming Language by intelliyole
The Kotlin Programming LanguageThe Kotlin Programming Language
The Kotlin Programming Language
intelliyole9.4K views
K is for Kotlin by TechMagic
K is for KotlinK is for Kotlin
K is for Kotlin
TechMagic514 views
Intro to Kotlin by Magda Miu
Intro to KotlinIntro to Kotlin
Intro to Kotlin
Magda Miu301 views
No excuses, switch to kotlin by Thijs Suijten
No excuses, switch to kotlinNo excuses, switch to kotlin
No excuses, switch to kotlin
Thijs Suijten586 views
Develop your next app with kotlin @ AndroidMakersFr 2017 by Arnaud Giuliani
Develop your next app with kotlin @ AndroidMakersFr 2017Develop your next app with kotlin @ AndroidMakersFr 2017
Develop your next app with kotlin @ AndroidMakersFr 2017
Arnaud Giuliani3.2K views
Kotlin in action by Ciro Rizzo
Kotlin in actionKotlin in action
Kotlin in action
Ciro Rizzo3.7K views
Swift and Kotlin Presentation by Andrzej Sitek
Swift and Kotlin PresentationSwift and Kotlin Presentation
Swift and Kotlin Presentation
Andrzej Sitek7.3K views
Kotlin, smarter development for the jvm by Arnaud Giuliani
Kotlin, smarter development for the jvmKotlin, smarter development for the jvm
Kotlin, smarter development for the jvm
Arnaud Giuliani898 views
Kotlin hands on - MorningTech ekito 2017 by Arnaud Giuliani
Kotlin hands on - MorningTech ekito 2017Kotlin hands on - MorningTech ekito 2017
Kotlin hands on - MorningTech ekito 2017
Arnaud Giuliani476 views
Little Helpers for Android Development with Kotlin by Kai Koenig
Little Helpers for Android Development with KotlinLittle Helpers for Android Development with Kotlin
Little Helpers for Android Development with Kotlin
Kai Koenig2.6K views
Kotlin: Challenges in JVM language design by Andrey Breslav
Kotlin: Challenges in JVM language designKotlin: Challenges in JVM language design
Kotlin: Challenges in JVM language design
Andrey Breslav2.2K views
Kotlin advanced - language reference for android developers by Bartosz Kosarzycki
Kotlin advanced - language reference for android developersKotlin advanced - language reference for android developers
Kotlin advanced - language reference for android developers
Bartosz Kosarzycki5.7K views
(How) can we benefit from adopting scala? by Tomasz Wrobel
(How) can we benefit from adopting scala?(How) can we benefit from adopting scala?
(How) can we benefit from adopting scala?
Tomasz Wrobel1.1K views
API management with Taffy and API Blueprint by Kai Koenig
API management with Taffy and API BlueprintAPI management with Taffy and API Blueprint
API management with Taffy and API Blueprint
Kai Koenig1.1K views

Similar to Kotlin boost yourproductivity

Scala in Places API by
Scala in Places APIScala in Places API
Scala in Places APIŁukasz Bałamut
629 views22 slides
Introduction to Kotlin by
Introduction to KotlinIntroduction to Kotlin
Introduction to KotlinOswald Campesato
444 views48 slides
Refactoring to Macros with Clojure by
Refactoring to Macros with ClojureRefactoring to Macros with Clojure
Refactoring to Macros with ClojureDmitry Buzdin
3.5K views51 slides
Functional Programming - Past, Present and Future by
Functional Programming - Past, Present and FutureFunctional Programming - Past, Present and Future
Functional Programming - Past, Present and FuturePushkar Kulkarni
458 views56 slides
Functional Programming Past Present Future by
Functional Programming Past Present FutureFunctional Programming Past Present Future
Functional Programming Past Present FutureIndicThreads
786 views56 slides
Cocoa Design Patterns in Swift by
Cocoa Design Patterns in SwiftCocoa Design Patterns in Swift
Cocoa Design Patterns in SwiftMichele Titolo
9.1K views106 slides

Similar to Kotlin boost yourproductivity(20)

Refactoring to Macros with Clojure by Dmitry Buzdin
Refactoring to Macros with ClojureRefactoring to Macros with Clojure
Refactoring to Macros with Clojure
Dmitry Buzdin3.5K views
Functional Programming - Past, Present and Future by Pushkar Kulkarni
Functional Programming - Past, Present and FutureFunctional Programming - Past, Present and Future
Functional Programming - Past, Present and Future
Pushkar Kulkarni458 views
Functional Programming Past Present Future by IndicThreads
Functional Programming Past Present FutureFunctional Programming Past Present Future
Functional Programming Past Present Future
IndicThreads786 views
Cocoa Design Patterns in Swift by Michele Titolo
Cocoa Design Patterns in SwiftCocoa Design Patterns in Swift
Cocoa Design Patterns in Swift
Michele Titolo9.1K views
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf by Hiroshi Ono
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfpragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
Hiroshi Ono370 views
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf by Hiroshi Ono
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfpragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
Hiroshi Ono406 views
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf by Hiroshi Ono
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfpragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
Hiroshi Ono524 views
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf by Hiroshi Ono
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfpragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
Hiroshi Ono760 views
What can be done with Java, but should better be done with Erlang (@pavlobaron) by Pavlo Baron
What can be done with Java, but should better be done with Erlang (@pavlobaron)What can be done with Java, but should better be done with Erlang (@pavlobaron)
What can be done with Java, but should better be done with Erlang (@pavlobaron)
Pavlo Baron2.2K views
Functional Programming With Scala by Knoldus Inc.
Functional Programming With ScalaFunctional Programming With Scala
Functional Programming With Scala
Knoldus Inc.802 views
Kotlin coroutines and spring framework by Sunghyouk Bae
Kotlin coroutines and spring frameworkKotlin coroutines and spring framework
Kotlin coroutines and spring framework
Sunghyouk Bae2.9K views
2019-01-29 - Demystifying Kotlin Coroutines by Eamonn Boyle
2019-01-29 - Demystifying Kotlin Coroutines2019-01-29 - Demystifying Kotlin Coroutines
2019-01-29 - Demystifying Kotlin Coroutines
Eamonn Boyle535 views
Emerging Languages: A Tour of the Horizon by Alex Payne
Emerging Languages: A Tour of the HorizonEmerging Languages: A Tour of the Horizon
Emerging Languages: A Tour of the Horizon
Alex Payne6.3K views
Java/Scala Lab: Анатолий Кметюк - Scala SubScript: Алгебра для реактивного пр... by GeeksLab Odessa
Java/Scala Lab: Анатолий Кметюк - Scala SubScript: Алгебра для реактивного пр...Java/Scala Lab: Анатолий Кметюк - Scala SubScript: Алгебра для реактивного пр...
Java/Scala Lab: Анатолий Кметюк - Scala SubScript: Алгебра для реактивного пр...
GeeksLab Odessa683 views
Scala for Java Programmers by Eric Pederson
Scala for Java ProgrammersScala for Java Programmers
Scala for Java Programmers
Eric Pederson967 views
Introduction to Scalding and Monoids by Hugo Gävert
Introduction to Scalding and MonoidsIntroduction to Scalding and Monoids
Introduction to Scalding and Monoids
Hugo Gävert7.6K views

More from nklmish

Demystifying Kafka by
Demystifying KafkaDemystifying Kafka
Demystifying Kafkanklmish
1.1K views81 slides
Scaling CQRS in theory, practice, and reality by
Scaling CQRS in theory, practice, and realityScaling CQRS in theory, practice, and reality
Scaling CQRS in theory, practice, and realitynklmish
535 views53 slides
CQRS and EventSourcing with Spring & Axon by
CQRS and EventSourcing with Spring & AxonCQRS and EventSourcing with Spring & Axon
CQRS and EventSourcing with Spring & Axonnklmish
1.3K views83 slides
(SPRING)KAFKA - ONE MORE ARSENAL IN A DISTRIBUTED TOOLBOX by
(SPRING)KAFKA - ONE MORE ARSENAL IN A DISTRIBUTED TOOLBOX(SPRING)KAFKA - ONE MORE ARSENAL IN A DISTRIBUTED TOOLBOX
(SPRING)KAFKA - ONE MORE ARSENAL IN A DISTRIBUTED TOOLBOXnklmish
1.1K views38 slides
Distributed tracing - get a grasp on your production by
Distributed tracing - get a grasp on your productionDistributed tracing - get a grasp on your production
Distributed tracing - get a grasp on your productionnklmish
2.2K views58 slides
Spock by
SpockSpock
Spocknklmish
728 views52 slides

More from nklmish(10)

Demystifying Kafka by nklmish
Demystifying KafkaDemystifying Kafka
Demystifying Kafka
nklmish1.1K views
Scaling CQRS in theory, practice, and reality by nklmish
Scaling CQRS in theory, practice, and realityScaling CQRS in theory, practice, and reality
Scaling CQRS in theory, practice, and reality
nklmish535 views
CQRS and EventSourcing with Spring & Axon by nklmish
CQRS and EventSourcing with Spring & AxonCQRS and EventSourcing with Spring & Axon
CQRS and EventSourcing with Spring & Axon
nklmish1.3K views
(SPRING)KAFKA - ONE MORE ARSENAL IN A DISTRIBUTED TOOLBOX by nklmish
(SPRING)KAFKA - ONE MORE ARSENAL IN A DISTRIBUTED TOOLBOX(SPRING)KAFKA - ONE MORE ARSENAL IN A DISTRIBUTED TOOLBOX
(SPRING)KAFKA - ONE MORE ARSENAL IN A DISTRIBUTED TOOLBOX
nklmish1.1K views
Distributed tracing - get a grasp on your production by nklmish
Distributed tracing - get a grasp on your productionDistributed tracing - get a grasp on your production
Distributed tracing - get a grasp on your production
nklmish2.2K views
Spock by nklmish
SpockSpock
Spock
nklmish728 views
Microservice no fluff, the REAL stuff by nklmish
Microservice no fluff, the REAL stuffMicroservice no fluff, the REAL stuff
Microservice no fluff, the REAL stuff
nklmish2.7K views
Neo4J by nklmish
Neo4JNeo4J
Neo4J
nklmish1.2K views
Mongo - an intermediate introduction by nklmish
Mongo - an intermediate introductionMongo - an intermediate introduction
Mongo - an intermediate introduction
nklmish614 views
Detailed Introduction To Docker by nklmish
Detailed Introduction To DockerDetailed Introduction To Docker
Detailed Introduction To Docker
nklmish1.2K views

Recently uploaded

Info Session November 2023.pdf by
Info Session November 2023.pdfInfo Session November 2023.pdf
Info Session November 2023.pdfAleksandraKoprivica4
12 views15 slides
Zero to Automated in Under a Year by
Zero to Automated in Under a YearZero to Automated in Under a Year
Zero to Automated in Under a YearNetwork Automation Forum
15 views23 slides
Igniting Next Level Productivity with AI-Infused Data Integration Workflows by
Igniting Next Level Productivity with AI-Infused Data Integration Workflows Igniting Next Level Productivity with AI-Infused Data Integration Workflows
Igniting Next Level Productivity with AI-Infused Data Integration Workflows Safe Software
263 views86 slides
STKI Israeli Market Study 2023 corrected forecast 2023_24 v3.pdf by
STKI Israeli Market Study 2023   corrected forecast 2023_24 v3.pdfSTKI Israeli Market Study 2023   corrected forecast 2023_24 v3.pdf
STKI Israeli Market Study 2023 corrected forecast 2023_24 v3.pdfDr. Jimmy Schwarzkopf
19 views29 slides
Mini-Track: Challenges to Network Automation Adoption by
Mini-Track: Challenges to Network Automation AdoptionMini-Track: Challenges to Network Automation Adoption
Mini-Track: Challenges to Network Automation AdoptionNetwork Automation Forum
12 views27 slides
TrustArc Webinar - Managing Online Tracking Technology Vendors_ A Checklist f... by
TrustArc Webinar - Managing Online Tracking Technology Vendors_ A Checklist f...TrustArc Webinar - Managing Online Tracking Technology Vendors_ A Checklist f...
TrustArc Webinar - Managing Online Tracking Technology Vendors_ A Checklist f...TrustArc
10 views29 slides

Recently uploaded(20)

Igniting Next Level Productivity with AI-Infused Data Integration Workflows by Safe Software
Igniting Next Level Productivity with AI-Infused Data Integration Workflows Igniting Next Level Productivity with AI-Infused Data Integration Workflows
Igniting Next Level Productivity with AI-Infused Data Integration Workflows
Safe Software263 views
STKI Israeli Market Study 2023 corrected forecast 2023_24 v3.pdf by Dr. Jimmy Schwarzkopf
STKI Israeli Market Study 2023   corrected forecast 2023_24 v3.pdfSTKI Israeli Market Study 2023   corrected forecast 2023_24 v3.pdf
STKI Israeli Market Study 2023 corrected forecast 2023_24 v3.pdf
TrustArc Webinar - Managing Online Tracking Technology Vendors_ A Checklist f... by TrustArc
TrustArc Webinar - Managing Online Tracking Technology Vendors_ A Checklist f...TrustArc Webinar - Managing Online Tracking Technology Vendors_ A Checklist f...
TrustArc Webinar - Managing Online Tracking Technology Vendors_ A Checklist f...
TrustArc10 views
PharoJS - Zürich Smalltalk Group Meetup November 2023 by Noury Bouraqadi
PharoJS - Zürich Smalltalk Group Meetup November 2023PharoJS - Zürich Smalltalk Group Meetup November 2023
PharoJS - Zürich Smalltalk Group Meetup November 2023
Noury Bouraqadi127 views
Data Integrity for Banking and Financial Services by Precisely
Data Integrity for Banking and Financial ServicesData Integrity for Banking and Financial Services
Data Integrity for Banking and Financial Services
Precisely21 views
Unit 1_Lecture 2_Physical Design of IoT.pdf by StephenTec
Unit 1_Lecture 2_Physical Design of IoT.pdfUnit 1_Lecture 2_Physical Design of IoT.pdf
Unit 1_Lecture 2_Physical Design of IoT.pdf
StephenTec12 views
Automating a World-Class Technology Conference; Behind the Scenes of CiscoLive by Network Automation Forum
Automating a World-Class Technology Conference; Behind the Scenes of CiscoLiveAutomating a World-Class Technology Conference; Behind the Scenes of CiscoLive
Automating a World-Class Technology Conference; Behind the Scenes of CiscoLive
STPI OctaNE CoE Brochure.pdf by madhurjyapb
STPI OctaNE CoE Brochure.pdfSTPI OctaNE CoE Brochure.pdf
STPI OctaNE CoE Brochure.pdf
madhurjyapb14 views
HTTP headers that make your website go faster - devs.gent November 2023 by Thijs Feryn
HTTP headers that make your website go faster - devs.gent November 2023HTTP headers that make your website go faster - devs.gent November 2023
HTTP headers that make your website go faster - devs.gent November 2023
Thijs Feryn22 views
SAP Automation Using Bar Code and FIORI.pdf by Virendra Rai, PMP
SAP Automation Using Bar Code and FIORI.pdfSAP Automation Using Bar Code and FIORI.pdf
SAP Automation Using Bar Code and FIORI.pdf

Kotlin boost yourproductivity

  • 1. Kotlin - Boost Your Productivity By Nklmish @nklmish
  • 2. Jetbrains • Develops tools dedicated for software developers. • Large code base written in Java (IDE and server side tools). • E.g. IntelliJ-Community edition, 3M+ lines of Java code. @nklmish
  • 3. Back in 2010, Jetbrains were looking for a language… Java Interoperability Can use existing Java code base & eco system Reduce boilerplate code Concise Expressive Easy tooling Should be easy to prepare tooling for the language Pragmatic Solve real world problem @nklmish
  • 4. Why not X language ? • “Most languages did not have the features we were looking for, with the exception of Scala” - Dmitry Jemerov • So why not Scala? • Slow compilation time • Tooling @nklmish
  • 5. Kotlin • Open source programming language. • Targets : Server side, client side web, mobile and native. • First commit - 8 Nov 2010, First release - 15 Feb 2016 • Gaining momentum - 20K+ repos and millions of lines of code • Google officially support it for android development. @nklmish
  • 6. Why Kotlin ? Java Interoperability We can use existing Java code & libraries as well As call Java code from Kotlin and vice-versa Null safety baked into type system Safe Statically Typed Easy tooling Pragmatic Reduce boilerplate code Concise Expressive Small Learning Curve Java developers can leverage there existing knowledge Support Both
  • 8. Hello fun main(args: Array<String>) { println("Hello") } @nklmish
  • 9. Hello - source code level fun main(args: Array<String>) { println("Hello") } kotlin.Array @nklmish
  • 10. Hello - source code level fun main(args: Array<String>) { println("Hello") } kotlin.String @nklmish
  • 11. Hello - source code level fun main(args: Array<String>) { println("Hello") } kotlin.io.println @nklmish
  • 12. Hello- bytecode level public final class com/nklmish/presentation/demo/s/_00Kt { // access flags 0x19 public final static main([Ljava/lang/String;)V @Lorg/jetbrains/annotations/NotNull;() // invisible, parameter 0 L0 ALOAD 0 LDC "args" INVOKESTATIC kotlin/jvm/internal/Intrinsics.checkParameterIsNotNull (Ljava/lang/Object;Ljava/lang/String;)V L1 LINENUMBER 7 L1 LDC "Hello" ASTORE 1 L2 GETSTATIC java/lang/System.out : Ljava/io/PrintStream; ALOAD 1 INVOKEVIRTUAL java/io/PrintStream.println (Ljava/lang/Object;)V L3 L4 LINENUMBER 8 L4 RETURN L5 LOCALVARIABLE args [Ljava/lang/String; L0 L5 0 MAXSTACK = 2 MAXLOCALS = 2 @Lkotlin/Metadata;(mv={1, 1, 7}, bv={1, 0, 2}, k=2, d1={"u0000u0014nu0000nu0002u0010u0002nu0000nu0002u0010u0011nu0002u0010u000enu0002u0008u0002u001au0019u0010u0000u0 01au00020u00012u000cu0010u0002u001au0008u0012u0004u0012u00020u00040u0003u00a2u0006u0002u0010u0005u00a8u0006u0006"}, d2={"main", "", "args", "", "", "([Ljava/lang/String;)V", "production sources for module kotlin-presentation_main"}) // compiled from: 00.kt // debug info: SMAP 00.kt Kotlin *S Kotlin *F + 1 00.kt com/nklmish/presentation/demo/s/_00Kt *L 1#1,8:1 *E} @nklmish
  • 14. Let’s understand build process @nklmish
  • 15. Variable @nklmish List<Integer> list = new ArrayList<>(Arrays.asList(1, 2, 3)); val list: List<Int> = listOf(1, 2, 3) Java Kotlin
  • 16. Variable @nklmish List<Integer> list = new ArrayList<>(Arrays.asList(1, 2, 3)); val list: List<Int> = listOf(1, 2, 3) Java Kotlin Why Opposite ?
  • 17. Variable @nklmish List<Integer> list = new ArrayList<>(Arrays.asList(1, 2, 3)); val list = listOf(1, 2, 3) Java Kotlin Type inference
  • 18. Variable @nklmish List<Integer> list = new ArrayList<>(Arrays.asList(1, 2, 3)); val list = listOf(1, 2, 3) Java Kotlin IntelliJ view!
  • 20. Function fun calculateBonus(base : Int, factor : Double) : Double { return base * factor } @nklmish
  • 21. Function fun calculateBonus(base : Int, factor : Double) : Double { return base * factor } Single Expression ? @nklmish
  • 22. Function fun calculateBonus(base : Int, factor : Double) : Double { return base * factor } Single Expression ? Can be omitted @nklmish
  • 23. Function fun calculateBonus(base : Int, factor : Double) : Double = base * factor @nklmish
  • 24. Function fun calculateBonus(base : Int, factor : Double) : Double = base * factor Type Inference @nklmish
  • 25. Function fun calculateBonus(base : Int, factor : Double) = base * factor @nklmish Useful ?
  • 26. Function fun calculateBonus(base : Int, factor : Double) = base * factor @nklmish Concise + refactor
  • 27. Infix function == function prefixed with “infix” Must be a member/
 extension function @nklmish Must take only one parameter class Stack { infix fun push(num : Int) { // } } fun main(args: Array<String>) { val stack = Stack() stack push 1 } class Stack { fun push(num : Int) { // } } fun main(args: Array<String>) { val stack = Stack() stack.push(1) }
  • 28. Infix function - real life @nklmish "should assign a default state for a newly launched game" { game.states.count() shouldBe 1 } val map = mapOf("Bob" to "123 North Avenue") kotlintest Kotlin
  • 29. Extension functions == replace utility classes @nklmish fun LocalDateTime.toDate(): Date = Date.from(this.toInstant(OffsetDateTime.now().offset))
  • 30. Higher order function @nklmish fun calculateTotal(amount : Double, exchange: (Double) -> Double) : Double { val convertedAmount = exchange(amount) return convertedAmount + (convertedAmount * 0.23) }
  • 31. Higher order function @nklmish fun calculateTotal(amount : Double, exchange: (Double) -> Double) : Double { val convertedAmount = exchange(amount) return convertedAmount + (convertedAmount * 0.23) } calculateTotal(100.00) { amount -> amount * 4.5 } calculateTotal(100.00) { amount -> amount * 3.7 } Invocation
  • 32. Higher order function fun calculateTotal(amount : Double, exchange: (Double) -> Double) : Double { val convertedAmount = exchange(amount) return convertedAmount + (convertedAmount * 0.23) } calculateTotal(100.00) { amount -> amount * 4.5 } calculateTotal(100.00) { amount -> amount * 3.7 } Lambda, extra cost (Wrapper Function), worried about runtime overhead ? @nklmish
  • 33. Inline function == avoid runtime overhead @nklmish inline fun calculateTotal(amount : Double, exchange: (Double) -> Double) : Double { val convertedAmount = exchange(amount) return convertedAmount + (convertedAmount * 0.23) }
  • 34. Inline function == avoid runtime overhead @nklmish inline fun calculateTotal(amount : Double, exchange: (Double) -> Double) : Double { val convertedAmount = exchange(amount) return convertedAmount + (convertedAmount * 0.23) } Compiler will replace this call with inline (copy and paste) code
  • 35. Inline function lambda bytecode @nklmish inline fun calculateTotal(amount : Double, exchange: (Double) -> Double) : Double { val convertedAmount = exchange(amount) return convertedAmount + (convertedAmount * 0.23) } calculateTotal(100.00) { amount -> amount * 4.5 } calculateTotal(100.00) { amount -> amount * 3.7 }
  • 36. Inline function - time measurement @nklmish val elapsedTime = measureTimeMillis { //execute the given code & returns elapsed time in ms. calculateTotal(100.00) { amount -> amount * 4.5 } } val elapsedTime = measureNanoTime { //execute the given block & returns elapsed time in ns. ... } Inline functions
  • 37. Inline + reified == access generic type info @nklmish @Suppress("UNCHECKED_CAST") fun <T> Node.parent(clazz: Class<T>): T? { var tmp = parent while (tmp != null && !clazz.isInstance(tmp)) tmp = tmp.parent return tmp as T? } //invocation node.parent(Node::class.java) Without reified inline fun <reified T> Node.parent(): T? { var tmp = parent while (p != null && p !is T) tmp = tmp.parent return p as T? } //invocation node.parent<Node>() Reified
  • 38. Function literal with receiver == recipe for DSL @nklmish class Delivery { fun person(function: Person.() -> Unit) : Person { ... } fun address(function: Address.() -> Unit) : Address { ... } } fun delivery(function: Delivery.() -> Unit): Delivery { ... } Extension fun on Delivery
  • 39. Function literal with receiver == recipe for DSL @nklmish class Delivery { fun person(function: Person.() -> Unit) : Person { ... } fun address(function: Address.() -> Unit) : Address { ... } } fun delivery(function: Delivery.() -> Unit): Delivery { ... } Extension fun on Delivery => we can access
  • 40. Function literal with receiver == recipe for DSL @nklmish delivery({ }) Syntactic sugar (if lambda is last argument) delivery() { }== delivery { }== Calling function “delivery” passing lambda as argument
  • 41. Function literal with receiver == recipe for DSL @nklmish
  • 42. Function literal with receiver == recipe for DSL @nklmish class Delivery { fun person(function: Person.() -> Unit) : Person { ... } fun address(function: Address.() -> Unit) : Address { ... } } fun delivery(function: Delivery.() -> Unit): Delivery { ... } fun onTransit(function: () -> Unit) : TransitInfo { … } fun sendSMS(message: String) { ... } Extension fun on Delivery Extension fun on Address Extension fun on Person Higher Order Function
  • 43. Function literal with receiver == recipe for DSL @nklmish delivery { person { name = "Bob" surname = "Smith" } address { city = “paris" street = "abc street" postalCode = "12345" onTransit { sendSMS("...") } } } Final Result
  • 44. Real life DSL - Anko verticalLayout { val name = editText() button("Say Hello") { onClick { toast("Hello, ${name.text}!") } } } https://github.com/Kotlin/anko @nklmish
  • 45. Real life DSL - GradleKotlinDSL https://github.com/gradle/kotlin-dsl @nklmish
  • 47. Overloading - Java Which argument is which ? @nklmish
  • 48. Overloading - Kotlin fun print(firstName : String, middleName: String = "", lastName : String = "") = { println("$firstName $middleName $lastName”) } fun main(args: Array<String>) { print(firstName = "john") print(firstName = "john", lastName = "smith") print(firstName = "john", middleName = "mac", lastName = "smith") } Default value Default value @nklmish
  • 49. Overloading - Kotlin fun print(firstName : String, middleName: String = "", lastName : String = "") = println("$firstName $middleName $lastName") fun main(args: Array<String>) { print(firstName = "john") print(firstName = "john", lastName = "smith") print(firstName = "john", middleName = "mac", lastName = "smith") } Named arguments can further improve readability
  • 51. Class - Java public class Schedule { private final LocalDateTime start; private final LocalDateTime end; private String notes; public Schedule(LocalDateTime start, LocalDateTime end) { this.start = start; this.end = end; } public LocalDateTime getStart() { return start; } public LocalDateTime getEnd() { return end; } public String getNotes() { return notes; } public void setNotes(String notes) { this.notes = notes; } } @nklmish
  • 52. Class - Kotlin class Schedule(val start: LocalDateTime, val end: LocalDateTime, var note : String) @nklmish
  • 53. Class - Kotlin class Schedule(val start: LocalDateTime, val end: LocalDateTime, var note : String) Default: public and final @nklmish
  • 54. Class - Kotlin class Schedule(val start: LocalDateTime, val end: LocalDateTime, var note : String) Properties @nklmish
  • 55. Class - Kotlin class Schedule(val start: LocalDateTime, val end: LocalDateTime, var note : String) Immutable Immutable @nklmish
  • 56. Class - Kotlin class Schedule(val start: LocalDateTime, val end: LocalDateTime, var note : String) Mutable @nklmish
  • 57. Data class == data holders data class Schedule(val start : LocalDateTime, val end : LocalDateTime) @nklmish
  • 58. Data class data class Schedule(val start : LocalDateTime, val end : LocalDateTime) Autogenerate: meaningful toString(), copy(), equals(), hashcode() @nklmish
  • 59. Data class - copy() val schedule = Schedule(LocalDateTime.now(), LocalDateTime.now().plusSeconds(1)) val copy = schedule.copy() val copyWithModifiedEndDate = schedule.copy(end = schedule.end.plusSeconds(1)) // we can change specific fields during copy, comes handy during unit testing @nklmish
  • 60. Data class - validation data class Schedule(val start : LocalDateTime, val end : LocalDateTime) { init { if (end.isBefore(start)) throw IllegalArgumentException("end $end should be after start $start") } } @nklmish String interpolation Note: String interpolation comes handy when dealing with JSON strings. e.g. private val expectedServerContent = """ {"name":"$canonicalName","json":"{"id":"$expectedGameProviderId"}","data":{"@foo":".bar","number":"123"},"policy":"","password":""} """.trimIndent()
  • 61. Sealed class ~ extension of enum classes sealed class Bonus { data class Yearly(val amount : BigDecimal) : Bonus() data class Monthly(val amount : BigDecimal, val factor : BigDecimal) : Bonus() } @nklmish Each enum constant exists only as 
 a single instance Enum Subclass of a sealed class can have multiple instances which can contain state Sealed class
  • 62. Sealed class ~ extension of enum classes sealed class Bonus { data class Yearly(val amount : BigDecimal) : Bonus() data class Monthly(val amount : BigDecimal, val factor : BigDecimal) : Bonus() } fun evaluate(bonus: Bonus) = when(bonus) { is Yearly -> bonus.amount is Monthly -> bonus.amount.multiply(bonus.factor) } Abstract class @nklmish
  • 64. Delegation class NetworkChaosSimulator{ private ChaosSwitch chaosSwitch = new DefaultSwitch(); public void enableActivationChaos() { chaosSwitch.enableActivationChaos(); } public void disableActivationChaos() { chaosSwitch.disableActivationChaos(); } public void enableDeactivationChaos() { chaosSwitch.enableDeactivationChaos(); } public void disableDeactivationChaos() { chaosSwitch.disableDeactivationChaos(); } public boolean isActivationChaosEnabled() { return chaosSwitch.isActivationChaosEnabled(); } public boolean isDeactivationChaosEnabled() { return chaosSwitch.isDeactivationChaosEnabled(); } } @nklmish class NetworkChaosSimulator(switch: ChaosSwitch = DefaultSwitch()) : ChaosSwitch by switch Java Kotlin
  • 65. Delegated properties • Wrap objects with custom behaviour. @nklmish
  • 66. Lazy • Create a new instance only when an object get accessed for the very first time. @nklmish
  • 67. Lazy class GameRound(val player : String) { val bets by lazy { fetchBets(this) } private fun fetchBets(gameRound: GameRound): Int { ... } } @nklmish
  • 68. Lazy - thread safety ? class GameRound(val player : String) { val bets by lazy(mode = LazyThreadSafetyMode.SYNCHRONIZED) { fetchBets(this) } private fun fetchBets(gameRound: GameRound): Int { ... } } Only a single thread can initialise the Lazy instance. @nklmish
  • 69. Lazy - thread safety ? class GameRound(val player : String) { val bets by lazy(mode = LazyThreadSafetyMode.PUBLICATION) { fetchBets(this) } private fun fetchBets(gameRound: GameRound): Int { ... } } Concurrent access permissible but only first returned value will be used. @nklmish
  • 70. Lazy - thread safety ? class GameRound(val player : String) { val bets by lazy(mode = LazyThreadSafetyMode.NONE) { fetchBets(this) } private fun fetchBets(gameRound: GameRound): Int { ... } } multiple threads == undefined behaviour @nklmish There are more builtin delegated properties like notNull, observable, etc. We can also create our own.
  • 72. players.filter({p -> p.score > 70}) @nklmish
  • 73. players.filter({p -> p.score > 70}) players.filter() {p -> p.score > 70} players.filter {p -> p.score > 70} players.filter {it.score > 70} syntactic sugar Implicit name for a single parameter @nklmish
  • 74. • Allows to invoke methods of different object (w/o any qualifiers) inside there body. @nklmish@nklmish with receiver @nklmish
  • 75. @nklmish@nklmish@nklmish public String toCSVFormat(List<Integer> list) { StringBuilder sb = new StringBuilder("["); for (Integer integer : list) { sb.append(integer).append(“;"); } sb.deleteCharAt(sb.length() - 1); sb.append("]"); return sb.toString(); } Java Kotlin : with (returns result of last call) fun toCSVFormat(list: List<Int>) = with(StringBuilder()) { append("[") for (i in list) { append(i).append(";") } deleteCharAt(length - 1) append("]") toString() } with receiver - with
  • 76. @nklmish@nklmish@nklmish public String toCSVFormat(List<Integer> list) { StringBuilder sb = new StringBuilder("["); for (Integer integer : list) { sb.append(integer).append(“;"); } sb.deleteCharAt(sb.length() - 1); sb.append("]"); return sb.toString(); } Java Kotlin : apply (returns the receiver) fun toCSVFormat(list: List<Int>) = StringBuilder().apply { append("[") for (i in list) { append(i).append(";") } deleteCharAt(length - 1) append("]") }.toString() with receiver - apply
  • 78. Null safety - baked into type system @nklmish var message : String = "hello" message = null // compile time error var message : String? = "hello" message = null // ok println(message?.length) //safe operator, if not null then invoke length Java message?.let { process(it) } Kotlin if (message != null) { process(message); }
  • 79. Null safety - using Java API from Kotlin? • Annotate Java code with nullability annotations. • Kotlin can understand annotations from: • Jetbrains (org.jetbrains.annotations) • JSR-305 (javax.annotation) • Android (android.support.annotation) @nklmish
  • 81. For loop - Java for (int i = 0; i < 10; i++) { System.out.println(i); } @nklmish
  • 82. For loop - Kotlin
  • 83. Progressions - to rescue for (i in 0..9) println(i) @nklmish
  • 84. Progressions - to rescue for (i in 0..9) println(i) Lots of useful methods : downTo(), stepTo(), until… @nklmish
  • 85. Collection • No Kotlin specific collections. • Kotlin Collection == Java collection classes + enrichment. @nklmish
  • 87. Typealias • Synonyms for pre-existing types
  • 88. Typealias - without fun main(args: Array<String>) { val map : Map<String,String> = mapOf("Bob" to "North Avenue") } @nklmish Less semantics
  • 89. Typealias - with typealias FirstName = String typealias Street = String fun main(args: Array<String>) { val map : Map<FirstName, Street> = mapOf("Bob" to "North Avenue") } @nklmish Better Semantics
  • 90. Casting - Java Object obj = "Any" if (obj instanceof String) { String str = (String) obj; str.toUpperCase(); } @nklmish
  • 91. Casting - Kotlin (smartcast) val obj:Any = "Any" if (obj is String) { obj.toUpperCase() // compiler smartness, auto cast to String // Works only, if obj is immutable or 
 // haven’t changed after check } @nklmish
  • 92. Deprecation @Deprecated(level = DeprecationLevel.WARNING, message = "we are going to replace with StringUtils", replaceWith = @ReplaceWith( expression = "StringUtils.isEmpty(input)", imports = {"org.apache.commons.lang3.StringUtils"}) ) public static boolean isEmpty(String input) { ... } @nklmish
  • 93. Deprecation @Deprecated(level = DeprecationLevel.WARNING, message = "we are going to replace with StringUtils", replaceWith = @ReplaceWith( expression = "StringUtils.isEmpty(input)", imports = {"org.apache.commons.lang3.StringUtils"}) ) public static boolean isEmpty(String input) { ... } level: Warning, Error, Hidden @nklmish
  • 94. Deprecation @Deprecated(level = DeprecationLevel.WARNING, message = "we are going to replace with StringUtils", replaceWith = @ReplaceWith( expression = "StringUtils.isEmpty(input)", imports = {"org.apache.commons.lang3.StringUtils"}) ) public static boolean isEmpty(String input) { ... } Method to replace with @nklmish
  • 95. Deprecation @Deprecated(level = DeprecationLevel.WARNING, message = "we are going to replace with StringUtils", replaceWith = @ReplaceWith( expression = "StringUtils.isEmpty(input)", imports = {"org.apache.commons.lang3.StringUtils"}) ) public static boolean isEmpty(String input) { ... } Which class to import @nklmish
  • 96. Deprecation - final result @nklmish
  • 97. when == powerful switch fun playerPrivileges(rank : Int) = when(rank) { in 1..3 -> "VIP" in 4..50 -> "Elevated" in 51..1000 -> "Classic" else -> "Regular" } @nklmish
  • 98. when == powerful switch fun playerPrivileges(rank : Int) = when(rank) { in 1..3 -> "VIP" in 4..50 -> "Elevated" in 51..1000 -> "Classic" else -> "Regular" } Can be any type, no limitations @nklmish
  • 99. when == powerful switch fun playerPrivileges(rank : Int) = when(rank) { in 1..3 -> "VIP" in 4..50 -> "Elevated" in 51..1000 -> "Classic" else -> "Regular" } No need to type break @nklmish
  • 100. Operator overloading - Java?public class Wallet { public Wallet(Integer amount) { this.amount = amount; } private final Integer amount; public Wallet plus(Wallet w) { return new Wallet(this.amount + w.amount); } public Wallet minus(Wallet w) { return new Wallet(this.amount - w.amount); } public Wallet multiply(Wallet w) { return new Wallet(this.amount * w.amount); } } Wallet walletA = new Wallet(100); Wallet walletB = new Wallet(200); walletA.plus(walletB); walletA.subtract(walletB); walletA.multiply(walletB); @nklmish
  • 101. Operator overloading - Kotlin data class Wallet(val amount : Int) { operator fun plus(w : Wallet) = Wallet(amount.plus(w.amount)) operator fun minus(w : Wallet) = Wallet(amount.minus(w.amount)) operator fun times(w : Wallet) = Wallet(amount.minus(w.amount)) } val walletA = Wallet(100) val walletB = Wallet(200) walletA + walletB walletA - walletB walletA * walletB @nklmish
  • 102. Operator overloading - Kotlin Naming Convention Syntax plus walletA + walletB unaryPlus +walletA minus walletA - walletB unaryMinus -walletA inc ++walletA dec — walletA times walletA * walletB div walletA / walletB mod walletA % walletB not !walletA @nklmish
  • 103. Co-routines == asyn programming made simple @nklmish val jobs = List(1_000_000) { async(CommonPool) { delay(10L) 1.0 } } runBlocking { println(jobs.sumByDouble { it.await() }) }
  • 104. Co-routines == asyn programming made simple @nklmish val jobs = List(1_000_000) { async(CommonPool) { delay(10L) 1.0 } } runBlocking { println(jobs.sumByDouble { it.await() }) } Lightweight
  • 108. Kotlin + Spring - build.gradle @nklmish dependencies { classpath("org.jetbrains.kotlin:kotlin-allopen:$kotlinVersion") }
  • 109. Kotlin + Spring - build.gradle @nklmish dependencies { classpath("org.jetbrains.kotlin:kotlin-allopen:$kotlinVersion") } Before plugin After Plugin @SpringBootApplication open class PhoneBookApplication { @Bean open fun passwordEncoder(): PasswordEncoder { return BCryptPasswordEncoder() } } @SpringBootApplication class PhoneBookApplication { @Bean fun passwordEncoder(): PasswordEncoder { return BCryptPasswordEncoder() } }
  • 110. Kotlin + Spring - build.gradle @nklmish dependencies { classpath("org.jetbrains.kotlin:kotlin-allopen:$kotlinVersion") } @Document data class Contact(@Id val id: String = UUID.randomUUID().toString(), val firstName: String, var lastName: String, val phones: List<String> = emptyList() )
  • 111. Kotlin + Spring - controller @nklmish
  • 112. Kotlin + Spring - controller @nklmish Constructor injection(no @Autowired required)
  • 113. Kotlin + Spring - controller @nklmish Type Inference
  • 114. Kotlin + Spring - 
 null safety? @nklmish @GetMapping("/schedule") fun getSchedule(@RequestParam id: Long): Mono<ScheduleDto> = scheduleService.findOne(id).map { it.get().dto() } @GetMapping("/schedule") fun getSchedule(@RequestParam id: Long?): Mono<ScheduleDto> = scheduleService.findOne(id).map { it.get().dto() }
  • 115. Kotlin + Spring - null safety @nklmish
  • 116. Kotlin + Spring @nklmish @GetMapping(path = arrayOf("/schedules"), produces = arrayOf(TEXT_EVENT_STREAM_VALUE)) fun getSchedules(): Flux<ScheduleDto> = scheduleService.findAll().map { it.dto() } route( path(“/schedules”).and(accept(TEXT_EVENT_STREAM_VALUE)), ) Same thing expressed in Kotlin
  • 117. Who uses Kotlin… • Amazon • Uber • Netflix • Foursquare • Expedia • HSBC • Goldman Sachs • Trello • Casumo • … @nklmish
  • 118. Useful links • http://slack.kotlinlang.org/ • https://kotlin.link/ @nklmish