$30 off During Our Annual Pro Sale. View Details »

Kotlin: Uncovered

Kotlin: Uncovered

Kotlin does a lot for us in the way of reducing boilerplate. But what is it really doing? We will be inspecting some decompiled Kotlin to discover how it does its job. By looking underneath at how it handles data classes, lambdas, and delegation, we can better understand how the language executes what we write. If you’re curious about the language, or already using it in production, you should walk away from this investigation with a deeper understanding of Kotlin, and some tools for continued exploration.

- As given at Droidcon Boston '17 and Chicago Roboto '17

Victoria Gonda

April 05, 2017
Tweet

More Decks by Victoria Gonda

Other Decks in Programming

Transcript

  1. @TTGonda
    collectiveidea.com
    Kotlin: Uncovered
    Victoria Gonda
    www.victoriagonda.com
    @TTGonda

    View Slide

  2. @TTGonda
    collectiveidea.com
    Holland, MI
    Dancer
    Collective Idea

    View Slide

  3. @TTGonda
    collectiveidea.com
    I ❤
    Programming
    Languages

    View Slide

  4. @TTGonda
    collectiveidea.com
    DEFINE('BUBBLE(A,ALEN)I,J,UB,TMP') :
    (BUBBLE_END)
    BUBBLE I = 1; UB = ALEN
    OUTER GT(UB,1) :F(BDONE)
    J = 1
    INNER LE(A, A) :S(INCRJ)
    TMP = A
    A = A
    A = TMP
    INCRJ J = LT(J + 1,UB) J + 1 :S(INNER)
    UB = UB - 1 :(OUTER)
    BDONE BUBBLE = A :(RETURN)
    BUBBLE_END
    NUMBERS = '33 99 15 54 1 20 88 47 68 72'
    OUTPUT = "Unsorted List"
    OUTPUT = NUMBERS;
    NUMARRAY = ARRAY(10)
    FLOOP I = I + 1
    NUMBERS SPAN('0123456789') . NUMARRAY =
    :S(FLOOP)
    BUBBLE(NUMARRAY,10); NUMBERS = ''
    SLOOP J = J + 1;
    NUMBERS = NUMBERS NUMARRAY '
    ' :S(SLOOP)
    OUTPUT = TRIM(NUMBERS)
    END
    SNOBOL

    View Slide

  5. @TTGonda
    collectiveidea.com
    HAI 1.2
    CAN HAS STDIO?
    VISIBLE "IS KITTAH GAME!"
    VISIBLE "ENTER 'HELP' FOR CONTROLS"
    VISIBLE ""
    I HAS A NAME
    VISIBLE "WHAT IS KITTAH'S NAME?"
    GIMMEH NAME
    I HAS A ACTION
    VISIBLE SMOOSH "WAT U WANTING TO DO WITH " NAME "?" MKAY
    GIMMEH ACTION
    IM IN YR LOOP NERFIN YR PURRS TIL BOTH SAEM ACTION AN "KBYE"
    BOTH SAEM ACTION AN "HELP", O RLY?
    YA RLY
    VISIBLE "PET"
    VISIBLE "FEED"
    VISIBLE "IS HAPPY?"
    VISIBLE "KBYE"
    MEBBE BOTH SAEM ACTION AN "PURRS"
    VISIBLE SMOOSH "PURRS: " PURRS MKAY
    MEBBE BOTH SAEM ACTION AN "FEED"
    VISIBLE SMOOSH "YOU DID FEED " NAME ". " NAME " IS HAPPY WITH FOOD." MKAY
    PURRS R SUM OF PURRS AN 3
    LOLCODE

    View Slide

  6. @TTGonda
    collectiveidea.com

    View Slide

  7. @TTGonda
    collectiveidea.com
    “Statically typed programming language
    for the JVM, Android and the browser”

    View Slide

  8. @TTGonda
    collectiveidea.com
    Statically Typed

    View Slide

  9. @TTGonda
    collectiveidea.com
    Statically Typed
    final String name = "Victoria";
    val name = "Victoria"

    View Slide

  10. @TTGonda
    collectiveidea.com
    Null Safety

    View Slide

  11. @TTGonda
    collectiveidea.com
    Null Safety
    NullPointerException

    View Slide

  12. @TTGonda
    collectiveidea.com
    Concise

    View Slide

  13. @TTGonda
    collectiveidea.com
    map{$P=$P[$f^ord($p{$_})&6];$p{$_}=/ ^$P/ix?$P:close$_}
    Perl

    View Slide

  14. @TTGonda
    collectiveidea.com

    View Slide

  15. @TTGonda
    collectiveidea.com
    Java Virtual Machine

    View Slide

  16. @TTGonda
    collectiveidea.com
    Java Virtual Machine

    View Slide

  17. @TTGonda
    collectiveidea.com

    View Slide

  18. @TTGonda
    collectiveidea.com

    View Slide

  19. @TTGonda
    collectiveidea.com
    Data Classes
    Null Safety
    Delegation
    Class Extensions
    Lambdas

    View Slide

  20. @TTGonda
    collectiveidea.com
    Data Classes

    View Slide

  21. @TTGonda
    collectiveidea.com
    class User(
    val firstName: String,
    var lastName: String?
    )

    View Slide

  22. @TTGonda
    collectiveidea.com
    public final class User {
    @NotNull
    private final String firstName;
    @Nullable
    private String lastName;
    public User(@NotNull String firstName, @Nullable String lastName) {
    Intrinsics.checkParameterIsNotNull(firstName, "firstName");
    super();
    this.firstName = firstName;
    this.lastName = lastName;
    }
    @NotNull
    public final String getFirstName() {
    return this.firstName;
    }
    @Nullable
    public final String getLastName() {
    return this.lastName;
    }
    public final void setLastName(@Nullable String var1) {
    this.lastName = var1;
    }
    }

    View Slide

  23. @TTGonda
    collectiveidea.com
    public final class User {

    View Slide

  24. @TTGonda
    collectiveidea.com
    @NotNull
    private final String firstName;
    @Nullable
    private String lastName;
    public final class User {

    View Slide

  25. @TTGonda
    collectiveidea.com
    public User(@NotNull String firstName, @Nullable String lastName) {
    Intrinsics.checkParameterIsNotNull(firstName, "firstName");
    super();
    this.firstName = firstName;
    this.lastName = lastName;
    }
    public final class User {
    @NotNull
    private final String firstName;
    @Nullable
    private final String lastName;

    View Slide

  26. @TTGonda
    collectiveidea.com
    public User(@NotNull String firstName, @Nullable String lastName) {
    Intrinsics.checkParameterIsNotNull(firstName, "firstName");
    super();
    this.firstName = firstName;
    this.lastName = lastName;
    }
    public final class User {
    @NotNull
    private final String firstName;
    @Nullable
    private final String lastName;

    public static void checkParameterIsNotNull(
    Object value, String paramName) {
    if (value == null) {
    // prints error with stack trace
    throwParameterIsNullException(paramName);
    }
    }

    View Slide

  27. @TTGonda
    collectiveidea.com
    public User(@NotNull String firstName, @Nullable String lastName) {
    Intrinsics.checkParameterIsNotNull(firstName, "firstName");
    super();
    this.firstName = firstName;
    this.lastName = lastName;
    }
    public final class User {
    @NotNull
    private final String firstName;
    @Nullable
    private final String lastName;

    public static void checkParameterIsNotNull(
    Object value, String paramName) {
    if (value == null) {
    // prints error with stack trace
    throwParameterIsNullException(paramName);
    }
    }
    Caused by:
    java.lang.IllegalStateException: firstName must not be null
    at com.project.User.(User.kt:8)

    View Slide

  28. @TTGonda
    collectiveidea.com
    public User(@NotNull String firstName, @Nullable String lastName) {
    Intrinsics.checkParameterIsNotNull(firstName, "firstName");
    super();
    this.firstName = firstName;
    this.lastName = lastName;
    }
    public final class User {
    @NotNull
    private final String firstName;
    @Nullable
    private final String lastName;

    View Slide

  29. @TTGonda
    collectiveidea.com
    @NotNull
    public final String getFirstName() {
    return this.firstName;
    }
    @Nullable
    public final String getLastName() {
    return this.lastName;
    }
    public final void setLastName(@Nullable String var1) {
    this.lastName = var1;
    }
    }
    Intrinsics.checkParameterIsNotNull(lastName, "lastName");
    super();
    this.firstName = firstName;
    this.lastName = lastName;
    }

    View Slide

  30. @TTGonda
    collectiveidea.com
    data class User(
    val firstName: String,
    var lastName: String?
    )

    View Slide

  31. @TTGonda
    collectiveidea.com
    public final class User {
    @NotNull
    private final String firstName;
    @Nullable
    private String lastName;
    public User(@NotNull String firstName, @Nullable String lastName) {
    Intrinsics.checkParameterIsNotNull(firstName, "firstName");
    super();
    this.firstName = firstName;
    this.lastName = lastName;
    }
    @NotNull
    public final String getFirstName() {
    return this.firstName;
    }
    @Nullable
    public final String getLastName() {
    return this.lastName;
    }
    public final void setLastName(@Nullable String var1) {
    this.lastName = var1;
    }
    @NotNull
    public final String component1() {
    return this.firstName;
    }
    @Nullable
    public final String component2() {
    return this.lastName;
    }
    @NotNull
    public final User copy(@NotNull String firstName, @Nullable String lastName) {
    Intrinsics.checkParameterIsNotNull(firstName, "firstName");
    return new User(firstName, lastName);
    }
    // $FF: synthetic method
    // $FF: bridge method
    @NotNull
    public static User copy$default(User var0, String var1, String var2, int var3, Object var4) {
    if((var3 & 1) != 0) {
    var1 = var0.firstName;
    }
    if((var3 & 2) != 0) {
    var2 = var0.lastName;
    }
    return var0.copy(var1, var2);
    }
    public String toString() {
    return "User(firstName=" + this.firstName + ", lastName=" + this.lastName + ")";
    }
    public int hashCode() {
    return (this.firstName != null?this.firstName.hashCode():0) * 31 + (this.lastName != null?this.lastName.hashCode():0);
    }
    public boolean equals(Object var1) {
    if(this != var1) {
    if(var1 instanceof User) {
    User var2 = (User)var1;
    if(Intrinsics.areEqual(this.firstName, var2.firstName) && Intrinsics.areEqual(this.lastName, var2.lastName)) {
    return true;
    }
    }
    return false;
    } else {
    return true;
    }
    }
    }

    View Slide

  32. @TTGonda
    collectiveidea.com
    @NotNull
    public final String component1() {
    return this.firstName;
    }
    @Nullable
    public final String component2() {
    return this.lastName;
    }
    }
    public final void setLastName(@Nullable String
    this.lastName = var1;
    }

    View Slide

  33. @TTGonda
    collectiveidea.com
    @NotNull
    public final String component1() {
    return this.firstName;
    }
    @Nullable
    public final String component2() {
    return this.lastName;
    }
    }
    public final void setLastName(@Nullable String
    this.lastName = var1;
    }

    // Destructuring Data Class Declarations
    val user = User("Victoria", "Gonda")
    val (firstname, lastname) = user

    View Slide

  34. @TTGonda
    collectiveidea.com
    @NotNull
    public final String component1() {
    return this.firstName;
    }
    @Nullable
    public final String component2() {
    return this.lastName;
    }
    }
    public final void setLastName(@Nullable String
    this.lastName = var1;
    }

    View Slide

  35. @TTGonda
    collectiveidea.com
    @NotNull
    public final User copy(
    @NotNull String firstName, @Nullable String lastName) {
    Intrinsics
    .checkParameterIsNotNull(firstName, "firstName");
    return new User(firstName, lastName);
    }
    return this.firstName;
    }
    @Nullable
    public final String component2() {
    return this.lastName;
    }

    View Slide

  36. @TTGonda
    collectiveidea.com

    // $FF: synthetic method
    // $FF: bridge method
    @NotNull
    public static User copy$default(
    User var0, String var1, String var2, int var3, Object var4) {
    if((var3 & 1) != 0) {
    var1 = var0.firstName;
    }
    if((var3 & 2) != 0) {
    var2 = var0.lastName;
    }
    return var0.copy(var1, var2);
    }
    public final User copy(
    @NotNull String firstName, @Nullable String lastName) {
    Intrinsics
    .checkParameterIsNotNull(firstName, "firstName");
    return new User(firstName, lastName);
    }

    View Slide

  37. @TTGonda
    collectiveidea.com
    public String toString() {
    return "User(firstName=" + this.firstName +
    ", lastName=" + this.lastName + ")";
    }
    if((var3 & 1) != 0) {
    var1 = var0.firstName;
    }
    if((var3 & 2) != 0) {
    var2 = var0.lastName;
    }
    return var0.copy(var1, var2);
    }

    View Slide

  38. @TTGonda
    collectiveidea.com
    public int hashCode() {
    return (this.firstName != null?
    this.firstName.hashCode():0) * 31 +
    (this.lastName != null?
    this.lastName.hashCode():0);
    }
    public String toString() {
    return "User(firstName=" + this.firstName +
    ", lastName=" + this.lastName + ")";
    }

    View Slide

  39. @TTGonda
    collectiveidea.com
    public boolean equals(Object var1) {
    if(this != var1) {
    if(var1 instanceof User) {
    User var2 = (User)var1;
    if(Intrinsics.areEqual(this.firstName, var2.firstName) &&
    Intrinsics.areEqual(this.lastName, var2.lastName)) {
    return true;
    }
    }
    return false;
    } else {
    return true;
    }
    }
    }
    this.firstName.hashCode():0) * 31 +
    (this.lastName != null?
    this.lastName.hashCode():0);
    }

    View Slide

  40. @TTGonda
    collectiveidea.com
    public final class User {
    @NotNull
    private final String firstName;
    @Nullable
    private String lastName;
    public User(@NotNull String firstName, @Nullable String lastName) {
    Intrinsics.checkParameterIsNotNull(firstName, "firstName");
    super();
    this.firstName = firstName;
    this.lastName = lastName;
    }
    @NotNull
    public final String getFirstName() {
    return this.firstName;
    }
    @Nullable
    public final String getLastName() {
    return this.lastName;
    }
    public final void setLastName(@Nullable String ) {
    this.lastName = ;
    }
    @NotNull
    public final String component1() {
    return this.firstName;
    }
    @Nullable
    public final String component2() {
    return this.lastName;
    }
    @NotNull
    public final User copy(@NotNull String firstName, @Nullable String lastName) {
    Intrinsics.checkParameterIsNotNull(firstName, "firstName");
    return new User(firstName, lastName);
    }
    // $FF: synthetic method
    // $FF: bridge method
    @NotNull
    public static User copy$default(User var0, String var1, String var2, int var3, Object var4) {
    if((var3 & 1) != 0) {
    var1 = var0.firstName;
    }
    if((var3 & 2) != 0) {
    var2 = var0.lastName;
    }
    return var0.copy(var1, var2);
    }
    public String toString() {
    return "User(firstName=" + this.firstName + ", lastName=" + this.lastName + ")";
    }
    public int hashCode() {
    return (this.firstName != null?this.firstName.hashCode():0) * 31 + (this.lastName != null?this.lastName.hashCode():0);
    }
    public boolean equals(Object var1) {
    if(this != var1) {
    if(var1 instanceof User) {
    User var2 = (User)var1;
    if(Intrinsics.areEqual(this.firstName, var2.firstName) && Intrinsics.areEqual(this.lastName, var2.lastName)) {
    return true;
    }
    }
    return false;
    } else {
    return true;
    }
    }
    }

    View Slide

  41. @TTGonda
    collectiveidea.com
    data class User(
    val firstName: String = "Victoria",
    var lastName: String?
    )
    Default Values

    View Slide

  42. @TTGonda
    collectiveidea.com
    val user = User(

    lastName = "Gonda"
    )
    Named Parameters

    View Slide

  43. @TTGonda
    collectiveidea.com
    Null Safety

    View Slide

  44. @TTGonda
    collectiveidea.com
    // Wont compile

    var maybeString: String? = "Hello"

    maybeString.length

    View Slide

  45. @TTGonda
    collectiveidea.com
    Safe Call Operator
    val maybeString: String? = "Hello"
    maybeString?.length

    View Slide

  46. @TTGonda
    collectiveidea.com
    String maybeString = "Hello";
    maybeString.length();

    ? ? ?

    View Slide

  47. @TTGonda
    collectiveidea.com
    Safe Call Operator
    val maybeString: String? = null
    maybeString?.length

    View Slide

  48. @TTGonda
    collectiveidea.com
    String maybeString = (String) null;
    if(maybeString != null) {
    maybeString.length();
    }

    View Slide

  49. @TTGonda
    collectiveidea.com
    val maybeString: String? = null
    maybeString!!.length // NPE!

    View Slide

  50. @TTGonda
    collectiveidea.com
    String maybeString = (String) null;
    if(maybeString == null) {
    Intrinsics.throwNpe();
    }
    maybeString.length();

    View Slide

  51. @TTGonda
    collectiveidea.com
    val maybeString: String? = null
    maybeString?.let { string ->
    string.length
    }

    let

    View Slide

  52. @TTGonda
    collectiveidea.com
    String maybeString = (String) null;
    if(maybeString != null) {
    String string = (String)maybeString;
    string.length();
    }

    let

    View Slide

  53. @TTGonda
    collectiveidea.com
    val maybeString: String? = null

    return maybeString?.length ?: 0

    Elvis Operator ?:

    View Slide

  54. @TTGonda
    collectiveidea.com
    String maybeString = (String)null;

    if(maybeString != null) {

    return maybeString.length();

    } else {

    return 0;
    }

    Elvis Operator ?:

    View Slide

  55. @TTGonda
    collectiveidea.com
    Delegation

    View Slide

  56. @TTGonda
    collectiveidea.com
    class CopyPrinter(copier: Copy, printer: Print)
    : Copy by copier, Print by printer
    interface Copy {
    fun copy(page: Page): Page
    }
    interface Print {
    fun print(page: Page)
    }

    View Slide

  57. @TTGonda
    collectiveidea.com
    public final class CopyPrinter implements Copy, Print {
    // $FF: synthetic field
    private final Copy $$delegate_0;
    // $FF: synthetic field
    private final Print $$delegate_1;
    public CopyPrinter(@NotNull Copy copier, @NotNull Print printer) {
    Intrinsics.checkParameterIsNotNull(copier, "copier");
    Intrinsics.checkParameterIsNotNull(printer, "printer");
    super();
    this.$$delegate_0 = copier;
    this.$$delegate_1 = printer;
    }
    @NotNull
    public Page copy(@NotNull Page page) {
    Intrinsics.checkParameterIsNotNull(page, "page");
    return this.$$delegate_0.copy(page);
    }
    public void print(@NotNull Page page) {
    Intrinsics.checkParameterIsNotNull(page, "page");
    this.$$delegate_1.print(page);
    }
    }
    public interface Copy {
    @NotNull
    Page copy(@NotNull Page var1);
    }
    public interface Print {
    void print(@NotNull Page var1);
    }

    View Slide

  58. @TTGonda
    collectiveidea.com
    public final class CopyPrinter
    implements Copy, Print {

    View Slide

  59. @TTGonda
    collectiveidea.com
    // $FF: synthetic field
    private final Copy $$delegate_0;
    // $FF: synthetic field
    private final Print $$delegate_1;
    public final class CopyPrinter
    implements Copy, Print {

    View Slide

  60. @TTGonda
    collectiveidea.com
    public CopyPrinter(
    @NotNull Copy copier,
    @NotNull Print printer) {
    Intrinsics
    .checkParameterIsNotNull(copier, "copier");
    Intrinsics
    .checkParameterIsNotNull(printer, "printer");
    super();
    this.$$delegate_0 = copier;
    this.$$delegate_1 = printer;
    }
    // $FF: synthetic field
    private final Copy $$delegate_0;
    // $FF: synthetic field
    private final Print $$delegate_1;

    View Slide

  61. @TTGonda
    collectiveidea.com
    @NotNull
    public Page copy(@NotNull Page page) {
    Intrinsics
    .checkParameterIsNotNull(page, "page");
    return this.$$delegate_0.copy(page);
    }
    public void print(@NotNull Page page) {
    Intrinsics
    .checkParameterIsNotNull(page, "page");
    this.$$delegate_1.print(page);
    }
    }
    super();
    this.$$delegate_0 = copier;
    this.$$delegate_1 = printer;
    }

    View Slide

  62. @TTGonda
    collectiveidea.com
    public interface Copy {
    @NotNull
    Page copy(@NotNull Page var1);
    }
    public interface Print {
    void print(@NotNull Page var1);
    }
    public void print(@NotNull Page page) {
    Intrinsics
    .checkParameterIsNotNull(page, "page");
    this.$$delegate_1.print(page);
    }
    }

    View Slide

  63. @TTGonda
    collectiveidea.com
    public final class CopyPrinter implements Copy, Print {
    // $FF: synthetic field
    private final Copy $$delegate_0;
    // $FF: synthetic field
    private final Print $$delegate_1;
    public CopyPrinter(@NotNull Copy copier, @NotNull Print printer) {
    Intrinsics.checkParameterIsNotNull(copier, "copier");
    Intrinsics.checkParameterIsNotNull(printer, "printer");
    super();
    this.$$delegate_0 = copier;
    this.$$delegate_1 = printer;
    }
    @NotNull
    public Page copy(@NotNull Page page) {
    Intrinsics.checkParameterIsNotNull(page, "page");
    return this.$$delegate_0.copy(page);
    }
    public void print(@NotNull Page page) {
    Intrinsics.checkParameterIsNotNull(page, "page");
    this.$$delegate_1.print(page);
    }
    }
    public interface Copy {
    @NotNull
    Page copy(@NotNull Page var1);
    }
    public interface Print {
    void print(@NotNull Page var1);
    }

    View Slide

  64. @TTGonda
    collectiveidea.com
    Class Extensions

    View Slide

  65. @TTGonda
    collectiveidea.com
    Class Extensions
    TextUtils.isEmpty("hello");

    View Slide

  66. @TTGonda
    collectiveidea.com
    // StringExt.kt
    fun String.double(): String {
    return this + this
    }

    View Slide

  67. @TTGonda
    collectiveidea.com
    "hello".double()
    // -> “hellohello”
    // StringExt.kt
    fun String.double(): String {
    return this + this
    }

    View Slide

  68. @TTGonda
    collectiveidea.com
    public final class StringExtKt {
    @NotNull
    public static final String double(
    @NotNull String $receiver) {
    Intrinsics
    .checkParameterIsNotNull($receiver, "$receiver");
    return $receiver + $receiver;
    }
    }

    View Slide

  69. @TTGonda
    collectiveidea.com
    StringExtKt.double("hello");
    // -> "hellohello"
    public final class StringExtKt {
    @NotNull
    public static final String double(
    @NotNull String $receiver) {
    Intrinsics
    .checkParameterIsNotNull($receiver, "$r
    return $receiver + $receiver;
    }
    }

    View Slide

  70. @TTGonda
    collectiveidea.com
    Lambdas

    View Slide

  71. @TTGonda
    collectiveidea.com
    fun firstNSquares(n: Int): Array
    = Array(n, { i -> i * i })
    // firstNSquares(3)
    // -> [0, 1, 4]

    View Slide

  72. @TTGonda
    collectiveidea.com
    @NotNull
    public static final Integer[] firstNSquares(int n) {
    Integer[] result$iv = new Integer[n];
    int i$iv = 0;
    int var3 = n - 1;
    if(i$iv <= var3) {
    while(true) {
    Integer var9 = Integer.valueOf(i$iv * i$iv);
    result$iv[i$iv] = var9;
    if(i$iv == var3) {
    break;
    }
    ++i$iv;
    }
    }
    return (Integer[])((Object[])result$iv);
    }

    View Slide

  73. @TTGonda
    collectiveidea.com
    @NotNull
    public static Integer[] firstNSquares(int n) {
    Integer[] resultArray = new Integer[n];
    int i = 0;
    int max = n - 1;
    if(i <= max) {
    while(true) {
    Integer square = i * i;
    resultArray[i] = square;
    if(i == max) {
    break;
    }
    ++i;
    }
    }
    return resultArray;
    }

    View Slide

  74. @TTGonda
    collectiveidea.com
    fun firstNSquares(n: Int): Array
    = Array(n, { i -> square(i + 1) })
    // firstNSquares(3)
    // -> [1, 4, 9]

    View Slide

  75. @TTGonda
    collectiveidea.com
    @NotNull
    public static Integer[] firstNSquares(int n) {
    Integer[] resultArray = new Integer[n];
    int i = 0;
    int max = n - 1;
    if(i <= max) {
    while(true) {
    Integer square = square(i+1);
    resultArray[i] = square;
    if(i == max) {
    break;
    }
    ++i;
    }
    }
    return resultArray;
    }

    View Slide

  76. @TTGonda
    collectiveidea.com
    inline fun beforeAndAfter(
    startString: String,
    function: (string: String) -> String) {
    print("Before: $startString")
    val after = function(startString)
    print("After: $after")
    }

    View Slide

  77. @TTGonda
    collectiveidea.com
    inline fun beforeAndAfter(
    startString: String,
    function: (string: String) -> String) {
    print("Before: $startString")
    val after = function(startString)
    print("After: $after")
    }

    public inline fun T.let(block: (T) -> R): R
    = block(this)

    View Slide

  78. @TTGonda
    collectiveidea.com
    inline fun beforeAndAfter(
    startString: String,
    function: (string: String) -> String) {
    print("Before: $startString")
    val after = function(startString)
    print("After: $after")
    }

    View Slide

  79. @TTGonda
    collectiveidea.com
    public final void beforeAndAfter(
    @NotNull String startString,
    @NotNull Function1 function) {
    Intrinsics
    .checkParameterIsNotNull(startString, "startString");
    Intrinsics
    .checkParameterIsNotNull(function, "function");
    String after = "Before: " + startString;
    System.out.print(after);
    after = (String)function.invoke(startString);
    String var4 = "After: " + after;
    System.out.print(var4);
    }

    View Slide

  80. @TTGonda
    collectiveidea.com
    public final void beforeAndAfter(
    @NotNull String startString,
    @NotNull Function1 function) {
    Intrinsics
    .checkParameterIsNotNull(startString, "startString");
    Intrinsics
    .checkParameterIsNotNull(function, "function");
    String after = "Before: " + startString;
    System.out.print(after);
    after = (String)function.invoke(startString);
    String var4 = "After: " + after;
    System.out.print(var4);
    }
    public interface Function1 : Function {
    public operator fun invoke(p1: P1): R
    }

    View Slide

  81. @TTGonda
    collectiveidea.com
    public final void beforeAndAfter(
    @NotNull String startString,
    @NotNull Function1 function) {
    Intrinsics
    .checkParameterIsNotNull(startString, "startString");
    Intrinsics
    .checkParameterIsNotNull(function, "function");
    String after = "Before: " + startString;
    System.out.print(after);
    after = (String)function.invoke(startString);
    String var4 = "After: " + after;
    System.out.print(var4);
    }

    View Slide

  82. @TTGonda
    collectiveidea.com
    fun example() {
    beforeAndAfter("hello", { string -> string + " world" })
    }
    // Output
    “Before: hello"
    “After: hello world"

    View Slide

  83. @TTGonda
    collectiveidea.com
    public final void example() {
    String startString$iv = "hello";
    String after$iv = "Before: " + startString$iv;
    System.out.print(after$iv);
    String string = (String)startString$iv;
    after$iv = (String)(string + " world");
    string = "After: " + after$iv;
    System.out.print(string);
    }

    View Slide

  84. @TTGonda
    collectiveidea.com
    beforeAndAfter("hello", { string -> string + " world" })

    beforeAndAfter("hello", { it + " world" })

    beforeAndAfter("hello") { it + " world" }

    Lambda Parameters

    View Slide

  85. @TTGonda
    collectiveidea.com
    fun beforeAndAfter(
    startString: String,
    function: (string: String) -> String
    ) {
    print("Before: $startString")
    val after = function(startString)
    print("After: $after")
    }

    View Slide

  86. @TTGonda
    collectiveidea.com
    public final void example() {
    this.beforeAndAfter("hello", (Function1)null.INSTANCE);
    }
    // Output
    “Before: hello”
    “After: hello world”

    View Slide

  87. @TTGonda
    collectiveidea.com

    View Slide

  88. @TTGonda
    collectiveidea.com
    // Pseudocode for bytecode
    final class BytecodeClass
    extends Lambda
    implements Function1 {
    public void invoke(String string) {
    StringBuilder sb = new StringBuilder("hello");
    sb.append(" world");
    returnValue = sb.toString();
    }
    static Function1 INSTANCE = new BytecodeClass();
    }

    View Slide

  89. @TTGonda
    collectiveidea.com
    // Pseudocode for bytecode
    final class BytecodeClass
    extends Lambda
    implements Function1 {
    public void invoke(String string) {
    StringBuilder sb = new StringBuilder("hello");
    sb.append(" world");
    returnValue = sb.toString();
    }
    static Function1 INSTANCE = new BytecodeClass();
    }
    public final void example() {
    this.beforeAndAfter("hello", (Function1)null.INSTANCE);
    }

    View Slide

  90. @TTGonda
    collectiveidea.com
    // Pseudocode for bytecode
    final class BytecodeClass
    extends Lambda
    implements Function1 {
    public void invoke(String string) {
    StringBuilder sb = new StringBuilder("hello");
    sb.append(" world");
    returnValue = sb.toString();
    }
    static Function1 INSTANCE = new BytecodeClass();
    }

    View Slide

  91. @TTGonda
    collectiveidea.com
    Companion Objects
    Smart Casting
    Collection Functions
    Control Flow Structures
    Operator Overloading
    Named Parameters

    View Slide

  92. @TTGonda
    collectiveidea.com
    Menu > Tools > Kotlin > Show Kotlin Bytecode
    or
    CMD+SHFT+A and search “Show Kotlin Bytecode”

    View Slide

  93. @TTGonda
    collectiveidea.com
    Code > Convert Java File to Kotlin File
    or
    CMD+SHFT+A and search “Convert Java File to Kotlin File”

    View Slide

  94. @TTGonda
    collectiveidea.com
    DETOUR
    JAVA

    View Slide

  95. @TTGonda
    collectiveidea.com
    Thanks!
    Victoria Gonda
    www.victoriagonda.com
    @TTGonda

    View Slide