A presentation at Gradle Summit in in Palo Alto, CA, USA by Jake Wharton
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 "
class User {
public String getName() {
// ...
} X
public void setName(String name) {
// ...
} Y } Z
// ^^^ Java vvv Kotlin
val user = User() println ( "Name is "
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 {
"Jake" }
// ^^^ Kotlin
class User {
"Jake" }
// ^^^ Kotlin vvv Java User user = new User(); System. out .println( "Name is "
class User {
"Jake" }
// ^^^ Kotlin vvv Java User user = new User(); System. out .println( "Name is "
class User {
"Jake" }
// ^^^ Kotlin vvv Java User user = new User(); System. out .println( "Name is "
user.setName( "Jane" );
class User {
"Jake" }
// ^^^ Kotlin vvv Java User user = new User(); System. out .println( "Name is "
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 {
2 }
fun Date.isTuesday(): Boolean {
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 {
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 {
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
INSTANCEOF java/lang/Integer IFEQ L8 ALOAD 5
ALOAD 7
INVOKEINTERFACE java/util/Collection.add (Ljava/lang/Object;)Z
class User { D
"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'
apply plugin : 'org.jetbrains.kotlin.jvm'
apply plugin : 'org.jetbrains.kotlin.android'
apply plugin : 'kotlin2js'
apply plugin : 'konan'
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'
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
Kotlin’s popularity has been exploding in the past year. From last year’s announcement that Gradle would support it as a build language, to its adoption on large platforms like Android and Spring, to its general applicability for writing IDE and build system plugins, it’s hard to find an area that isn’t adopting the language in some form.
This talk will be an introduction to the language in the context of Gradle. After covering the language syntax and features and their benefits, we’ll look at why it’s great for authoring Gradle plugins. Finally, we’ll set the stage for Gradle’s Kotlin build script support for which there are other full talks at the conference.