Kotlin
Next level of Java










www.leanpub.com/effectivekotlin

www.kt.academy
Kotlin history
2010
2011
2012
JetBrains unveiled Kotlin
Start Development
Open sourced
Feb 2016




Feb 2016
May 2016
May 2017
Official Android Support




https://trends.google.com/


https://android-developers.googleblog.com/2018/10/
kotlin-momentum-for-android-and-beyond.html
Safeness
Language safeness - more errors can be prevented by checks at compile time instead of falling at run time. Also language is referred as safe when it is promoting way of coding that is know as more secure.
Billion-dollar mistake

Sir Charles Hoare
"This has led to innumerable errors, vulnerabilities, and system crashes, which have probably caused a billion dollars of pain and damage in the last forty years."

Null safety
var person: Person

Must be inilialized
var person: Person = null

Not null type cannot be null
var person: Person? = null
? after type makes it nullable
person.name

Nullable must be unpacked
Null safety
person?.name
Safe call (null if person is null)
person!!.name
Unsafe call (exception if person is null)
if(person != null) {
person.name
}
Smart Cast (after nullability check, object is casted to not-null)
if(person == null)
return
person.name
if(person != null && person.name == "Marcin")
if(person == null || person.age < 18)
person?.school?.name
Elvis operator
val name = person?.name ?: "unknown"
val name = person?.name ?: throw Error("No person or name is null")

val name = person?.name ?: return
Read-only properties
val name: String = "Marcin"
Read only
var name: String = "Marcin"
Read-write
val list = listOf("A", "B", "C")
val name: String by lazy { getNameFromForm() }
Read-only properties
MutableList
Mutable
List
Immutable
var list = listOf("A", "B", "C")
list += "D"
list -= "A"
val list = mutableListOf("A", "B", "C")
list.add("D")
list.remove("A")
Object-Oriented
Kotlin
Classes


Classes
// Java
public class PersonJava {
private String name;
private String surname;
private int age;
PersonJava(String name, String surname, int age) {
this.setName(name);
this.setSurname(surname);
this.setAge(age);
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSurname() {
return surname;
}
public void setSurname(String surname) {
this.surname = surname;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
Classes
class Person {
var name: String
var surname: String
var age: Int
constructor(name: String, surname: String, age: Int) {
this.name = name
this.surname = surname
this.age = age
}
}
class Person(name: String, surname: String, age: Int) {
var name: String = name
var surname: String = surname
var age: Int = age
}
class Person(var name: String, var surname: String, var age: Int)
Classes
// Kotlin
class Person(
var name: String,
var surname: String,
var age: Int
)
// Java
public class PersonJava {
private String name;
private String surname;
private int age;
PersonJava(String name, String surname, int age) {
this.setName(name);
this.setSurname(surname);
this.setAge(age);
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSurname() {
return surname;
}
public void setSurname(String surname) {
this.surname = surname;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
Data Classes
data class Person(
var name: String,
var surname: String,
var age: Int
)
- toString
- equals / hashCode
- copy
class Person(
var name: String,
var surname: String,
var age: Int
)
Data Classes - toString
val person = Person("Johny", "Bravo", 34)
println(person)
normal classs: Person@5305068a
data class: Person(name=Johny, surname=Bravo, age=34)
Data Classes - equals
val person1 = Person("Johny", "Bravo", 21)
val person2 = Person("Johny", "Bravo", 21)
println(person1 == person2)
Java default behaviour: false
Kotlin data class behaiour: true
Data Classes - copy
val person1 = Person("Johny", "Bravo", 21)
val person2 = person1.copy(surname = "Cage")
println(person1)
println(person2)
Prints:
Person(name=Johny, surname=Bravo, age=21)
Person(name=Johny, surname=Cage, age=21)
val person1 = Person("Johny", "Bravo", 21)
val person2 = person1.copy()
println(person1)
println(person2)
Prints:
Person(name=Johny, surname=Bravo, age=21)
Person(name=Johny, surname=Bravo, age=21)
Conciseness and
code reusability
Java Utils hell

Java Utils hell
Arrays.asList(1,2,3);
listOf(1,2,3)
List<Integer> list = new ArrayList();
list.add(1);
list.add(2);
list.add(3);
Java Utils hell
view.visibility = View.GONE
view.hide()
ViewUtils.hide(view)
Java Utils hell
val replacedStr = StringUtils.replaceAll(str, "name" to name, "surname" to surname)
val capitalizedStr = StringUtils.capitalize(replacedStr)
str.replaceAll("{name}" to name, "{surname}" to surname)
.capitalize()


Kotlin extension functions
fun String.noLongerThen(max: Int): String {
return this.substring(0, Math.min(max, this.length))
}
fun main(args: Array<String>) {
println("Joe".noLongerThen(4)) // Joe
println("James".noLongerThen(4)) // Jame
println("Ashley".noLongerThen(4)) // Ashl
}
fun View.hide() {
this.visibility = View.GONE
}
Functions everywhere
fun double(i: Int) = i * 2
class A() {
fun triple(i: Int) = i * 3
fun twelveTimes(i: Int): Int {
fun fourTimes() = double(double(i))
return triple(fourTimes())
}
}
fun main(args: Array<String>) {
double(1) // 2
A().twelveTimes(2) // 24
}
Top-level function
Mamber function
Local function
Kotlin extension properties
val Context.inflater
get() = getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater
var View.isVisible: Boolean
get() = visibility == View.VISIBLE
set(value) {
visibility = if (value) View.VISIBLE else View.GONE
}
context.inflater
progress.isVisible = true
Higher level of code extraction
fun sum(a: Int, b: Int): Int {
var sum = 0
for (i in a..b) {
sum += i
}
return sum
}
fun product(a: Int, b: Int): Int {
var product = 1
for (i in a..b) {
product *= i
}
return product
}
Higher level of code extraction
fun sum(a: Int, b: Int) = fold(a, b, 0, { acc, i -> acc + i })
fun product(a: Int, b: Int) = fold(a, b, 1, { acc, i -> acc * i })
fun fold(a: Int, b: Int, initial: Int, operation: (Int, Int)->Int): Int {
var acc = initial
for (i in a..b) {
acc = operation(acc, i)
}
return acc
}
Higher level of code extraction
fun sum(a: Int, b: Int) = (a..b).fold(0) { acc, i -> acc + i }
fun product(a: Int, b: Int) = (a..b).fold(1) { acc, i -> acc * i }
//Imperative
val filteredList = arrayListOf<String>()
for (fruit in list) {
if (fruit.startsWith('A'))
filteredList.add(fruit)
}
Collection stream processing
//Declatative
val filteredList = list.filter{ it.startsWith("A")}
val list = listOf("Apple", "Lemon", "Avocado")
Collection stream processing

val filteredList = students
.filter { it.passing }
.filter { it.averageGrade > 4.0 }
.sortedBy { it.averageGrade }
.take(10)
inline fun <T, R> Iterable<T>.map(transform: (T) -> R): List<R> {
val destination = ArrayList<R>()
for (item in this) destination.add(transform(item))
return destination
}
inline fun <T> Iterable<T>.filter(predicate: (T) -> Boolean): List<T> {
val destination = ArrayList<T>()
for (item in this) if(predicate(item)) destination.add(item)
return destination
}
...
Collection stream processing
"This is Sparta".map { it.toUpperCase() }.toString() // THIS IS SPARTA

Collection stream processing
String processing
val str = list.joinToString("|", "(", ")", 2, "...", { it.toUpperCase() })
val str = list.joinToString(separator = "|")
Result: Apple|Lemon|Avocado
val str = list.joinToString(separator = "|", prefix = "(", postfix = ")")
Result: (Apple|Lemon|Avocado)
val str = list.joinToString(separator = "|", transform = { it.toUpperCase() })
Result: APPLE|LEMON|AVOCADO
Collection sorting
val personList: List<Person> = listOf(...)
val sortedList = personList.sortedWith(compareBy({ it.surname }, { it.name }))
val sortedList = personList.sortedWith(compareBy(Person::surname, Person::name))
val sortedList = personList.sortedBy { it.fullName }
Multiplatfom development





Native development
Native bytecode
We can easily use all platform-specific libraries and solutions
We use native libraries and solutions like OpenGL or GLES
Let's start using Kotlin

Website
IDE

Android
Studio
Intellij
Idea
Eclipse

CLion
IDE

Interoperability


Project








Java 2 Kotlin Converter


- Whole classes
- Paste code


Resources
References
Getting started with Kotlin on Android
https://developer.android.com/kotlin/get-started.html
Kotlin language reference
https://kotlinlang.org/docs/reference/
Kotlin Koans


www.kt.academy

blog.kotlin-academy.com
Biggest Medium publication dedicated to Kotlin
Questions?
@marcinmoskala
marcinmoskala.com
contact@kt.academy
Warsaw "Kotlin: Next level of Java"
By Marcin Moskala
Warsaw "Kotlin: Next level of Java"
- 1,198