Jake Wharton A Builder's Intro to Kotlin

Kotlin?

Why Kotlin?

Plugin Author

Plugin Author Buildscript Author

Plugin Author Buildscript Author App Developer

val firstName: String = "Jake" 
 val lastName: String? = null

val firstName: String = "Jake" 
 val lastName: String? = null

val firstName: String = "Jake" 
 val lastName: String? = null

val firstName: String = "Jake" 
 val lastName: String? = null

val firstName: String = "Jake" 
 val lastName: String? = null

val firstName = "Jake" 
 val lastName: String? = null

class User { 


public String getName() { 


// ... 


} 


public void setName(String name) { 


// ... 


} 
 }

// ^^^ Java

class User { 


public String getName() { 


// ... 


} X 


public void setName(String name) { 


// ... 


} Y 
 } Z

// ^^^ Java vvv Kotlin

val user = User() 
 println ( "Name is "

  • user. name )

class User { 


public String getName() { 


// ... 


} X 


public void setName(String name) { 


// ... 


} Y 
 } Z

// ^^^ Java vvv Kotlin

val user = User() 
 println ( "Name is "

  • user. name ) X

class User { 


public String getName() { 


// ... 


} X 


public void setName(String name) { 


// ... 


} Y 
 } Z

// ^^^ Java vvv Kotlin

val user = User() 
 println ( "Name is ${ user. name } " ) X

class User { 


public String getName() { 


// ... 


} X 


public void setName(String name) { 


// ... 


} Y 
 } Z

// ^^^ Java vvv Kotlin

val user = User() 
 println ( "Name is $ user " ) X

class User { 


public String getName() { 


// ... 


} X 


public void setName(String name) { 


// ... 


} Y 
 } Z

// ^^^ Java vvv Kotlin

val user = User() 
 println ( "Name is $ user " ) X

class User { 


var name

"Jake" 
 }

// ^^^ Kotlin

class User { 


var name

"Jake" 
 }

// ^^^ Kotlin vvv Java User user = new User(); System. out .println( "Name is "

  • user.getName());

class User { 


var name

"Jake" 
 }

// ^^^ Kotlin vvv Java User user = new User(); System. out .println( "Name is "

  • user.getName());

class User { 


var name

"Jake" 
 }

// ^^^ Kotlin vvv Java User user = new User(); System. out .println( "Name is "

  • user.getName());

user.setName( "Jane" );

class User { 


var name

"Jake" 
 }

// ^^^ Kotlin vvv Java User user = new User(); System. out .println( "Name is "

  • user.getName());

user.setName( "Jane" );

val user = User()

val user = User() 
 user = User()

val user = User() 
 user = User() 



 var currentUser = User() 
 currentUser = User()

fun Date.isTuesday(): Boolean { 


return day

2 
 }

fun Date.isTuesday(): Boolean { 


return day

2 
 }

val epoch = Date( 1970 , 0 , 0 ) 
 if (epoch. isTuesday ()) { 


println ( "The epoch was a Tuesday." ) 
 } else { 


println ( "The epoch was not a Tuesday." ) 
 }

fun Date.isTuesday(): Boolean { 


return day

2 
 }

val epoch = Date( 1970 , 0 , 0 ) 
 if (epoch. isTuesday ()) { 


println ( "The epoch was a Tuesday." ) 
 } else { 


println ( "The epoch was not a Tuesday." ) 
 }

fun Date.isTuesday(): Boolean { 


return day

2 
 }

val epoch = Date( 1970 , 0 , 0 ) 
 if (epoch. isTuesday ()) { 


println ( "The epoch was a Tuesday." ) 
 } else { 


println ( "The epoch was not a Tuesday." ) 
 } // ^^^ Kotlin vvv Java DateKt. isTuesday (date)

val executor = Executors.newSingleThreadExecutor(); 
 executor. execute { B println ( "Background thread!" ) } X

val executor = Executors.newSingleThreadExecutor();

val foo = Foo() 
 executor. execute (foo::printIt)

class Foo {

fun printIt() { B

println(

"Background thread!" ) } X

}

val executor = Executors.newSingleThreadExecutor();

val foo = Foo() 
 executor. execute (foo::printIt)

class Foo {

fun printIt() { B

println(

"Background thread!" ) } X

}

fun < T

List< T .filter(predicate: ( T ) -> Boolean): List< T { 


// ... 
 }

fun < T

List< T .filter(predicate: ( T ) -> Boolean): List< T { 


// ... 
 }

fun < T

List< T .filter(predicate: ( T ) -> Boolean): List< T { 


// ... 
 } A

val items = listOf ( 1 , 2 , 3 ) val odds = items. filter ( { item -> item % 2 != 0 } ) B

fun < T

List< T .filter(predicate: ( T ) -> Boolean): List< T { 


// ... 
 } A

val items = listOf ( 1 , 2 , 3 ) val odds = items. filter ( { item -> item % 2 != 0 } ) B

fun < T

List< T .filter(predicate: ( T ) -> Boolean): List< T { 


// ... 
 } A

val items = listOf ( 1 , 2 , 3 ) val odds = items. filter ( { it % 2 != 0 } ) B

fun < T

List< T .filter(predicate: ( T ) -> Boolean): List< T { 


// ... 
 } A

val items = listOf ( 1 , 2 , 3 ) val odds = items. filter () B { it % 2 != 0 }

fun < T

List< T .filter(predicate: ( T ) -> Boolean): List< T { 


// ... 
 } A

val items = listOf ( 1 , 2 , 3 ) val odds = items. filter { it % 2 != 0 }

fun < T

List< T .filter(predicate: ( T ) -> Boolean): List< T { 


// ... 
 } A

val items = listOf ( 1 , 2 , 3 ) val oddList = items. filter { it % 2 != 0 }

val oddSet = items. filterTo(mutableListOf()) { it % 2 != 0 }

fun < T

List< T .filter(predicate: ( T ) -> Boolean): List< T { 


// ... 
 } A

val items = listOf ( 1 , 2 , 3 ) val odds = items. filter { it % 2 != 0 }

inline fun < T

List< T .filter(predicate: ( T ) -> Boolean): List< T { 


// ... 
 } A

val items = listOf ( 1 , 2 , 3 ) val odds = items. filter { it % 2 != 0 }

inline fun < T

List< T .filter(predicate: ( T ) -> Boolean): List< T {

val destination = mutableListOf < T

()

for (item in this ) {

if (predicate(item)) destination.add(item) } B

return destination } A

val items = listOf ( 1 , 2 , 3 ) val odds = items. filter { it % 2 != 0 } val destination = mutableListOf <

() for (item in

) {

if ( item ) destination.add(item) } G

destination

inline fun < T

List< T .filter(predicate: ( T ) -> Boolean): List< T {

val destination = mutableListOf < T

()

for (item in this ) {

if (predicate(item)) destination.add(item) } B

return destination } A

val items = listOf ( 1 , 2 , 3 ) val destination = mutableListOf <Int>() for (item in items ) {

if (item % 2 != 0 ) destination.add(item) } G

val odds = destination

filter

it

fun < T

List< T .filterIsInstance(c: Class< T ): List< T { 


val destination = mutableListOf < T

() for (item in this ) {

if (c.isInstance(item)) destination.add(item)

}

return destination 
 } A

fun < T

List< T .filterIsInstance(c: Class< T ): List< T { 


val destination = mutableListOf < T

() for (item in this ) {

if (c.isInstance(item)) destination.add(item) } G

return destination 
 } A

fun < T

List< T .filterIsInstance(): List< T { 


val destination = mutableListOf < T

() for (item in this ) {

if (item in

T ) destination.add(item) } G

return destination 
 } A

c: Class<T> 


c.isInstance(
)

fun < T

List< T .filterIsInstance(): List< T { 


val destination = mutableListOf < T

() for (item in this ) {

if (item in

T ) destination.add(item) } G

return destination 
 } A

inline fun < T

List< T .filterIsInstance(): List< T { 


val destination = mutableListOf < T

() for (item in this ) {

if (item in

T ) destination.add(item) } G

return destination 
 } A

inline fun < reified T

List< T .filterIsInstance(): List< T { 


val destination = mutableListOf < T

() for (item in this ) {

if (item in

T ) destination.add(item) } G

return destination 
 } A

inline fun < reified T

List< T .filterIsInstance(): List< T { 


val destination = mutableListOf < T

() for (item in this ) {

if (item in

T ) destination.add(item) } G

return destination 
 } A

inline fun < reified T

List< T .filterIsInstance(): List< T { 


val destination = mutableListOf < T

() for (item in this ) {

if (item in

T ) destination.add(item)

}

return destination 
 } A val list = listOf ( 1 , 2f , 3 , 4f ) val ints = list. filterIsInstance <Int>()

inline fun < reified T

List< T .filterIsInstance(): List< T { 


val destination = mutableListOf < T

() for (item in this ) {

if (item in

T ) destination.add(item)

}

return destination 
 } A val list = listOf ( 1 , 2f , 3 , 4f ) val ints = list. filterIsInstance <Int>()

ALOAD 7

item

INSTANCEOF java/lang/Integer IFEQ L8 ALOAD 5

destination

ALOAD 7

item

INVOKEINTERFACE java/util/Collection.add (Ljava/lang/Object;)Z

class User { D 


val name

"Jake" 
 } A

class User(name: String) { D 


val name = name 
 } A 


    "

Jake"

class User( val

name : String) { 
 } A

class User( val

name : String)

class User( val

name : String)

val jake = User( "Jake" ) println ( "Hello, $ jake !" )

class User( val

name : String)

val jake = User( "Jake" ) println ( "Hello, $ jake !" )

Hello, User@3a71f4dd !

data class User( val

name : String)

val jake = User( "Jake" ) println ( "Hello, $ jake !" )

Hello, User@3a71f4dd !

@3a71f4dd data class User( val

name : String)

val jake = User( "Jake" ) println ( "Hello, $ jake !" )

Hello, User(name=Jake) !

data class User( val

name : String)

val jake = User( "Jake" ) println ( "Hello, $ jake !" )

Hello, User(name=Jake) !

class UserPersisence(db: SqlDatabase) {

private val deleteByName

= db.createStatement( "DELETE FROM user WHERE name = ?" )

fun delete(name: String) {

deleteByName .bind( 1 , name)

deleteByName .execute() } }

class UserPersisence(db: SqlDatabase) {

private val deleteByName

= db.createStatement( "DELETE FROM user WHERE name = ?" )

fun delete(name: String) {

deleteByName .bind( 1 , name)

deleteByName .execute() } B

} A

class UserPersisence(db: SqlDatabase) {

private val deleteByName by lazy {

db.createStatement( "DELETE FROM user WHERE name = ?" )

} C

fun delete(name: String) {

deleteByName .bind( 1 , name)

deleteByName .execute() } B

} A

val deleteByName by lazy {

db.createStatement( "DELETE FROM user WHERE name = ?" ) } C

val deleteByName by lazy {

db.createStatement( "DELETE FROM user WHERE name = ?" ) } C var name by Delegates.observable( "Jane" ) { prop, old, new ->

println ( "Name changed from $ old to $ new " ) }

val deleteByName by lazy {

db.createStatement( "DELETE FROM user WHERE name = ?" ) } C var name by Delegates.observable( "Jane" ) { prop, old, new ->

println ( "Name changed from $ old to $ new " ) }

var address by Delegates.notNull<String>()

val deleteByName by lazy {

db.createStatement( "DELETE FROM user WHERE name = ?" ) } C var name by Delegates.observable( "Jane" ) { prop, old, new ->

println ( "Name changed from $ old to $ new " ) }

var address by Delegates.notNull<String>() val nameView by bindView <TextView>(R. id . name )

val deleteByName by lazy {

db.createStatement( "DELETE FROM user WHERE name = ?" ) } C var name by Delegates.observable( "Jane" ) { prop, old, new ->

println ( "Name changed from $ old to $ new " ) }

var address by Delegates.notNull<String>() val nameView by bindView <TextView>(R. id . name )

fun main( vararg args: String) = runBlocking<Unit> {

val jobs = List ( 100_000 ) {

launch(CommonPool) {

delay( 1000L )

print ( "." )

} }

jobs.forEach { it.join() } }

Plugin Author Buildscript Author App Developer

App Developer

Plugin Author

Buildscript Author

apply plugin : 'org.jetbrains.kotlin.jvm'

apply plugin : 'org.jetbrains.kotlin.jvm' src/ main/ java/ Fizz.java Buzz.java

apply plugin : 'org.jetbrains.kotlin.jvm' src/ main/ java/ Fizz.java Buzz.kt

*.java *.kt

*.java *.kt kotlinc

*.java *.kt kotlinc

*.java *.kt kotlinc javac

*.java *.kt kotlinc javac

*.java *.kt kotlinc javac

kotlin-stdlib *.java *.kt kotlinc javac

kotlin-stdlib *.java *.kt kotlinc javac

kotlin-stdlib *.java *.kt kotlinc javac

project(':some-library')

apply plugin : 'org.jetbrains.kotlin.jvm'

apply plugin : 'org.jetbrains.kotlin.jvm'

apply plugin : 'org.jetbrains.kotlin.android '

apply plugin : 'org.jetbrains.kotlin.jvm'

apply plugin : 'org.jetbrains.kotlin.android'

apply plugin : 'kotlin2js '

apply plugin : 'org.jetbrains.kotlin.jvm'

apply plugin : 'org.jetbrains.kotlin.android'

apply plugin : 'kotlin2js'

apply plugin : 'konan'

Different classpath dependency

apply plugin : 'org.jetbrains.kotlin.jvm'

apply plugin : 'org.jetbrains.kotlin.android'

apply plugin : 'kotlin2js'

apply plugin : 'konan'

Different classpath dependency

or apply plugin : 'org.jetbrains.kotlin.platform.common ' apply plugin : 'org.jetbrains.kotlin.platform.jvm ' apply plugin : 'org.jetbrains.kotlin.platform.js ' apply plugin : 'konan'

Different classpath dependency

Plugin Author Buildscript Author App Developer

Buildscript Author

Plugin Author

App Developer

apply plugin : 'org.jetbrains.kotlin.jvm' apply plugin : 'org.jetbrains.kotlin.kapt' sourceCompatibility = JavaVersion. VERSION_1_8 targetCompatibility = JavaVersion. VERSION_1_8 dependencies { compile deps. kotlin .stdLibJre8 compile deps. javaPoet

compile deps. autoCommon

compileOnly deps. autoService

kapt deps. autoService

testCompile deps. junit

testCompile deps. truth

testCompile deps. compileTesting

}

apply plugin : 'org.jetbrains.kotlin.jvm' apply plugin : 'org.jetbrains.kotlin.kapt' sourceCompatibility = JavaVersion. VERSION_1_8 targetCompatibility = JavaVersion. VERSION_1_8 dependencies { compile deps. kotlin .stdLibJre8 compile deps. javaPoet

compile deps. autoCommon

compileOnly deps. autoService

kapt deps. autoService

testCompile deps. junit

testCompile deps. truth

testCompile deps. compileTesting

}

apply( plugin : 'org.jetbrains.kotlin.jvm' ) X

apply plugin : 'org.jetbrains.kotlin.kapt' sourceCompatibility = JavaVersion. VERSION_1_8 targetCompatibility = JavaVersion. VERSION_1_8 dependencies { compile deps. kotlin .stdLibJre8 compile deps. javaPoet

compile deps. autoCommon

compileOnly deps. autoService

kapt deps. autoService

testCompile deps. junit

testCompile deps. truth

testCompile deps. compileTesting

}

apply( singletonMap ( 'plugin' , 'org.jetbrains.kotlin.jvm' )) X

apply plugin : 'org.jetbrains.kotlin.kapt' sourceCompatibility = JavaVersion. VERSION_1_8 targetCompatibility = JavaVersion. VERSION_1_8 dependencies { compile deps. kotlin .stdLibJre8 compile deps. javaPoet

compile deps. autoCommon

compileOnly deps. autoService

kapt deps. autoService

testCompile deps. junit

testCompile deps. truth

testCompile deps. compileTesting

}

apply( singletonMap ( 'plugin' , 'org.jetbrains.kotlin.jvm' )) X

apply plugin : 'org.jetbrains.kotlin.kapt' sourceCompatibility = JavaVersion. VERSION_1_8 targetCompatibility = JavaVersion. VERSION_1_8 dependencies { compile deps. kotlin .stdLibJre8 compile deps. javaPoet

compile deps. autoCommon

compileOnly deps. autoService

kapt deps. autoService

testCompile deps. junit

testCompile deps. truth

testCompile deps. compileTesting

}

apply( singletonMap ( 'plugin' , 'org.jetbrains.kotlin.jvm' )) X

apply plugin : 'org.jetbrains.kotlin.kapt' sourceCompatibility = JavaVersion. VERSION_1_8 targetCompatibility = JavaVersion. VERSION_1_8 dependencies { compile deps. kotlin .stdLibJre8 compile deps. javaPoet

compile deps. autoCommon

compileOnly deps. autoService

kapt deps. autoService

testCompile deps. junit

testCompile deps. truth

testCompile deps. compileTesting

}

apply( singletonMap ( 'plugin' , 'org.jetbrains.kotlin.jvm' )) X

apply plugin : 'org.jetbrains.kotlin.kapt' sourceCompatibility = JavaVersion. VERSION_1_8 targetCompatibility = JavaVersion. VERSION_1_8 dependencies { compile deps. kotlin .stdLibJre8 compile(deps. javaPoet )

compile deps. autoCommon

compileOnly deps. autoService

kapt deps. autoService

testCompile deps. junit

testCompile deps. truth

testCompile deps. compileTesting

}

apply( singletonMap ( 'plugin' , 'org.jetbrains.kotlin.jvm' )) X

apply plugin : 'org.jetbrains.kotlin.kapt' sourceCompatibility = JavaVersion. VERSION_1_8 targetCompatibility = JavaVersion. VERSION_1_8 dependencies { compile deps. kotlin .stdLibJre8 compile(deps. javaPoet )

compile deps. autoCommon

compileOnly deps. autoService

kapt deps. autoService

testCompile deps. junit

testCompile deps. truth

testCompile deps. compileTesting

}

android { // ...

testOptions {

unitTests.all {

systemProperty( 'robolectric.dependency.repo.id' , 'example-nexus' ) systemProperty( 'robolectric.dependency.repo.url' ,

'https://nexus.example.com/content/groups/public' )

} }

}

android { // ...

testOptions {

unitTests.all {

systemProperty( 'robolectric.dependency.repo.id' , 'example-nexus' ) systemProperty( 'robolectric.dependency.repo.url' ,

'https://nexus.example.com/content/groups/public' )

} }

}

android { // ...

testOptions {

unitTests.all {

systemProperty( 'robolectric.dependency.repo.id' , 'example-nexus' ) systemProperty( 'robolectric.dependency.repo.url' ,

'https://nexus.example.com/content/groups/public' ) } 
 
 }

apply plugin : 'org.jetbrains.kotlin.jvm' apply plugin : 'org.jetbrains.kotlin.kapt' sourceCompatibility = JavaVersion. VERSION_1_8 targetCompatibility = JavaVersion. VERSION_1_8 dependencies { compile deps. kotlin .stdLibJre8 compile deps. javaPoet

compile deps. autoCommon

compileOnly deps. autoService

kapt deps. autoService

testCompile deps. junit

testCompile deps. truth

testCompile deps. compileTesting

} A java build.gradle

apply {

plugin( 'org.jetbrains.kotlin.jvm' )

plugin( 'org.jetbrains.kotlin.kapt' )

} java {

sourceCompatibility = JavaVersion. VERSION_1_8

targetCompatibility = JavaVersion. VERSION_1_8

}

dependencies { compile(deps. kotlin .stdLibJre8)

compile(deps. javaPoet )

compile(deps. autoCommon )

compileOnly(deps. autoService )

kapt(deps. autoService )

testCompile(deps. junit )

testCompile(deps. truth )

testCompile(deps. compileTesting )

} A build.gradle.kts

apply {

plugin( 'org.jetbrains.kotlin.jvm' )

plugin( 'org.jetbrains.kotlin.kapt' )

} java {

sourceCompatibility = JavaVersion. VERSION_1_8

targetCompatibility = JavaVersion. VERSION_1_8

}

dependencies { compile(deps. kotlin .stdLibJre8)

compile(deps. javaPoet )

compile(deps. autoCommon )

compileOnly(deps. autoService )

kapt(deps. autoService )

testCompile(deps. junit )

testCompile(deps. truth )

testCompile(deps. compileTesting )

} A build.gradle.kts

apply {

plugin( 'org.jetbrains.kotlin.jvm' )

plugin( 'org.jetbrains.kotlin.kapt' )

} java {

sourceCompatibility = JavaVersion. VERSION_1_8

targetCompatibility = JavaVersion. VERSION_1_8

}

dependencies { compile(deps. kotlin .stdLibJre8)

compile(deps. javaPoet )

compile(deps. autoCommon )

compileOnly(deps. autoService )

kapt(deps. autoService )

testCompile(deps. junit )

testCompile(deps. truth )

testCompile(deps. compileTesting )

} A build.gradle.kts

apply {

plugin( 'org.jetbrains.kotlin.jvm' )

plugin( 'org.jetbrains.kotlin.kapt' )

} java {

sourceCompatibility = JavaVersion. VERSION_1_8

targetCompatibility = JavaVersion. VERSION_1_8

}

dependencies { compile(deps. kotlin .stdLibJre8)

compile(deps. javaPoet )

compile(deps. autoCommon )

compileOnly(deps. autoService )

kapt(deps. autoService )

testCompile(deps. junit )

testCompile(deps. truth )

testCompile(deps. compileTesting )

} A build.gradle.kts

apply {

plugin( 'org.jetbrains.kotlin.jvm' )

plugin( 'org.jetbrains.kotlin.kapt' )

} java {

sourceCompatibility = JavaVersion. VERSION_1_8

targetCompatibility = JavaVersion. VERSION_1_8

}

dependencies { compile(deps. kotlin .stdLibJre8)

compile(deps. javaPoet )

compile(deps. autoCommon )

compileOnly(deps. autoService )

kapt(deps. autoService )

testCompile(deps. junit )

testCompile(deps. truth )

testCompile(deps. compileTesting )

} A build.gradle.kts

apply {

plugin( 'org.jetbrains.kotlin.jvm' )

plugin( 'org.jetbrains.kotlin.kapt' )

} java {

sourceCompatibility = JavaVersion. VERSION_1_8

targetCompatibility = JavaVersion. VERSION_1_8

}

dependencies { compile(deps. kotlin .stdLibJre8)

compile(deps. javaPoet )

compile(deps. autoCommon )

compileOnly(deps. autoService )

kapt(deps. autoService )

testCompile(deps. junit )

testCompile(deps. truth )

testCompile(deps. compileTesting )

} A build.gradle.kts

Plugin Author Buildscript Author App Developer

Plugin Author

Buildscript Author

App Developer

class My Plugin : Plugin<Project> {

override fun apply(project: Project) {

// ...

} B

} A

import org.gradle.kotlin.dsl.* class My Plugin : Plugin<Project> {

override fun apply(project: Project) {

// ...

} B

} A

kotlin-stdlib *.java *.kt kotlinc javac

kotlin-stdlib *.java *.kt kotlinc javac

apply plugin : 'your-gradle-plugin'

jakewharton jakewharton jakewharton twitter.com/ github.com/ .com A Builder's Intro to Kotlin