Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Java vs Kotlin

Java vs Kotlin

Kotlin is bypassing all other JVM languages with incredible pace. In Android development, it is already the language to use! But Java also evolved in meantime. Let’s look at Kotlin and compare its features side by side.

Danny Preussler

June 04, 2019
Tweet

More Decks by Danny Preussler

Other Decks in Programming

Transcript

  1. Java
    vs
    Kotlin
    Danny Preussler, JNation

    View Slide

  2. @PreusslerBerlin
    about:me
    • Java developer since 2003
    • Kotlin developer since 2016
    • Google Developer Expert for Android and Kotlin
    • Introduced Kotlin at Groupon and Viacom

    View Slide

  3. @PreusslerBerlin
    sporttotal.tv
    • We are streaming under-
    medialised sports
    • Amateur and semi professional
    football
    • Professional Volleyball…

    View Slide

  4. @PreusslerBerlin

    View Slide

  5. @PreusslerBerlin

    View Slide

  6. @PreusslerBerlin
    Kotlin adoption
    • Languages developers
    want to learn in 2019
    • https://research.hackerrank.co
    m/developer-skills/2019

    View Slide

  7. @PreusslerBerlin
    Kotlin adoption
    Okt 18, GitHub:
    'Kotlin for Android now fastest-growing
    programming language'
    https://www.zdnet.com/article/microsofts-github-kotlin-for-android-
    now-fastest-growing-programming-language/

    View Slide

  8. @PreusslerBerlin
    Kotlin adoption
    Stackoverflow trends of JVM languages. #kotlin is first
    with a strong growth during the last 2 years.

    View Slide

  9. @PreusslerBerlin
    Kotlin adoption
    • JVM Ecosystem Report 2018 (10k questionaires):
    What is the principal JVM language you use for your
    main applications?
    • Kotlin edges past Groovy and Scala in language usage
    on 2.42%
    https://snyk.io/blog/jvm-ecosystem-report-2018/

    View Slide

  10. @PreusslerBerlin
    Kotlin adoption
    • 1.5M+ developers edited Kotlin code in 2018
    • 100M+ lines of Kotlin code
    • 96,000+ Kotlin GitHub repositories
    • Android — 1 in 4 apps (from top 1000) uses Kotlin
    • Server — х2 from 2017
    https://www.jetbrains.com/annualreport/2018/community/

    View Slide

  11. @PreusslerBerlin
    2010 2011 2012 2013 2014 2015 2016 2017 2018 2019
    The year: 2010
    Java6 has been around the 4th year

    View Slide

  12. @PreusslerBerlin
    2010 2011 2012 2013 2014 2015 2016 2017 2018 2019
    The year: 2010
    Kotlin Development started internally

    View Slide

  13. @PreusslerBerlin
    2010 2011 2012 2013 2014 2015 2016 2017 2018 2019
    July 2010
    Swift Development started

    View Slide

  14. @PreusslerBerlin
    2010 2011 2012 2013 2014 2015 2016 2017 2018 2019
    July 2011
    Java 7

    View Slide

  15. @PreusslerBerlin
    2010 2011 2012 2013 2014 2015 2016 2017 2018 2019
    July 2011
    JetBrains unveiled Project Kotlin

    View Slide

  16. @PreusslerBerlin
    2010 2011 2012 2013 2014 2015 2016 2017 2018 2019
    February 2012
    JetBrains open sourced Kotlin

    View Slide

  17. @PreusslerBerlin
    2010 2011 2012 2013 2014 2015 2016 2017 2018 2019
    March 2014
    Java 8

    View Slide

  18. @PreusslerBerlin
    2010 2011 2012 2013 2014 2015 2016 2017 2018 2019
    June 2014
    WWDC application became
    the first publicly released Swift app

    View Slide

  19. @PreusslerBerlin
    2010 2011 2012 2013 2014 2015 2016 2017 2018 2019
    September 2014
    Swift 1.0

    View Slide

  20. @PreusslerBerlin
    2010 2011 2012 2013 2014 2015 2016 2017 2018 2019
    Februar 2016
    Kotlin 1.0

    View Slide

  21. @PreusslerBerlin
    2010 2011 2012 2013 2014 2015 2016 2017 2018 2019
    Google I/O 2017
    Official Kotlin support
    for Android

    View Slide

  22. @PreusslerBerlin
    2010 2011 2012 2013 2014 2015 2016 2017 2018 2019
    September 2017
    Java 9

    View Slide

  23. @PreusslerBerlin
    2010 2011 2012 2013 2014 2015 2016 2017 2018 2019
    March 2018
    Java 10

    View Slide

  24. @PreusslerBerlin
    2010 2011 2012 2013 2014 2015 2016 2017 2018 2019
    Google I/O 2019
    Kotlin becomes preferred language
    for Android

    View Slide

  25. @PreusslerBerlin
    Why
    Kotlin?

    View Slide

  26. @PreusslerBerlin
    Goals of Kotlin
    Modern language
    Faster compilation than Scala Smaller footprint than Scala
    Designed to work perfectly with Java
    (designed for 6+8)

    View Slide

  27. @PreusslerBerlin
    Why Kotlin?
    Null safe
    Functional aspects
    Strongly typed but type Inference
    Reduces boilerplate

    View Slide

  28. @PreusslerBerlin
    Kotlin is..
    Strongly typed
    Dynamic typed
    Object orientated
    Functional
    kotlin
    java
    scala
    groovy
    clojure

    View Slide

  29. @PreusslerBerlin
    Makes developers happy
    Happiness

    View Slide

  30. @PreusslerBerlin
    Basics
    String someString;
    final String someConstantString;

    View Slide

  31. @PreusslerBerlin
    Basics

    View Slide

  32. @PreusslerBerlin
    Basics
    var someString: String
    val someConstantString: String

    View Slide

  33. @PreusslerBerlin
    The power of type inference
    Integer doSomething(String someString) {
    return someString.getLength();
    }

    View Slide

  34. @PreusslerBerlin
    The power of type inference

    View Slide

  35. @PreusslerBerlin
    The power of type inference
    fun doSomething(someString: String): Int {
    return someString.length
    }

    View Slide

  36. @PreusslerBerlin
    The power of type inference
    fun doSomething(someString: String): Int =
    someString.length

    View Slide

  37. @PreusslerBerlin
    The power of type inference
    fun doSomething(someString: String) =
    someString.length

    View Slide

  38. @PreusslerBerlin
    Type inference in Java
    HashMap x =
    new HashMap();

    View Slide

  39. @PreusslerBerlin
    Type inference in Java
    HashMap x =
    new HashMap();

    View Slide

  40. @PreusslerBerlin
    Type inference in Java 10
    var x = new HashMap();

    View Slide

  41. @PreusslerBerlin
    Type inference in Java 10
    Difference to Kotlin:
    • var is not a keyword in Java 10
    • it‘s a reserved type name

    View Slide

  42. @PreusslerBerlin
    Let’s talk
    about
    null

    View Slide

  43. @PreusslerBerlin
    Lets talk null
    I call it my billion-dollar mistake.
    It was the invention
    of the null reference
    in 1965
    Tony Hoare ( inventor of the null reference)

    View Slide

  44. @PreusslerBerlin
    Lets talk null
    if (button != null){
    button.onPressed();
    }

    View Slide

  45. @PreusslerBerlin
    Lets talk null
    if (button.isPresent()){
    button.get().onPressed();
    }

    View Slide

  46. @PreusslerBerlin
    Lets talk null

    View Slide

  47. @PreusslerBerlin
    Lets talk null
    button?.onPressed()

    View Slide

  48. @PreusslerBerlin
    Lets talk null
    someString?.length

    View Slide

  49. @PreusslerBerlin
    Lets talk null
    someString?.length ?: 0

    View Slide

  50. @PreusslerBerlin
    Lets talk null
    someString!!.length

    View Slide

  51. @PreusslerBerlin
    Lets talk null
    val someString : String? …

    View Slide

  52. @PreusslerBerlin
    Lets talk null
    • Equivalent in Java: @NonNull
    but runtime crash vs compiler only
    • Nullability is Part of Typesystem

    View Slide

  53. @PreusslerBerlin
    Lets talk null
    fun some(thing: String?) {…}
    public final void some(
    @Nullable String thing) {…}

    View Slide

  54. @PreusslerBerlin
    Lets talk null
    fun some(thing: String) {…}
    public final void some(
    @NotNull String thing) {
    checkParameterIsNotNull(thing, "thing");
    }

    View Slide

  55. @PreusslerBerlin
    Smart casts
    Object someString …
    if (someString instanceOf String) {
    ((String)someString).getLength();
    }

    View Slide

  56. @PreusslerBerlin
    Smart casts

    View Slide

  57. @PreusslerBerlin
    Smart casts
    val someString : Any
    if (someString is String) {
    someString.length
    }

    View Slide

  58. @PreusslerBerlin
    Getter, setter
    view.setVisibility(View.GONE);

    View Slide

  59. @PreusslerBerlin
    Getter, setter

    View Slide

  60. @PreusslerBerlin
    Getter, setter
    view.visibility = View.GONE

    View Slide

  61. @PreusslerBerlin
    Lambdas
    • Came in Java-8
    • Android devs had to rely on Retrolambda very long

    View Slide

  62. @PreusslerBerlin
    Lambdas
    list.forEach(
    element -> System.out.println(element)
    );

    View Slide

  63. @PreusslerBerlin
    Lambdas

    View Slide

  64. @PreusslerBerlin
    Lambdas
    list.forEach{
    element -> System.out.println(element)
    }

    View Slide

  65. @PreusslerBerlin
    Lambdas
    list.forEach{
    System.out.println(it)
    }

    View Slide

  66. @PreusslerBerlin
    Collections
    List myList =
    Arrays.asList("1", "2", "3")

    View Slide

  67. @PreusslerBerlin
    Collections

    View Slide

  68. @PreusslerBerlin
    Collections
    val myList = listOf("1", "2", "3")
    val myList = mutablelistOf("1", "2", "3")

    View Slide

  69. @PreusslerBerlin
    Streams
    tags.stream()
    .map(tag -> tag.replace("#", ""))
    .collect(joining(",");

    View Slide

  70. @PreusslerBerlin
    Streams

    View Slide

  71. @PreusslerBerlin
    Streams
    tags.map{ it.replace("#", "") }
    .join(",")

    View Slide

  72. @PreusslerBerlin
    Streams
    tags.asSequence().
    .map{ it.replace("#", "") }
    .join(",")

    View Slide

  73. @PreusslerBerlin
    default parameters vs overloading
    class Api {
    Api(String baseURl) {
    this(baseURl, CacheStrategy.NO_CACHE)
    }
    Api(String baseURl, CacheStrategy cache) {
    }
    }

    View Slide

  74. @PreusslerBerlin
    default parameters vs overloading

    View Slide

  75. @PreusslerBerlin
    default parameters vs overloading
    class Api(
    baseUrl: String,
    cache: CacheStrategy =
    CacheStrategy.NO_CACHE
    )

    View Slide

  76. @PreusslerBerlin
    default parameters vs overloading
    class Api(
    private val baseUrl: String,
    val cache: CacheStrategy =
    CacheStrategy.NO_CACHE
    )

    View Slide

  77. @PreusslerBerlin
    Data classes
    data class Team(
    val name: String? = null,
    val logo: String? = null
    )

    View Slide

  78. @PreusslerBerlin
    Sealed classes
    sealed class LoadingState {
    class Loading : LoadingState()
    class Loaded : LoadingState()
    class Empty : LoadingState()
    }

    View Slide

  79. @PreusslerBerlin
    Lazy initialization
    public class LazyField {
    private String value;
    public String getValue() {
    if (value == null) {
    value = computeValue();
    }
    return value
    }
    private String computeValue() {
    ....
    }
    }

    View Slide

  80. @PreusslerBerlin
    Lazy initialization

    View Slide

  81. @PreusslerBerlin
    Lazy initialization
    class LazyField {
    val: String by lazy { computeValue() }
    private fun computeValue()= …
    }

    View Slide

  82. @PreusslerBerlin
    Lazy initialization
    • Framework class like Activities: no control over
    constructor
    • How use the compiler to check for null?

    View Slide

  83. @PreusslerBerlin
    Late initialization
    • Framework class like Activities: no control over
    constructor
    • How use the compiler to check for null?

    View Slide

  84. @PreusslerBerlin
    Late initialization
    View someView;
    ...
    someView = findViewbyId(R.id.myView);

    View Slide

  85. @PreusslerBerlin
    Late initialization

    View Slide

  86. @PreusslerBerlin
    Late initialization
    lateinit someView: View
    ...
    someView = findViewbyId(R.id.myView);

    View Slide

  87. @PreusslerBerlin
    Primitives in Kotlin

    View Slide

  88. @PreusslerBerlin
    Primitives in Kotlin
    • No primitives

    View Slide

  89. @PreusslerBerlin
    Primitives in Kotlin
    • No primitives
    int a;
    Integer b;
    a: Integer

    View Slide

  90. @PreusslerBerlin
    Primitives in Kotlin
    • No primitives
    • Boxing? Therefore no boxing issues (mostly)
    int a;
    Integer b;
    a: Integer

    View Slide

  91. @PreusslerBerlin
    Primitives in Kotlin: Costs?
    • The numeric type usages in Kotlin are compiled
    into JVM primitives where possible.
    • Compiler decides

    View Slide

  92. @PreusslerBerlin
    Primitives in Kotlin: Costs?
    • The numeric type usages in Kotlin are compiled
    into JVM primitives where possible.
    • Compiler decides
    • Works because of missing widening
    int a = 1;
    double b = a;
    val a:Int = 1
    val b:Double = a

    View Slide

  93. @PreusslerBerlin
    Primitives in Kotlin
    • Nullable type cannot be primitive
    • Primitives cannot be used as a generic type
    argument.
    • List is equivalent of Java List
    • Therefore IntArray as type!

    View Slide

  94. @PreusslerBerlin
    Operator
    overloading

    View Slide

  95. @PreusslerBerlin
    Operator overloading
    operator fun plusAssign(callback: Callback) {
    callbacks.add(callback)
    }
    operator fun minusAssign(callback: Callback) {
    callbacks.remove(callback)
    }
    adapterCallbacks += {…}

    View Slide

  96. @PreusslerBerlin
    Expression Translated to
    a++ a.inc() + see below
    a-- a.dec() + see below
    Expression Translated to
    +a a.unaryPlus()
    -a a.unaryMinus()
    !a a.not()
    Expression Translated to
    a + b a.plus(b)
    a - b a.minus(b)
    a * b a.times(b)
    a / b a.div(b)
    a % b a.rem(b), a.mod(b) (deprecated)
    a..b a.rangeTo(b)

    View Slide

  97. @PreusslerBerlin
    Operator overloading
    Expression Translated to
    a > b a.compareTo(b) > 0
    a < b a.compareTo(b) < 0
    a >= b a.compareTo(b) >= 0
    a <= b a.compareTo(b) <= 0
    Expression Translated to
    a == b a?.equals(b) ?: (b === null)
    a != b !(a?.equals(b) ?: (b === null))

    View Slide

  98. @PreusslerBerlin
    Operator overloading
    Expression Translated to
    a in b b.contains(a)
    a !in b !b.contains(a)
    Expression Translated to
    a[i] a.get(i)
    a[i, j] a.get(i, j)
    a[i_1, ..., i_n] a.get(i_1, ..., i_n)
    a[i] = b a.set(i, b)
    a[i, j] = b a.set(i, j, b)
    a[i_1, ..., i_n] = b a.set(i_1, ..., i_n, b)

    View Slide

  99. @PreusslerBerlin
    Operator overloading
    Expression Translated to
    a() a.invoke()
    a(i) a.invoke(i)
    a(i, j) a.invoke(i, j)
    a(i_1, ..., i_n) a.invoke(i_1, ..., i_n)
    Expression Translated to
    a += b a.plusAssign(b)
    a -= b a.minusAssign(b)
    a *= b a.timesAssign(b)
    a /= b a.divAssign(b)
    a %= b a.remAssign(b), a.modAssign(b) (deprecated)

    View Slide

  100. @PreusslerBerlin
    Operator overloading
    • Range expression
    for (i in 1..4) print(i)
    operator fun rangeTo(other: Int) =
    IntRange(this, other)

    View Slide

  101. @PreusslerBerlin
    Operator overloading in RxKotlin
    disposables += clips.subscribeBy(
    onError = { logE(it) },
    onNext = { onNewClip(it) }
    )

    View Slide

  102. @PreusslerBerlin
    Getter / Setter
    var live = true
    private set

    View Slide

  103. @PreusslerBerlin
    Getter / Setter
    val live
    get() = category.live
    val live = category.live

    View Slide

  104. @PreusslerBerlin
    Getter / Setter
    val live
    get() = category.live

    View Slide

  105. @PreusslerBerlin
    Getter / Setter
    val live
    get() = category.live
    public final boolean getLive() {
    return category.getLive();
    }

    View Slide

  106. @PreusslerBerlin
    Delegated properties
    var something: Something by lazy{}
    var something: Something by inject{}

    View Slide

  107. @PreusslerBerlin
    Delegation
    • inheritance
    Effective Java:
    Item 16: Favor composition over inheritance
    class FirebaseFeatureFlags (
    private val defaults: DefaultFeatureFlags
    ) : FeatureFlags by defaults {

    View Slide

  108. @PreusslerBerlin
    Singleton
    class Singleton {
    final static Singleton instance
    = new Singleton()
    private Singleton() {}
    }

    View Slide

  109. @PreusslerBerlin
    Singleton

    View Slide

  110. @PreusslerBerlin
    Singleton
    object Singleton

    View Slide

  111. @PreusslerBerlin
    Extension functions
    class Utils {
    public static boolean
    isNonNullOrEmpty(String string){

    }
    }
    isNonNullOrEmpty(“hallo“)

    View Slide

  112. @PreusslerBerlin
    Extension functions

    View Slide

  113. @PreusslerBerlin
    Extension functions
    fun String?.isNonNullOrEmpty() = {…}
    “hallo“.isNonNullOrEmpty()

    View Slide

  114. @PreusslerBerlin
    Extension functions
    fun String?.isNonNullOrEmpty() = {…}
    public static final boolean isNonNullOrEmpty(
    @Nullable String $receiver) {… }

    View Slide

  115. @PreusslerBerlin
    Standard functions
    val calendar =
    Calendar.getInstance(Locale.US).apply {
    set(Calendar.DAY_OF_MONTH, 3)
    set(Calendar.MONTH, Calendar.MARCH)
    set(Calendar.YEAR, 1990)
    }

    View Slide

  116. @PreusslerBerlin
    Standard functions

    View Slide

  117. @PreusslerBerlin
    inlining

    View Slide

  118. @PreusslerBerlin
    inline
    •Avoid runtime penalties of wrappers
    by inline”ing

    View Slide

  119. @PreusslerBerlin
    inline
    •Powerful with reified:
    Allows generics with type check: T::class
    inline fun Activity.start() {
    startActivity(Intent(this, T::class.java))
    }

    View Slide

  120. inline
    inline fun
    Activity.start() {
    startActivity(Intent(this, T::class.java))
    }
    start()
    $receiver$iv.startActivity(
    new Intent(
    (Context)$receiver$iv,
    MainActivity.class)
    );

    View Slide

  121. @PreusslerBerlin
    inline
    • Inline classes
    • Experimental
    inline class Time(private val long timeMs)

    View Slide

  122. @PreusslerBerlin
    inline
    • Inline classes
    • Experimental
    • Inline classes are final
    • Can lead to weird boxing issues
    • Not compatible with @Parcelize
    inline class Time(private val long timeMs)

    View Slide

  123. @PreusslerBerlin
    Some
    changes

    View Slide

  124. @PreusslerBerlin
    In/out
    https://twitter.com/fmuntenescu/status/982268265853476867

    View Slide

  125. @PreusslerBerlin
    Static?
    class Job {
    static String ERROR = null
    }

    View Slide

  126. @PreusslerBerlin
    Static?
    class Job {
    companion object {
    var ERROR: String = null
    }
    }

    View Slide

  127. @PreusslerBerlin
    Other changes
    • Classes/methods public by default

    View Slide

  128. @PreusslerBerlin
    Other changes
    • Classes/methods public by default
    • Classes/methods final by default (vs open)

    View Slide

  129. @PreusslerBerlin
    Other changes
    • Classes/methods public by default
    • Classes/methods final by default (vs open)
    • Inner class: static by default (vs inner)

    View Slide

  130. @PreusslerBerlin
    Other changes
    • Classes/methods public by default
    • Classes/methods final by default (vs open)
    • Inner class: static by default (vs inner)
    • Stricter usage of protected

    View Slide

  131. @PreusslerBerlin
    Other changes
    • Classes/methods public by default
    • Classes/methods final by default (vs open)
    • Inner class: static by default (vs inner)
    • Stricter usage of protected
    • New visibility: internal

    View Slide

  132. @PreusslerBerlin
    Other changes
    • Classes/methods public by default
    • Classes/methods final by default (vs open)
    • Inner class: static by default (vs inner)
    • Stricter usage of protected
    • New visibility: internal
    • One file can have multiple public classes

    View Slide

  133. @PreusslerBerlin
    Other changes
    • Classes/methods public by default
    • Classes/methods final by default (vs open)
    • Inner class: static by default (vs inner)
    • Stricter usage of protected
    • New visibility: internal
    • One file can have multiple public classes
    • „global“ functions & variables are allowed

    View Slide

  134. @PreusslerBerlin
    Other changes
    • Classes/methods public by default
    • Classes/methods final by default (vs open)
    • Inner class: static by default (vs inner)
    • Stricter usage of protected
    • New visibility: internal
    • One file can have multiple public classes
    • „global“ functions & variables are allowed
    • No checked Exceptions

    View Slide

  135. @PreusslerBerlin
    Other changes
    • void -> Unit
    • Object -> Any

    View Slide

  136. @PreusslerBerlin
    Other changes
    • void -> Unit
    • Object -> Any
    • Plus Nothing

    View Slide

  137. @PreusslerBerlin
    Bad news
    something ? 1 : 0
    something != null ? something : ""
    L

    View Slide

  138. @PreusslerBerlin
    Bad news
    if (something ) 1 else 0 L
    something ?: ""

    View Slide

  139. @PreusslerBerlin
    Java
    Interop

    View Slide

  140. @PreusslerBerlin
    Java Interop
    public final class FileKt {
    public static final void foobar() {..}
    }
    //File.kt
    fun foobar(){..}

    View Slide

  141. @PreusslerBerlin
    Java Interop
    • @JvmOverloads
    • @JvmStatic
    • @JvmField
    • @JvmName
    • @Throws

    View Slide

  142. @PreusslerBerlin
    Java Interop
    • Careful with „sneaky“ Kotlin exceptions
    • @Throws

    View Slide

  143. @PreusslerBerlin
    Java Interop
    @Metadata(
    mv = {1, 1, 13},
    bv = {1, 0, 3},
    k = 1,
    d1 =
    {"\u0000\u0014\n\u0002\u0018\u0002\n\u0002\u0010
    \u0000\n\u0002\b\u0002\n\u0002\u0010\u0002\n\u00
    02\b\u0003\u0018\u00002\u00020\u0001:\u0001\u000
    6B\u0005¢\u0006\u0002\u0010\u0002J\b\u0010\u0003
    \u001a\u00020\u0004H\u0007J\u0006\u0010\u0005\u0
    01a\u00020\u0004¨\u0006\u0007"},
    d2 =
    {"Lde/jodamob/android/kotlin/T_TestingTest;",
    "", "()V", "test", "", "throwSomething",
    "Something", "app"}
    )

    View Slide

  144. @PreusslerBerlin
    Java Interop
    • Performance in most case same as Java
    https://de.slideshare.net/intelliyole/kotlin-bytecode-generation-and-runtime-performance

    View Slide

  145. @PreusslerBerlin
    Compile time

    View Slide

  146. @PreusslerBerlin

    View Slide

  147. @PreusslerBerlin
    Sum up

    View Slide

  148. @PreusslerBerlin
    Kotlin
    Less code

    View Slide

  149. @PreusslerBerlin
    Less Code
    Kotlin .. helps to increase
    a cut in the lines of code
    by approximately 40 %
    (JetBrains)
    … tests show …
    the number of code lines
    reduces by 30…
    https://belitsoft.com/apps-development-services/java-vs-kotlin

    View Slide

  150. @PreusslerBerlin
    Kotlin
    Less code
    No more null

    View Slide

  151. @PreusslerBerlin
    Kotlin
    Less code
    Easy to learn
    No more null

    View Slide

  152. @PreusslerBerlin
    Kotlin
    No revolution

    View Slide

  153. @PreusslerBerlin
    Kotlin
    No revolution
    Just evolution

    View Slide

  154. @PreusslerBerlin
    Kotlin
    No revolution
    (pragmatic) evolution

    View Slide

  155. @PreusslerBerlin
    Kotlin
    ‘Kotlin isn't revolutionary
    (with the possible exception of its null-handling)
    but feels like a very careful amalgamation
    of some of the best features
    of other languages.
    Rob Fletcher, Netflix
    https://belitsoft.com/apps-development-services/java-vs-kotlin

    View Slide

  156. @PreusslerBerlin
    Kotlin is …
    „Scala for Dummies”
    https://towardsdatascience.com/introduction-to-kotlin-statistics-cdad3be88b5

    View Slide

  157. @PreusslerBerlin
    Makes developers happy
    fun fun fun

    View Slide

  158. @PreusslerBerlin
    Get started

    View Slide

  159. Java vs Kotlin
    @PreusslerBerlin
    Thanks

    View Slide