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

There's No Magic - How Kotlin can be your best ...

Aaron He
November 04, 2017

There's No Magic - How Kotlin can be your best friends @DevFest LA 2017

Kotlin finally got official support from Google. While a lot of people are cheering, some are hesitating. Should I use it in production? What are all those fancy features? How is Kotlin able to do that? In this talk, I'll share my experience with Kotlin and go a little bit in detail on what Kotlin is doing under the hood.

Aaron He

November 04, 2017
Tweet

More Decks by Aaron He

Other Decks in Technology

Transcript

  1. Kotlin@Tinder • First APK shipped with Kotlin in June •

    Our app has ~32% Kotlin adoption • Developers are happy
  2. inline functions property reified higher-order functions immutable collections extension functions

    companion object Any object object no NPEs delegation data class sealed class in and out coroutines internal visibility type aliases Java interop by lazy lateinit
  3. class Location(var street: String?, var city: String?) class Conference(var name:

    String?, var location: Location?) fun printCity(conference: Conference?) { println(conference?.location?.city) }
  4. // access flags 0x2 private Ljava/lang/String; name @Lorg/jetbrains/annotations/Nullable;() // invisible

    // access flags 0x11 public final getName()Ljava/lang/String; @Lorg/jetbrains/annotations/Nullable;() // invisible L0 LINENUMBER 4 L0 ALOAD 0 GETFIELD org/aaronhe/Conference.name : Ljava/lang/String; ARETURN L1 LOCALVARIABLE this Lorg/aaronhe/Conference; L0 L1 0 MAXSTACK = 1 MAXLOCALS = 1 // access flags 0x11 public final setName(Ljava/lang/String;)V @Lorg/jetbrains/annotations/Nullable;() // invisible, parameter 0 L0 LINENUMBER 4 L0 ALOAD 0 ALOAD 1 PUTFIELD org/aaronhe/Conference.name : Ljava/lang/String; RETURN L1 LOCALVARIABLE this Lorg/aaronhe/Conference; L0 L1 0 LOCALVARIABLE <set-?> Ljava/lang/String; L0 L1 1 MAXSTACK = 2 MAXLOCALS = 2 // access flags 0x2 private Lorg/aaronhe/Location; location @Lorg/jetbrains/annotations/Nullable;() // invisible // access flags 0x11 public final getLocation()Lorg/aaronhe/Location; @Lorg/jetbrains/annotations/Nullable;() // invisible L0 LINENUMBER 4 L0 ALOAD 0 GETFIELD org/aaronhe/Conference.location : Lorg/aaronhe/Location; ARETURN L1 LOCALVARIABLE this Lorg/aaronhe/Conference; L0 L1 0 MAXSTACK = 1 MAXLOCALS = 1 // access flags 0x11 public final setLocation(Lorg/aaronhe/Location;)V @Lorg/jetbrains/annotations/Nullable;() // invisible, parameter 0 L0 LINENUMBER 4 L0 ALOAD 0 EXACTLY!
  5. // DevFest.java package org.aaronhe; import kotlin.Metadata; import org.jetbrains.annotations.Nullable; @Metadata( mv

    = {1, 1, 7}, bv = {1, 0, 2}, k = 1, d1 = {"\u0000\u0018\n\u0002\u0018\u0002\n\u0002\u0010\u0000\n\u0002\b\u0002\n\u0002\u0010\u0002\n\u0000\n\u0002\u0018\u0002\n\u0000\u0018\u0000 2\u00020\u0001B\u0005¢ \u0006\u0002\u0010\u0002J\u0010\u0010\u0003\u001a\u00020\u00042\b\u0010\u0005\u001a\u0004\u0018\u00010\u0006¨\u0006\u0007"}, d2 = {"Lorg/aaronhe/DevFest;", "", "()V", "printCity", "", "conference", "Lorg/aaronhe/Conference;", "production sources for module moshi-kotlin"} ) public final class DevFest { public final void printCity(@Nullable Conference conference) { String var3; label12: { if (conference != null) { Location var10000 = conference.getLocation(); if (var10000 != null) { var3 = var10000.getCity(); break label12; } } var3 = null; } String var2 = var3; System.out.println(var2); } }
  6. // DevFest.java package org.aaronhe; import kotlin.Metadata; import org.jetbrains.annotations.Nullable; @Metadata( mv

    = {1, 1, 7}, bv = {1, 0, 2}, k = 1, d1 = {"\u0000\u0018\n\u0002\u0018\u0002\n\u0002\u0010\u0000\n\u0002\b\u0002\n\u0002\u0010\u0002\n\u0000\n\u0002\u0018\u0002\n\u0000\u0018\u0000 2\u00020\u0001B\u0005¢ \u0006\u0002\u0010\u0002J\u0010\u0010\u0003\u001a\u00020\u00042\b\u0010\u0005\u001a\u0004\u0018\u00010\u0006¨\u0006\u0007"}, d2 = {"Lorg/aaronhe/DevFest;", "", "()V", "printCity", "", "conference", "Lorg/aaronhe/Conference;", "production sources for module moshi-kotlin"} ) public final class DevFest { public final void printCity(@Nullable Conference conference) { String var3; label12: { if (conference != null) { Location var10000 = conference.getLocation(); if (var10000 != null) { var3 = var10000.getCity(); break label12; } } var3 = null; } String var2 = var3; System.out.println(var2); } }
  7. // DevFest.java package org.aaronhe; import kotlin.Metadata; import org.jetbrains.annotations.Nullable; @Metadata( mv

    = {1, 1, 7}, bv = {1, 0, 2}, k = 1, d1 = {"\u0000\u0018\n\u0002\u0018\u0002\n\u0002\u0010\u0000\n\u0002\b\u0002\n\u0002\u0010\u0002\n\u0000\n\u0002\u0018\u0002\n\u0000\u0018\u0000 2\u00020\u0001B\u0005¢ \u0006\u0002\u0010\u0002J\u0010\u0010\u0003\u001a\u00020\u00042\b\u0010\u0005\u001a\u0004\u0018\u00010\u0006¨\u0006\u0007"}, d2 = {"Lorg/aaronhe/DevFest;", "", "()V", "printCity", "", "conference", "Lorg/aaronhe/Conference;", "production sources for module moshi-kotlin"} ) public final class DevFest { public final void printCity(@Nullable Conference conference) { String var3; label12: { if (conference != null) { Location var10000 = conference.getLocation(); if (var10000 != null) { var3 = var10000.getCity(); break label12; } } var3 = null; } String var2 = var3; System.out.println(var2); } }
  8. // DevFest.java package org.aaronhe; import kotlin.Metadata; import org.jetbrains.annotations.Nullable; @Metadata( mv

    = {1, 1, 7}, bv = {1, 0, 2}, k = 1, d1 = {"\u0000\u0018\n\u0002\u0018\u0002\n\u0002\u0010\u0000\n\u0002\b\u0002\n\u0002\u0010\u0002\n\u0000\n\u0002\u0018\u0002\n\u0000\u0018\u0000 2\u00020\u0001B\u0005¢ \u0006\u0002\u0010\u0002J\u0010\u0010\u0003\u001a\u00020\u00042\b\u0010\u0005\u001a\u0004\u0018\u00010\u0006¨\u0006\u0007"}, d2 = {"Lorg/aaronhe/DevFest;", "", "()V", "printCity", "", "conference", "Lorg/aaronhe/Conference;", "production sources for module moshi-kotlin"} ) public final class DevFest { public final void printCity(@Nullable Conference conference) { String var3; label12: { if (conference != null) { Location var10000 = conference.getLocation(); if (var10000 != null) { var3 = var10000.getCity(); break label12; } } var3 = null; } String var2 = var3; System.out.println(var2); } }
  9. // DevFest.java package org.aaronhe; import kotlin.Metadata; import org.jetbrains.annotations.Nullable; @Metadata( mv

    = {1, 1, 7}, bv = {1, 0, 2}, k = 1, d1 = {"\u0000\u0018\n\u0002\u0018\u0002\n\u0002\u0010\u0000\n\u0002\b\u0002\n\u0002\u0010\u0002\n\u0000\n\u0002\u0018\u0002\n\u0000\u0018\u0000 2\u00020\u0001B\u0005¢ \u0006\u0002\u0010\u0002J\u0010\u0010\u0003\u001a\u00020\u00042\b\u0010\u0005\u001a\u0004\u0018\u00010\u0006¨\u0006\u0007"}, d2 = {"Lorg/aaronhe/DevFest;", "", "()V", "printCity", "", "conference", "Lorg/aaronhe/Conference;", "production sources for module moshi-kotlin"} ) public final class DevFest { public final void printCity(@Nullable Conference conference) { String var3; label12: { if (conference != null) { Location var10000 = conference.getLocation(); if (var10000 != null) { var3 = var10000.getCity(); break label12; } } var3 = null; } String var2 = var3; System.out.println(var2); } }
  10. // DevFest.java package org.aaronhe; import kotlin.Metadata; import org.jetbrains.annotations.Nullable; @Metadata( mv

    = {1, 1, 7}, bv = {1, 0, 2}, k = 1, d1 = {"\u0000\u0018\n\u0002\u0018\u0002\n\u0002\u0010\u0000\n\u0002\b\u0002\n\u0002\u0010\u0002\n\u0000\n\u0002\u0018\u0002\n\u0000\u0018\u0000 2\u00020\u0001B\u0005¢ \u0006\u0002\u0010\u0002J\u0010\u0010\u0003\u001a\u00020\u00042\b\u0010\u0005\u001a\u0004\u0018\u00010\u0006¨\u0006\u0007"}, d2 = {"Lorg/aaronhe/DevFest;", "", "()V", "printCity", "", "conference", "Lorg/aaronhe/Conference;", "production sources for module moshi-kotlin"} ) public final class DevFest { public final void printCity(@Nullable Conference conference) { String var3; label12: { if (conference != null) { Location var10000 = conference.getLocation(); if (var10000 != null) { var3 = var10000.getCity(); break label12; } } var3 = null; } String var2 = var3; System.out.println(var2); } }
  11. // DevFest.java package org.aaronhe; import kotlin.Metadata; import org.jetbrains.annotations.Nullable; @Metadata( mv

    = {1, 1, 7}, bv = {1, 0, 2}, k = 1, d1 = {"\u0000\u0018\n\u0002\u0018\u0002\n\u0002\u0010\u0000\n\u0002\b\u0002\n\u0002\u0010\u0002\n\u0000\n\u0002\u0018\u0002\n\u0000\u0018\u0000 2\u00020\u0001B\u0005¢ \u0006\u0002\u0010\u0002J\u0010\u0010\u0003\u001a\u00020\u00042\b\u0010\u0005\u001a\u0004\u0018\u00010\u0006¨\u0006\u0007"}, d2 = {"Lorg/aaronhe/DevFest;", "", "()V", "printCity", "", "conference", "Lorg/aaronhe/Conference;", "production sources for module moshi-kotlin"} ) public final class DevFest { public final void printCity(@Nullable Conference conference) { String var3; label12: { if (conference != null) { Location var10000 = conference.getLocation(); if (var10000 != null) { var3 = var10000.getCity(); break label12; } } var3 = null; } String var2 = var3; System.out.println(var2); } }
  12. // DevFest.java package org.aaronhe; import kotlin.Metadata; import org.jetbrains.annotations.Nullable; @Metadata( mv

    = {1, 1, 7}, bv = {1, 0, 2}, k = 1, d1 = {"\u0000\u0018\n\u0002\u0018\u0002\n\u0002\u0010\u0000\n\u0002\b\u0002\n\u0002\u0010\u0002\n\u0000\n\u0002\u0018\u0002\n\u0000\u0018\u0000 2\u00020\u0001B\u0005¢ \u0006\u0002\u0010\u0002J\u0010\u0010\u0003\u001a\u00020\u00042\b\u0010\u0005\u001a\u0004\u0018\u00010\u0006¨\u0006\u0007"}, d2 = {"Lorg/aaronhe/DevFest;", "", "()V", "printCity", "", "conference", "Lorg/aaronhe/Conference;", "production sources for module moshi-kotlin"} ) public final class DevFest { public final void printCity(@Nullable Conference conference) { String var3; label12: { if (conference != null) { Location var10000 = conference.getLocation(); if (var10000 != null) { var3 = var10000.getCity(); break label12; } } var3 = null; } String var2 = var3; System.out.println(var2); } }
  13. public final class ConferenceExtKt { public static final boolean isInLA(@NotNull

    Conference $receiver) { Intrinsics.checkParameterIsNotNull($receiver, "$receiver"); Location var10000 = $receiver.getLocation(); return Intrinsics.areEqual(var10000 != null ? var10000.getCity() : null, "Los Angeles"); } }
  14. public final class ConferenceExtKt { public static final boolean isInLA(@NotNull

    Conference $receiver) { Intrinsics.checkParameterIsNotNull($receiver, "$receiver"); Location var10000 = $receiver.getLocation(); return Intrinsics.areEqual(var10000 != null ? var10000.getCity() : null, "Los Angeles"); } }
  15. public final class ConferenceExtKt { public static final boolean isInLA(@NotNull

    Conference $receiver) { Intrinsics.checkParameterIsNotNull($receiver, "$receiver"); Location var10000 = $receiver.getLocation(); return Intrinsics.areEqual(var10000 != null ? var10000.getCity() : null, "Los Angeles"); } }
  16. public final class ConferenceExtKt { public static final boolean isInLA(@NotNull

    Conference $receiver) { Intrinsics.checkParameterIsNotNull($receiver, "$receiver"); Location var10000 = $receiver.getLocation(); return Intrinsics.areEqual(var10000 != null ? var10000.getCity() : null, "Los Angeles"); } }
  17. public final class ConferenceExtKt { public static final boolean isInLA(@NotNull

    Conference $receiver) { Intrinsics.checkParameterIsNotNull($receiver, "$receiver"); Location var10000 = $receiver.getLocation(); return Intrinsics.areEqual(var10000 != null ? var10000.getCity() : null, "Los Angeles"); } }
  18. public final class ConferenceExtKt { public static final boolean isInLA(@NotNull

    Conference $receiver) { Intrinsics.checkParameterIsNotNull($receiver, "$receiver"); Location var10000 = $receiver.getLocation(); return Intrinsics.areEqual(var10000 != null ? var10000.getCity() : null, "Los Angeles"); } }
  19. // What is this Java thing? public boolean checkIfInLA(@NotNull Conference

    conference) { return ConferenceExtKt.isInLA(conference); }
  20. Kotlin standard library public char lastCharacter(@NotNull String string) { return

    StringsKt.last(string); } public <T, R> List<R> map(@NotNull List<T> list, Function1<T, R> mapper) { return CollectionsKt.map(list, mapper); }
  21. public int hashCode() { return (this.name != null ? this.name.hashCode()

    : 0) * 31 + (this.location != null ? this.location.hashCode() : 0); } public boolean equals(Object var1) { if (this != var1) { if (var1 instanceof Conference) { Conference var2 = (Conference)var1; if (Intrinsics.areEqual(this.name, var2.name) && Intrinsics.areEqual(this.location, var2.location)) { return true; } } return false; } else { return true; } }
  22. public int hashCode() { return (this.name != null ? this.name.hashCode()

    : 0) * 31 + (this.location != null ? this.location.hashCode() : 0); } public boolean equals(Object var1) { if (this != var1) { if (var1 instanceof Conference) { Conference var2 = (Conference)var1; if (Intrinsics.areEqual(this.name, var2.name) && Intrinsics.areEqual(this.location, var2.location)) { return true; } } return false; } else { return true; } }
  23. public int hashCode() { return (this.name != null ? this.name.hashCode()

    : 0) * 31 + (this.location != null ? this.location.hashCode() : 0); } public boolean equals(Object var1) { if (this != var1) { if (var1 instanceof Conference) { Conference var2 = (Conference)var1; if (Intrinsics.areEqual(this.name, var2.name) && Intrinsics.areEqual(this.location, var2.location)) { return true; } } return false; } else { return true; } }
  24. @Nullable public final String getName() { return this.name; } public

    final void setName(@Nullable String var1) { this.name = var1; } @Nullable public final Location getLocation() { return this.location; } public final void setLocation(@Nullable Location var1) { this.location = var1; }
  25. @NotNull private final String name; @NotNull private final Location location;

    @NotNull public final String getName() { return this.name; } @NotNull public final Location getLocation() { return this.location; }
  26. @NotNull private final String name; @NotNull private final Location location;

    @NotNull public final String getName() { return this.name; } @NotNull public final Location getLocation() { return this.location; }
  27. @NotNull private final String name; @NotNull private final Location location;

    @NotNull public final String getName() { return this.name; } @NotNull public final Location getLocation() { return this.location; }