Next level of Java
www.leanpub.com/effectivekotlin
www.kt.academy
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
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.
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."
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
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
val name = person?.name ?: "unknown"
val name = person?.name ?: throw Error("No person or name is null")
val name = person?.name ?: return
val name: String = "Marcin"
Read only
var name: String = "Marcin"
Read-write
val list = listOf("A", "B", "C")
val name: String by lazy { getNameFromForm() }
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")
// 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;
}
}
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)
// 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 class Person(
var name: String,
var surname: String,
var age: Int
)
class Person(
var name: String,
var surname: String,
var age: Int
)
val person = Person("Johny", "Bravo", 34)
println(person)
normal classs: Person@5305068a
data class: Person(name=Johny, surname=Bravo, age=34)
val person1 = Person("Johny", "Bravo", 21)
val person2 = Person("Johny", "Bravo", 21)
println(person1 == person2)
Java default behaviour: false
Kotlin data class behaiour: true
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)
Arrays.asList(1,2,3);
listOf(1,2,3)
List<Integer> list = new ArrayList();
list.add(1);
list.add(2);
list.add(3);
view.visibility = View.GONE
view.hide()
ViewUtils.hide(view)
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()
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
}
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
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
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
}
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
}
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)
}
//Declatative
val filteredList = list.filter{ it.startsWith("A")}
val list = listOf("Apple", "Lemon", "Avocado")
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
}
...
"This is Sparta".map { it.toUpperCase() }.toString() // THIS IS SPARTA
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
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 }
Native development
Native bytecode
We can easily use all platform-specific libraries and solutions
We use native libraries and solutions like OpenGL or GLES
Android
Studio
Intellij
Idea
Eclipse
CLion
Project
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
@marcinmoskala
marcinmoskala.com
contact@kt.academy