Victoria Gonda
July 09, 2017
2.5k

# Kotlin: Uncovered - 360|AnDev 2017

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.

July 09, 2017

## Transcript

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

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

3. @TTGonda
collectiveidea.com
I ❤
Programming
Languages

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

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

6. @TTGonda
collectiveidea.com

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

8. @TTGonda
collectiveidea.com
Statically Typed

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

10. @TTGonda
collectiveidea.com
Null Safety

11. @TTGonda
collectiveidea.com
Null Safety
NullPointerException

12. @TTGonda
collectiveidea.com
Concise

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

14. @TTGonda
collectiveidea.com

15. @TTGonda
collectiveidea.com

16. @TTGonda
collectiveidea.com
Java Virtual Machine

17. @TTGonda
collectiveidea.com
Java Virtual Machine

18. @TTGonda
collectiveidea.com
Java Virtual Machine
*.class

19. @TTGonda
collectiveidea.com

20. @TTGonda
collectiveidea.com

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

22. @TTGonda
collectiveidea.com
Classes

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

Classes

24. @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;
}
}

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

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

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;

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;

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

29. @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)

30. @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;

31. @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;
}

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

Data Classes

33. @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;
}
}
}

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;
}

35. @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

36. @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;
}

37. @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;
}

38. @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);
}

39. @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);
}
val user1 = user.copy()
val user2 = user.copy(firstName = "Tori")
val user3 = user.copy(lastName = null)
val user4 = user.copy(firstName = "Josh", lastName = "Kovach")

40. @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);
}

41. @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);
}

42. @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 + ")";
}

43. @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);
}

44. @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;
}
}
}

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

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

// \$FF: synthetic method
public DataUser(String var1, String var2, int var3,
DefaultConstructorMarker var4) {
if((var3 & 1) != 0) {
var1 = "Victoria";
}
this(var1, var2);
}

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

48. @TTGonda
collectiveidea.com
val user = User(
lastName = "Gonda"
)
Named Parameters

49. @TTGonda
collectiveidea.com
Null Safety

50. @TTGonda
collectiveidea.com
// Wont compile
var maybeString: String? = "Hello"
maybeString.length

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

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

? ? ?

53. @TTGonda
collectiveidea.com
Safe Call Operator
val maybeString: String? = getString()
maybeString?.length

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

55. @TTGonda
collectiveidea.com
val maybeString: String? = getString()
maybeString!!.length

!! Operator

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

57. @TTGonda
collectiveidea.com
val maybeString: String? = getString()
return maybeString?.let {
// it == maybeString
it.length
}

Null Safe Scoping

58. @TTGonda
collectiveidea.com
String maybeString = this.getString();
return maybeString != null ?
Integer.valueOf(maybeString.length()) : null;

Null Safe Scoping

59. @TTGonda
collectiveidea.com
val maybeString: String? = getString()
return maybeString?.length ?: 0

Elvis Operator ?:

60. @TTGonda
collectiveidea.com
String maybeString = this.getString();
return maybeString != null ?
maybeString.length() : 0;

Elvis Operator ?:

61. @TTGonda
collectiveidea.com
Delegation

62. @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)
}

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);
}

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

65. @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 {

66. @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;
}
implements Copy, Print {
// \$FF: synthetic field
private final Copy \$\$delegate_0;
// \$FF: synthetic field
private final Print \$\$delegate_1;

67. @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);
}
}
Intrinsics.checkParameterIsNotNull(printer, "print
super();
this.\$\$delegate_0 = copier;
this.\$\$delegate_1 = printer;
}

68. @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);
}
}

69. @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);
}

70. @TTGonda
collectiveidea.com
Extension Functions

71. @TTGonda
collectiveidea.com
TextUtils.isEmpty("hello");
Extension Functions

72. @TTGonda
collectiveidea.com
// StringExt.kt
fun String?.isEmpty(): Boolean {
return this == null || this.length == 0
}

73. @TTGonda
collectiveidea.com
"".isEmpty() // true
// StringExt.kt
fun String?.isEmpty(): Boolean {
return this == null || this.length
}

74. @TTGonda
collectiveidea.com
public final class StringExtKt {
public static final boolean isEmpty(
}
}

75. @TTGonda
collectiveidea.com
StringExtKt.isEmpty(""); // true

public final class StringExtKt {
public static final boolean isEmpty(
}
}

76. @TTGonda
collectiveidea.com
Lambdas

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

78. @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);
}

79. @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;
}

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

81. @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;
}

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

83. @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)

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

85. @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);
}

86. @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
}

87. @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);
}

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

89. @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);
}

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

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

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

Lambda Parameters

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

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

93. @TTGonda
collectiveidea.com

94. @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();
}

95. @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);
}

96. @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);
}
// access flags 0x19
public final static ../../../Lambda\$example\$1; INSTANCE

97. @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();
}

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

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

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

101. @TTGonda
collectiveidea.com
DETOUR
JAVA

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

103. @TTGonda
collectiveidea.com