SlideShare a Scribd company logo
Kotlin Backstage
Mitchell Tilbook @sir_tilbrook
youtube.com/c/anzcoders
Kotlin Backstage
— What Kotlin generates in bytecode
— Impact of const
— Objects & Statics
— Impact of Scoping on method count
Mitchell Tilbook @sir_tilbrook
youtube.com/c/anzcoders
Primitives
val number: Int = 10
val number: Int? = 10
Mitchell Tilbook @sir_tilbrook
youtube.com/c/anzcoders
Primitives
private final static I number = 10
private final static L…/Integer; nullableNumber
@L…/Nullable;() // invisible
Mitchell Tilbook @sir_tilbrook
youtube.com/c/anzcoders
String Interpolation
val i = 10
val s = "i = $i" // evaluates to "i = 10"
Mitchell Tilbook @sir_tilbrook
youtube.com/c/anzcoders
String Interpolation
NEW StringBuilder
DUP
INVOKESPECIAL StringBuilder.<init> ()V
LDC "i = "
INVOKEVIRTUAL StringBuilder.append (LString;)LStringBuilder;
GETSTATIC ExtKt.i : I
INVOKEVIRTUAL StringBuilder.append (I)LStringBuilder;
INVOKEVIRTUAL StringBuilder.toString ()LString;
Mitchell Tilbook @sir_tilbrook
youtube.com/c/anzcoders
Classes
class Speaker(val talk: String)
Mitchell Tilbook @sir_tilbrook
youtube.com/c/anzcoders
Classes
public final class Speaker {
private final String; talk
@NotNull;() // invisible
public final getTalk()String;
@NotNull;() // invisible
GETFIELD Speaker.talk : String;
ARETURN
public <init>(String;)V
…
PUTFIELD Speaker.talk : String;
}
Mitchell Tilbook @sir_tilbrook
youtube.com/c/anzcoders
Classes
class Speaker(@JvmField val talk: String)
Mitchell Tilbook @sir_tilbrook
youtube.com/c/anzcoders
Classes
public final class Speaker {
public final String; talk
@JvmField;() // invisible
@NotNull;() // invisible
public <init>(String;)V { … }
}
Mitchell Tilbook @sir_tilbrook
youtube.com/c/anzcoders
Nulls
fun len(str: String) = str.length
fun maybeLen(str: String?) = str?.length ?: 0
Mitchell Tilbook @sir_tilbrook
youtube.com/c/anzcoders
No-Nulls
public final static len(String;)I
@NotNull;() // invisible, parameter 0
LDC "str"
INVOKESTATIC Intrinsics.checkParameterIsNotNull (Object;String;)V
INVOKEVIRTUAL String.length ()I
IRETURN
public final static maybeLen(String;)I
@Nullable;() // invisible, parameter 0
IFNULL L1
INVOKEVIRTUAL java/lang/String.length ()I
GOTO L2
ICONST_0
L2
IRETURN
Mitchell Tilbook @sir_tilbrook
youtube.com/c/anzcoders
No-Nulls
public final static len(String;)I
@NotNull;() // invisible, parameter 0
LDC "str"
INVOKESTATIC Intrinsics.checkParameterIsNotNull (Object;String;)V
INVOKEVIRTUAL String.length ()I
IRETURN
public final static maybeLen(String;)I
@Nullable;() // invisible, parameter 0
IFNULL L1
INVOKEVIRTUAL java/lang/String.length ()I
GOTO L2
ICONST_0
L2
IRETURN
Mitchell Tilbook @sir_tilbrook
youtube.com/c/anzcoders
Extension Functions
fun Context.color(@ColorRes color: Int) =
ContextCompat.getColor(this, color)
Mitchell Tilbook @sir_tilbrook
youtube.com/c/anzcoders
Extension Functions
public final static color(Context;I)I
@NotNull;() // invisible, parameter 0
@ColorRes;() // invisible, parameter 1
ALOAD 0
LDC "$receiver"
INVOKESTATIC checkParameterIsNotNull (Object; String;)V
ALOAD 0
ILOAD 1
INVOKESTATIC ContextCompat.getColor (Context;I)I
IRETURN
Mitchell Tilbook @sir_tilbrook
youtube.com/c/anzcoders
Extension Functions
fun Context.color(@ColorRes color: Int) =
ContextCompat.getColor(this, color)
// sort of becomes
fun color($receiver: Context, @ColorRes color: Int) =
ContextCompat.getColor($receiver, color)
Mitchell Tilbook @sir_tilbrook
youtube.com/c/anzcoders
Inline fun
inline fun inlineFun(f: () -> Unit) {
does()
f()
dat()
}
inlineFun { dis() }
Mitchell Tilbook @sir_tilbrook
youtube.com/c/anzcoders
Inline fun
public final inlineFun(Function0;)V
@NotNull;() // invisible, parameter 0
INVOKEVIRTUAL InlineFuns.does ()V
ALOAD 1
INVOKEINTERFACE Function0.invoke ()
INVOKEVIRTUAL InlineFuns.dat ()V
RETURN
Mitchell Tilbook @sir_tilbrook
youtube.com/c/anzcoders
Inline fun
inlineFun { dis() }
INVOKEVIRTUAL InlineFuns.does ()V
INVOKEVIRTUAL InlineFuns.dis ()V
INVOKEVIRTUAL InlineFuns.dat ()V
Mitchell Tilbook @sir_tilbrook
youtube.com/c/anzcoders
Inline fun
inlineFun { dis() }
INVOKEVIRTUAL InlineFuns.does ()V
INVOKEVIRTUAL InlineFuns.dis ()V
INVOKEVIRTUAL InlineFuns.dat ()V
Mitchell Tilbook @sir_tilbrook
youtube.com/c/anzcoders
Collection Map, Filter &
Sum
Mitchell Tilbook @sir_tilbrook
youtube.com/c/anzcoders
Collection Map, Filter & Sum
class TopicFragment {
fun twoX(x: Int) = x * 2
val numbers = arrayOf(0, 1, 2, 3, 4, 5)
numbers.map(::twoX)
}
Mitchell Tilbook @sir_tilbrook
youtube.com/c/anzcoders
BIPUSH 10
ANEWARRAY Integer
INVOKESTATIC Integer.valueOf (I)Integer;
…
INVOKESTATIC Integer.valueOf (I)Integer;
CHECKCAST [LObject;
NEW ArrayList
ARRAYLENGTH
INVOKESPECIAL ArrayList.<init> (I)V
CHECKCAST Collection
ARRAYLENGTH
IF_ICMPGE L9
CHECKCAST Number
INVOKEVIRTUAL Number.intValue ()I
CHECKCAST TopicFragment
INVOKESPECIAL TopicFragment.twoX (I)I
INVOKESTATIC Integer.valueOf (I)Integer;
INVOKEINTERFACE Collection.add (LObject;)GOTO L8
CHECKCAST List
Mitchell Tilbook @sir_tilbrook
youtube.com/c/anzcoders
Integer[] numbers = new Integer[]{0, 1, 2, 3, 4, 5};
Object[] $receiver$iv = (Object[])numbers;
TopicFragment var3 = this;
Object[] $receiver$iv$iv = $receiver$iv;
Collection destination$iv$iv = (Collection)(
new ArrayList($receiver$iv.length)
);
for(int var6 = 0; var6 < $receiver$iv$iv.length; ++var6) {
Object item$iv$iv = $receiver$iv$iv[var6];
int p1 = ((Number)item$iv$iv).intValue();
Integer var13 = ((TopicFragment)var3).twoX(p1);
destination$iv$iv.add(var13);
}
List var10000 = (List)destination$iv$iv;
Mitchell Tilbook @sir_tilbrook
youtube.com/c/anzcoders
Integer[] numbers = new Integer[]{0, 1, 2, 3, 4, 5};
Object[] $receiver$iv = (Object[])numbers;
TopicFragment var3 = this;
Object[] $receiver$iv$iv = $receiver$iv;
Collection destination$iv$iv = (Collection)(
new ArrayList($receiver$iv.length)
);
for(int var6 = 0; var6 < $receiver$iv$iv.length; ++var6) {
Object item$iv$iv = $receiver$iv$iv[var6];
int p1 = ((Number)item$iv$iv).intValue();
Integer var13 = ((TopicFragment)var3).twoX(p1);
destination$iv$iv.add(var13);
}
List var10000 = (List)destination$iv$iv;
Mitchell Tilbook @sir_tilbrook
youtube.com/c/anzcoders
Integer[] numbers = new Integer[]{0, 1, 2, 3, 4, 5};
Object[] $receiver$iv = (Object[])numbers;
TopicFragment var3 = this;
Object[] $receiver$iv$iv = $receiver$iv;
Collection destination$iv$iv = (Collection)(
new ArrayList($receiver$iv.length)
);
for(int var6 = 0; var6 < $receiver$iv$iv.length; ++var6) {
Object item$iv$iv = $receiver$iv$iv[var6];
int p1 = ((Number)item$iv$iv).intValue();
Integer var13 = ((TopicFragment)var3).twoX(p1);
destination$iv$iv.add(var13);
}
List var10000 = (List)destination$iv$iv;
Mitchell Tilbook @sir_tilbrook
youtube.com/c/anzcoders
val numbers = intArrayOf(0, 1, 2, 3, 4, 5)
Mitchell Tilbook @sir_tilbrook
youtube.com/c/anzcoders
int[] numbers = new int[]{0, 1, 2, 3, 4, 5};
TopicFragment var3 = this;
int[] $receiver$iv$iv = numbers;
Collection destination$iv$iv = (Collection)(
new ArrayList(numbers.length));
for(int var6 = 0; var6 < $receiver$iv$iv.length; ++var6) {
int item$iv$iv = $receiver$iv$iv[var6];
Integer var13 = ((TopicFragment)var3).twoX(item$iv$iv);
destination$iv$iv.add(var13);
}
Mitchell Tilbook @sir_tilbrook
youtube.com/c/anzcoders
intArrayOf(0, 1, 2, 3, 4, 5)
.filter(::isEven)
.map(::twoX)
Mitchell Tilbook @sir_tilbrook
youtube.com/c/anzcoders
int[] $receiver$iv = new int[]{0, 1, 2, 3, 4, 5};
// filter(::isEven)
for(int var5 = 0; var5 < $receiver$iv$iv.length; ++var5) {
int element$iv$iv = $receiver$iv$iv[var5];
if (((TopicFragment)var2).isEven(element$iv$iv)) {
destination$iv$iv.add(element$iv$iv);
}
}
// map(::twoX)
while(var14.hasNext()) {
Object item$iv$iv = var14.next();
int p1 = ((Number)item$iv$iv).intValue();
Integer var12 = ((TopicFragment)var2).twoX(p1);
destination$iv$iv.add(var12);
}
Mitchell Tilbook @sir_tilbrook
youtube.com/c/anzcoders
intArrayOf(0, 1, 2, 3, 4, 5)
.asSequence()
.filter(::isEven)
.map(::twoX)
.toList()
Mitchell Tilbook @sir_tilbrook
youtube.com/c/anzcoders
final class TopicFragment$1
extends FunctionReference implements Function1 {
public synthetic bridge invoke(Object;)
public final invoke(I)Z
public final getOwner()KDeclarationContainer;
public final getName()String;
public final getSignature()String;
}
Mitchell Tilbook @sir_tilbrook
youtube.com/c/anzcoders
intArrayOf(0, 1, 2, 3, 4, 5)
.asSequence()
.filter { it % 2 == 0 }
.map { it * 2}
.toList()
Mitchell Tilbook @sir_tilbrook
youtube.com/c/anzcoders
INVOKESTATIC ArraysKt.asSequence ([I)LSequence;
GETSTATIC TopicFragment$1.INSTANCE : TopicFragment$1;
INVOKESTATIC SequencesKt.filter (LSequence;Function1;)
GETSTATIC TopicFragment$2.INSTANCE : TopicFragment$2;
INVOKESTATIC SequencesKt.map (LSequence;Function1;)
INVOKESTATIC SequencesKt.toList (LSequence;)List;
Mitchell Tilbook @sir_tilbrook
youtube.com/c/anzcoders
INVOKESTATIC ArraysKt.asSequence ([I)LSequence;
GETSTATIC TopicFragment$1.INSTANCE : TopicFragment$1;
INVOKESTATIC SequencesKt.filter (LSequence;Function1;)
GETSTATIC TopicFragment$2.INSTANCE : TopicFragment$2;
INVOKESTATIC SequencesKt.map (LSequence;Function1;)
INVOKESTATIC SequencesKt.toList (LSequence;)List;
Mitchell Tilbook @sir_tilbrook
youtube.com/c/anzcoders
INVOKESTATIC ArraysKt.asSequence ([I)LSequence;
GETSTATIC TopicFragment$1.INSTANCE : TopicFragment$1;
INVOKESTATIC SequencesKt.filter (LSequence;Function1;)
GETSTATIC TopicFragment$2.INSTANCE : TopicFragment$2;
INVOKESTATIC SequencesKt.map (LSequence;Function1;)
INVOKESTATIC SequencesKt.toList (LSequence;)List;
Mitchell Tilbook @sir_tilbrook
youtube.com/c/anzcoders
INVOKESTATIC ArraysKt.asSequence ([I)LSequence;
GETSTATIC TopicFragment$1.INSTANCE : TopicFragment$1;
INVOKESTATIC SequencesKt.filter (LSequence;Function1;)
GETSTATIC TopicFragment$2.INSTANCE : TopicFragment$2;
INVOKESTATIC SequencesKt.map (LSequence;Function1;)
INVOKESTATIC SequencesKt.toList (LSequence;)List;
Mitchell Tilbook @sir_tilbrook
youtube.com/c/anzcoders
Data Classes
data class Speaker(
val description: String,
val talks: List<Talk>,
val profile: String
)
Mitchell Tilbook @sir_tilbrook
youtube.com/c/anzcoders
De-structure data class
val speaker = Speaker(
talks = arrayListOf(),
description = "Bytecode",
profile = ""
)
val (description, talks) = speaker
Mitchell Tilbook @sir_tilbrook
youtube.com/c/anzcoders
public final component1()String;
@NotNull;() // invisible
ALOAD 0
GETFIELD Speaker.description : String;
ARETURN
// signature ()LList<LTalk;>;
// declaration: java.util.List<Talk> component2()
public final component2()LList;
@NotNull;() // invisible
ALOAD 0
GETFIELD Speaker.talks : LList;
ARETURN
Mitchell Tilbook @sir_tilbrook
youtube.com/c/anzcoders
// signature …
// declaration: Speaker copy(java.lang.String, java.util.List<? extends Talk>)
public final copy(String;LList;)LSpeaker;
@NotNull;() // invisible
@NotNull;() // invisible, parameter 0
@NotNull;() // invisible, parameter 1
INVOKESTATIC checkParameterIsNotNull (Object;String;)V
INVOKESTATIC checkParameterIsNotNull (Object;String;)V
NEW Speaker
INVOKESPECIAL Speaker.<init> (String;LList;)V
ARETURN
Mitchell Tilbook @sir_tilbrook
youtube.com/c/anzcoders
val speaker2 = speaker.copy(
description = "Second speaker"
)
Mitchell Tilbook @sir_tilbrook
youtube.com/c/anzcoders
public static synthetic bridge copy$default(LSpeaker;String;LList;IObject;)LSpeaker;
@NotNull;() // invisible
ILOAD 3
ICONST_1
IAND
IFEQ L0
ALOAD 0
GETFIELD Speaker.description : String;
ASTORE 1
L0
ILOAD 3
ICONST_2
IAND
IFEQ L1
ALOAD 0
GETFIELD Speaker.talks : LList;
ASTORE 2
L1
ALOAD 0
ALOAD 1
ALOAD 2
INVOKEVIRTUAL Speaker.copy (String;LList;)LSpeaker;
ARETURN
Mitchell Tilbook @sir_tilbrook
youtube.com/c/anzcoders
public static Speaker copy$default(
Speaker var0,
String var1, List var2, String var3,
int var4, Object var5
) {
if ((var4 & 1) != 0) {
var1 = var0.description;
}
if ((var4 & 2) != 0) {
var2 = var0.talks;
}
if ((var4 & 4) != 0) {
var3 = var0.profile;
}
return var0.copy(var1, var2, var3);
}
Mitchell Tilbook @sir_tilbrook
youtube.com/c/anzcoders
Lambdas
— SAM (Single Access Method)
— Non-Capturing Lambdas
— Capturing Lambdas
Mitchell Tilbook @sir_tilbrook
youtube.com/c/anzcoders
SAMs
view.setOnClickListener {
print("Hello")
}
Mitchell Tilbook @sir_tilbrook
youtube.com/c/anzcoders
SAMs
final class Sam$1 implements View$OnClickListener {
public final onClick(Landroid/view/View;)V
LDC "Hello"
INVOKEVIRTUAL PrintStream.print (Object;)V
RETURN
<init>()V
INVOKESPECIAL Object.<init> ()V
RETURN
public final static Sam$1; INSTANCE
static <clinit>()V
NEW Sam$1
DUP
INVOKESPECIAL Sam$1.<init> ()V
PUTSTATIC Sam$1.INSTANCE : Sam$1;
RETURN
Mitchell Tilbook @sir_tilbrook
youtube.com/c/anzcoders
class Lmd {
private val lambda = {
"I'm a lambda"
}
}
Mitchell Tilbook @sir_tilbrook
youtube.com/c/anzcoders
public final class Lmd {
// signature Function0<String;>;
// declaration: Function0<java.lang.String>
private final Function0; lambda
public <init>()V
// …
ALOAD 0
GETSTATIC Lmd$lambda$1.INSTANCE : Lmd$lambda$1;
CHECKCAST Function0
PUTFIELD Lmd.lambda : Function0;
RETURN
}
Mitchell Tilbook @sir_tilbrook
youtube.com/c/anzcoders
final class Lmd$lambda$1
extends Lambda
implements Function0 {
<init>()V
INVOKESPECIAL Lambda.<init> (I)V
RETURN
public final static Lmd$lambda$1; INSTANCE
static <clinit>()V
NEW Lmd$lambda$1
DUP
INVOKESPECIAL Lmd$lambda$1.<init> ()V
PUTSTATIC Lmd$lambda$1.INSTANCE : Lmd$lambda$1;
RETURN
}
Mitchell Tilbook @sir_tilbrook
youtube.com/c/anzcoders
public synthetic bridge invoke()Object;
L0
LINENUMBER 3 L0
ALOAD 0
INVOKEVIRTUAL Lmd$lambda$1.invoke ()String;
ARETURN
// access flags 0x11
public final invoke()String;
@NotNull;() // invisible
L0
LINENUMBER 5 L0
LDC "I'm a lambda"
L1
ARETURN
Mitchell Tilbook @sir_tilbrook
youtube.com/c/anzcoders
class Lmd {
private val lambda = {
"I'm a lambda"
}
val value = lambda()
}
Mitchell Tilbook @sir_tilbrook
youtube.com/c/anzcoders
public final class Lmd {
public <init>()V
…
ALOAD 0
GETFIELD Lmd.lambda : Function0;
INVOKEINTERFACE Function0.invoke ()Object;
CHECKCAST String
}
final class public Lmd$lambda$1 {
public synthetic bridge invoke()Object;
Lmd$lambda$1.invoke ()String;
}
Mitchell Tilbook @sir_tilbrook
youtube.com/c/anzcoders
Lambda s and Field
class Lmd (
private val speaker: Speaker
) {
private val lambda = {
speaker.name
}
}
Mitchell Tilbook @sir_tilbrook
youtube.com/c/anzcoders
final class Lmd$lambda$1 {
final synthetic Lmd; this$0
public final invoke()String;
@NotNull;() // invisible
GETFIELD Lmd$lambda$1.this$0 : Lmd;
INVOKESTATIC Lmd.access$getSpeaker$p (Lmd;)LSpeaker;
INVOKEVIRTUAL Speaker.getName ()String;
ARETURN
<init>(Lmd;)V
PUTFIELD Lmd$lambda$1.this$0 : Lmd;
INVOKESPECIAL Lambda.<init> (I)V
RETURN
}
Mitchell Tilbook @sir_tilbrook
youtube.com/c/anzcoders
final class Lmd$lambda$1 {
final synthetic Lmd; this$0
public final invoke()String;
@NotNull;() // invisible
GETFIELD Lmd$lambda$1.this$0 : Lmd;
INVOKESTATIC Lmd.access$getSpeaker$p (Lmd;)LSpeaker;
INVOKEVIRTUAL Speaker.getName ()String;
ARETURN
<init>(Lmd;)V
PUTFIELD Lmd$lambda$1.this$0 : Lmd;
INVOKESPECIAL Lambda.<init> (I)V
RETURN
}
Mitchell Tilbook @sir_tilbrook
youtube.com/c/anzcoders
public final class Lmd {
public final static synthetic access$getSpeaker$p(Lmd;)Speaker;
@NotNull;() // invisible
ALOAD 0
GETFIELD Lmd.speaker : Speaker;
ARETURN
}
Mitchell Tilbook @sir_tilbrook
youtube.com/c/anzcoders
class Lmd (
@JvmField protected
private val speaker: Speaker
){
private val lambda = {
speaker.name
}
}
Mitchell Tilbook @sir_tilbrook
youtube.com/c/anzcoders
class Lmd (
@Suppress("WARNINGS")
@JvmField
protected
private val speaker: Speaker = Speaker("speaker")
){
private val lambda = {
speaker.name
}
}
Mitchell Tilbook @sir_tilbrook
youtube.com/c/anzcoders
final class Lmd$lambda$1 {
public final invoke()String;
GETFIELD Lmd$lambda$1.this$0 : LLmd;
GETFIELD Lmd.speaker : LSpeaker;
INVOKEVIRTUAL Speaker.getName ()String;
ARETURNdas.lambda : Function0;
RETURN
}
Mitchell Tilbook @sir_tilbrook
youtube.com/c/anzcoders
File values and
functions
Mitchell Tilbook @sir_tilbrook
youtube.com/c/anzcoders
// file name Objects
private val speaker = Speaker()
public final class ObjectsKt {
private final static Speaker; speaker
static <clinit>()V
NEW Speaker
DUP
INVOKESPECIAL Speaker.<init> ()V
PUTSTATIC ObjectsKt.speaker : LSpeaker;
RETURN
}
Mitchell Tilbook @sir_tilbrook
youtube.com/c/anzcoders
// file name Objects
private val speaker = Speaker()
public final class ObjectsKt {
private final static Speaker; speaker
static <clinit>()V
NEW Speaker
DUP
INVOKESPECIAL Speaker.<init> ()V
PUTSTATIC ObjectsKt.speaker : LSpeaker;
RETURN
}
Mitchell Tilbook @sir_tilbrook
youtube.com/c/anzcoders
fun someStr() = "Some String"
// Becomes
public final class ObjectsKt {
public final static someStr() String;
@NotNull;() // invisible
LDC "Some String"
ARETURN
}
Mitchell Tilbook @sir_tilbrook
youtube.com/c/anzcoders
private val someStr = "Some String"
Mitchell Tilbook @sir_tilbrook
youtube.com/c/anzcoders
public final class ObjectsKt {
private final static String; someStr = "Some String"
static <clinit>()V
LDC "Some String"
PUTSTATIC ObjectsKt.someStr : String;
RETURN
}
Mitchell Tilbook @sir_tilbrook
youtube.com/c/anzcoders
private const val someStr = "Some String"
Mitchell Tilbook @sir_tilbrook
youtube.com/c/anzcoders
public final class ObjectsKt {
private final static String; someStr = "Some String"
}
Mitchell Tilbook @sir_tilbrook
youtube.com/c/anzcoders
Objects
object AnObject
Mitchell Tilbook @sir_tilbrook
youtube.com/c/anzcoders
public final class AnObject {
public final static AnObject; INSTANCE
private <init>()V
INVOKESPECIAL Object.<init> ()V
RETURN
static <clinit>()V
NEW AnObject
DUP
INVOKESPECIAL AnObject.<init> ()V
PUTSTATIC AnObject.INSTANCE : AnObject;
RETURN
}
Mitchell Tilbook @sir_tilbrook
youtube.com/c/anzcoders
object AnObject {
val name = "Mitchell"
}
Mitchell Tilbook @sir_tilbrook
youtube.com/c/anzcoders
public final class AnObject {
private final static String; name = "Mitchell"
@NotNull;() // invisible
public final getName()String;
@NotNull;() // invisible
GETSTATIC AnObject.name : String;
ARETURN
static <clinit>()V
LDC "Mitchell"
PUTSTATIC AnObject.name : String;
RETURN
}
Mitchell Tilbook @sir_tilbrook
youtube.com/c/anzcoders
object AnObject {
const val name = "Mitchell"
}
Mitchell Tilbook @sir_tilbrook
youtube.com/c/anzcoders
public final class AnObject {
public final static String; name = "Mitchell"
public final static LAnObject; INSTANCE
private <init>()V
INVOKESPECIAL Object.<init> ()V
RETURN
static <clinit>()V
NEW AnObject
DUP
INVOKESPECIAL AnObject.<init> ()V
PUTSTATIC AnObject.INSTANCE : LAnObject;
Mitchell Tilbook @sir_tilbrook
youtube.com/c/anzcoders
object AnObject {
fun speaker() = Speaker()
}
Mitchell Tilbook @sir_tilbrook
youtube.com/c/anzcoders
public final class AnObject {
public final speaker() Speaker;
@NotNull;() // invisible
NEW Speaker
DUP
INVOKESPECIAL Speaker.<init> ()V
ARETURN
Mitchell Tilbook @sir_tilbrook
youtube.com/c/anzcoders
object AnObject {
@JvmStatic
fun speaker() = Speaker()
}
// With @JvmStatic
public final class AnObject {
public final static speaker() Speaker;
@JvmStatic;()
@NotNull;() // invisible
}
Mitchell Tilbook @sir_tilbrook
youtube.com/c/anzcoders
Companion Object
Mitchell Tilbook @sir_tilbrook
youtube.com/c/anzcoders
class TopicFragment {
companion object {
}
}
Mitchell Tilbook @sir_tilbrook
youtube.com/c/anzcoders
public final class TopicFragment {
public <init>()V
static <clinit>()V
NEW TopicFragment$Companion
DUP
ACONST_NULL
INVOKESPECIAL TopicFragment$Companion.<init> (
DefaultConstructorMarker;
)V
PUTSTATIC TopicFragment.Companion : TopicFragment$Companion;
RETURN
public final static TopicFragment$Companion; Companion
public final static INNERCLASS
TopicFragment$Companion TopicFragment Companion
}
Mitchell Tilbook @sir_tilbrook
youtube.com/c/anzcoders
public final class TopicFragment$Companion {
private <init>()V
INVOKESPECIAL Object.<init> ()V
RETURN
public synthetic <init>(DefaultConstructorMarker;)V
INVOKESPECIAL TopicFragment$Companion.<init> ()V
RETURN
public final static INNERCLASS
TopicFragment$Companion TopicFragment Companion
}
Mitchell Tilbook @sir_tilbrook
youtube.com/c/anzcoders
class TopicFragment {
companion object {
val EXTRA_TOPIC_ID = "EXTRA_TOPIC_ID"
}
}
Mitchell Tilbook @sir_tilbrook
youtube.com/c/anzcoders
class TopicFragment {
init {
EXTRA_TOPIC_ID
}
companion object {
val EXTRA_TOPIC_ID = "EXTRA_TOPIC_ID"
}
}
Mitchell Tilbook @sir_tilbrook
youtube.com/c/anzcoders
public final class TopicFragment {
private final static String; EXTRA_TOPIC_ID =
"EXTRA_TOPIC_ID"
static <clinit>()V
NEW TopicFragment$Companion
…
LDC "EXTRA_TOPIC_ID"
PUTSTATIC TopicFragment
.EXTRA_TOPIC_ID : String;
RETURN
}
Mitchell Tilbook @sir_tilbrook
youtube.com/c/anzcoders
public final class TopicFragment {
public <init>()V
GETSTATIC Companion : $Companion;
INVOKEVIRTUAL $Companion
.getEXTRA_TOPIC_ID ()String;
POP
…
}
Mitchell Tilbook @sir_tilbrook
youtube.com/c/anzcoders
public final class TopicFragment$Companion {
public final getEXTRA_TOPIC_ID()String;
@NotNull;() // invisible
L0
LINENUMBER 11 L0
INVOKESTATIC TopicFragment.access$getEXTRA_TOPIC_ID$cp ()String;
ARETURN
}
public final class TopicFragment {
public final static synthetic access$getEXTRA_TOPIC_ID$cp()String;
@NotNull;() // invisible
GETSTATIC TopicFragment.EXTRA_TOPIC_ID : String;
ARETURN
Mitchell Tilbook @sir_tilbrook
youtube.com/c/anzcoders
Mitchell Tilbook @sir_tilbrook
youtube.com/c/anzcoders
class TopicFragment {
init {
EXTRA_TOPIC_ID
}
companion object {
const val EXTRA_TOPIC_ID = "EXTRA_TOPIC_ID"
}
}
Mitchell Tilbook @sir_tilbrook
youtube.com/c/anzcoders
public final class TopicFragment {
public <init>()V
INVOKESPECIAL Object.<init> ()V
// Now all we get is metadata
LINENUMBER 6 L1
RETURN
public final static String; EXTRA_TOPIC_ID =
"EXTRA_TOPIC_ID"
@NotNull;() // invisible
Mitchell Tilbook @sir_tilbrook
youtube.com/c/anzcoders
package io.github.droidkaigi.confsched2018.data.api.response.mapper
class LocalDateTimeAdapter : JsonAdapter<LocalDateTime>() {
companion object {
private val FORMATTER: DateTimeFormatter =
DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss")
fun parseDateString(dateString: String?): LocalDateTime =
LocalDateTime.parse(dateString, FORMATTER)
}
}
Mitchell Tilbook @sir_tilbrook
youtube.com/c/anzcoders
private object FormatCompanion {
@JvmField
val FORMATTER: DateTimeFormatter =
DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss")
}
class LocalDateTimeAdapter : JsonAdapter<LocalDateTime>() {
…
companion object {
fun parseDateString(dateString: String?): LocalDateTime =
LocalDateTime.parse(dateString, FORMATTER)
}
}
Mitchell Tilbook @sir_tilbrook
youtube.com/c/anzcoders
/* package private */ final class FormatCompanion {
public final static DateTimeFormatter; FORMATTER
}
Mitchell Tilbook @sir_tilbrook
youtube.com/c/anzcoders
class TopicFragment {
companion object {
private const val EXTRA_TOPIC_ID = "EXTRA_TOPIC_ID"
fun newInstance(topicId: Int) {
}
}
}
Mitchell Tilbook @sir_tilbrook
youtube.com/c/anzcoders
Reducing Synthetic Methods
class TopicDetailViewModel
@Inject constructor(
private val repository: SessionRepository,
private val schedulerProvider: SchedulerProvider
) : ViewModel(), LifecycleObserver {
var topicId: Int = 0
val topicSessions: LiveDataSessions by lazy {
repository.topicSessions
.map {
it
.filter { it.key.id == topicId }
.map { it.key to it.value }
.first()
}
.toResult(schedulerProvider)
.toLiveData()
}
Mitchell Tilbook @sir_tilbrook
youtube.com/c/anzcoders
public final class TopicDetailViewModel
extends android/arch/lifecycle/ViewModel
implements android/arch/lifecycle/LifecycleObserver {
public final static synthetic access$getRepository
$p(LTopicDetailViewModel;)SessionRepository;
@NotNull;() // invisible
L0
LINENUMBER 20 L0
ALOAD 0
GETFIELD TopicDetailViewModel.repository : SessionRepository;
ARETURN
public final static synthetic access$getSchedulerProvider
$p(LTopicDetailViewModel;)SchedulerProvider;
@NotNull;() // invisible
L0
LINENUMBER 20 L0
ALOAD 0
GETFIELD TopicDetailViewModel.schedulerProvider : SchedulerProvider;
ARETURN
Mitchell Tilbook @sir_tilbrook
youtube.com/c/anzcoders
class TopicDetailViewModel
@Inject constructor(
private val repository: SessionRepository,
private val schedulerProvider: SchedulerProvider
) : ViewModel(), LifecycleObserver {
var topicId: Int = 0
val topicSessions: LiveDataSessions by lazy {
repository.topicSessions
.map {
it
.filter { it.key.id == topicId }
.map { it.key to it.value }
.first()
}
.toResult(schedulerProvider)
.toLiveData()
}
Mitchell Tilbook @sir_tilbrook
youtube.com/c/anzcoders
class TopicDetailViewModel
@Inject constructor(
@JvmField protected
val repository: SessionRepository,
@JvmField protected
val schedulerProvider: SchedulerProvider
)
Mitchell Tilbook @sir_tilbrook
youtube.com/c/anzcoders
// protected is effectively private in final classes
class TopicDetailViewModel
@Inject
@Suppress("warnings")
constructor(
@JvmField protected
val repository: SessionRepository,
@JvmField protected
val schedulerProvider: SchedulerProvider
)
Mitchell Tilbook @sir_tilbrook
youtube.com/c/anzcoders
Mitchell Tilbrook
@sir_tilbrook
Sydney Tech Talks
youtube.com/c/anzcoders
Moneytree
Android Developer
moneytree.jp
Mitchell Tilbook @sir_tilbrook
youtube.com/c/anzcoders

More Related Content

DOC
basic shell_programs
PDF
Fun with Kotlin
PDF
Implementing virtual machines in go & c 2018 redux
PDF
XKE Typeclass
PDF
Let's fly to the Kotlin Island. Just an introduction to Kotlin
PDF
Hello Swift 3/5 - Function
PDF
ZIO Schedule: Conquering Flakiness & Recurrence with Pure Functional Programming
PPT
Inheritance compiler support
basic shell_programs
Fun with Kotlin
Implementing virtual machines in go & c 2018 redux
XKE Typeclass
Let's fly to the Kotlin Island. Just an introduction to Kotlin
Hello Swift 3/5 - Function
ZIO Schedule: Conquering Flakiness & Recurrence with Pure Functional Programming
Inheritance compiler support

What's hot (20)

PDF
Streams for (Co)Free!
DOC
CBSE Class XII Comp sc practical file
PDF
Why Kotlin is your next language?
PDF
Stupid Awesome Python Tricks
PDF
20180310 functional programming
PDF
FP in scalaで鍛える関数型脳
PDF
Quarto Presentations with Reveal.js
PDF
20191116 custom operators in swift
KEY
Let's build a parser!
PDF
Galios: Python Programming
KEY
Stackful
PDF
Diving into byte code optimization in python
PPT
Introduction to Perl
PDF
Imugi: Compiler made with Python
PPT
PDF
Swift the implicit parts
PDF
Exploring slides
PDF
An Intro To ES6
PPT
C++totural file
PPTX
Ruby on rails tips
Streams for (Co)Free!
CBSE Class XII Comp sc practical file
Why Kotlin is your next language?
Stupid Awesome Python Tricks
20180310 functional programming
FP in scalaで鍛える関数型脳
Quarto Presentations with Reveal.js
20191116 custom operators in swift
Let's build a parser!
Galios: Python Programming
Stackful
Diving into byte code optimization in python
Introduction to Perl
Imugi: Compiler made with Python
Swift the implicit parts
Exploring slides
An Intro To ES6
C++totural file
Ruby on rails tips
Ad

Similar to Kotlin Backstage (20)

PDF
Kotlin Backstage - Android Makers Paris 2018
PDF
JavaZone 2022 - Building Kotlin DSL.pdf
PDF
Davide Cerbo - Kotlin: forse è la volta buona - Codemotion Milan 2017
PDF
TDC218SP | Trilha Kotlin - DSLs in a Kotlin Way
PDF
Functions in Objective-C and C Programming
PDF
Kotlin for Android Developers
PDF
Generics and Inference
PDF
"О некоторых особенностях Objective-C++" Влад Михайленко (Maps.Me)
PDF
Get Functional on the CLR: Intro to Functional Programming with F#
PPTX
Effective C#
PPTX
Connect() Mini 2016
PDF
The What, Why And How of ClojureScript
PDF
つくってあそぼ Kotlin DSL ~拡張編~
PPTX
EcmaScript unchained
PDF
From java to kotlin beyond alt+shift+cmd+k
PPTX
01 Introduction to Kotlin - Programming in Kotlin.pptx
PPTX
Introduction to Kotlin.pptx
PDF
Kotlin Generation
PPT
KEY
Metaprogramming in Haskell
Kotlin Backstage - Android Makers Paris 2018
JavaZone 2022 - Building Kotlin DSL.pdf
Davide Cerbo - Kotlin: forse è la volta buona - Codemotion Milan 2017
TDC218SP | Trilha Kotlin - DSLs in a Kotlin Way
Functions in Objective-C and C Programming
Kotlin for Android Developers
Generics and Inference
"О некоторых особенностях Objective-C++" Влад Михайленко (Maps.Me)
Get Functional on the CLR: Intro to Functional Programming with F#
Effective C#
Connect() Mini 2016
The What, Why And How of ClojureScript
つくってあそぼ Kotlin DSL ~拡張編~
EcmaScript unchained
From java to kotlin beyond alt+shift+cmd+k
01 Introduction to Kotlin - Programming in Kotlin.pptx
Introduction to Kotlin.pptx
Kotlin Generation
Metaprogramming in Haskell
Ad

Recently uploaded (20)

PPTX
Machine Learning_overview_presentation.pptx
PDF
gpt5_lecture_notes_comprehensive_20250812015547.pdf
PDF
Approach and Philosophy of On baking technology
PDF
Accuracy of neural networks in brain wave diagnosis of schizophrenia
PPTX
KOM of Painting work and Equipment Insulation REV00 update 25-dec.pptx
PDF
cuic standard and advanced reporting.pdf
PDF
NewMind AI Weekly Chronicles - August'25-Week II
PPTX
Digital-Transformation-Roadmap-for-Companies.pptx
PPT
Teaching material agriculture food technology
PDF
Getting Started with Data Integration: FME Form 101
PDF
Empathic Computing: Creating Shared Understanding
PDF
A comparative analysis of optical character recognition models for extracting...
PDF
Network Security Unit 5.pdf for BCA BBA.
PDF
Mobile App Security Testing_ A Comprehensive Guide.pdf
PDF
Reach Out and Touch Someone: Haptics and Empathic Computing
PDF
Blue Purple Modern Animated Computer Science Presentation.pdf.pdf
PDF
Machine learning based COVID-19 study performance prediction
PPTX
Spectroscopy.pptx food analysis technology
PDF
Profit Center Accounting in SAP S/4HANA, S4F28 Col11
PDF
The Rise and Fall of 3GPP – Time for a Sabbatical?
Machine Learning_overview_presentation.pptx
gpt5_lecture_notes_comprehensive_20250812015547.pdf
Approach and Philosophy of On baking technology
Accuracy of neural networks in brain wave diagnosis of schizophrenia
KOM of Painting work and Equipment Insulation REV00 update 25-dec.pptx
cuic standard and advanced reporting.pdf
NewMind AI Weekly Chronicles - August'25-Week II
Digital-Transformation-Roadmap-for-Companies.pptx
Teaching material agriculture food technology
Getting Started with Data Integration: FME Form 101
Empathic Computing: Creating Shared Understanding
A comparative analysis of optical character recognition models for extracting...
Network Security Unit 5.pdf for BCA BBA.
Mobile App Security Testing_ A Comprehensive Guide.pdf
Reach Out and Touch Someone: Haptics and Empathic Computing
Blue Purple Modern Animated Computer Science Presentation.pdf.pdf
Machine learning based COVID-19 study performance prediction
Spectroscopy.pptx food analysis technology
Profit Center Accounting in SAP S/4HANA, S4F28 Col11
The Rise and Fall of 3GPP – Time for a Sabbatical?

Kotlin Backstage

  • 1. Kotlin Backstage Mitchell Tilbook @sir_tilbrook youtube.com/c/anzcoders
  • 2. Kotlin Backstage — What Kotlin generates in bytecode — Impact of const — Objects & Statics — Impact of Scoping on method count Mitchell Tilbook @sir_tilbrook youtube.com/c/anzcoders
  • 3. Primitives val number: Int = 10 val number: Int? = 10 Mitchell Tilbook @sir_tilbrook youtube.com/c/anzcoders
  • 4. Primitives private final static I number = 10 private final static L…/Integer; nullableNumber @L…/Nullable;() // invisible Mitchell Tilbook @sir_tilbrook youtube.com/c/anzcoders
  • 5. String Interpolation val i = 10 val s = "i = $i" // evaluates to "i = 10" Mitchell Tilbook @sir_tilbrook youtube.com/c/anzcoders
  • 6. String Interpolation NEW StringBuilder DUP INVOKESPECIAL StringBuilder.<init> ()V LDC "i = " INVOKEVIRTUAL StringBuilder.append (LString;)LStringBuilder; GETSTATIC ExtKt.i : I INVOKEVIRTUAL StringBuilder.append (I)LStringBuilder; INVOKEVIRTUAL StringBuilder.toString ()LString; Mitchell Tilbook @sir_tilbrook youtube.com/c/anzcoders
  • 7. Classes class Speaker(val talk: String) Mitchell Tilbook @sir_tilbrook youtube.com/c/anzcoders
  • 8. Classes public final class Speaker { private final String; talk @NotNull;() // invisible public final getTalk()String; @NotNull;() // invisible GETFIELD Speaker.talk : String; ARETURN public <init>(String;)V … PUTFIELD Speaker.talk : String; } Mitchell Tilbook @sir_tilbrook youtube.com/c/anzcoders
  • 9. Classes class Speaker(@JvmField val talk: String) Mitchell Tilbook @sir_tilbrook youtube.com/c/anzcoders
  • 10. Classes public final class Speaker { public final String; talk @JvmField;() // invisible @NotNull;() // invisible public <init>(String;)V { … } } Mitchell Tilbook @sir_tilbrook youtube.com/c/anzcoders
  • 11. Nulls fun len(str: String) = str.length fun maybeLen(str: String?) = str?.length ?: 0 Mitchell Tilbook @sir_tilbrook youtube.com/c/anzcoders
  • 12. No-Nulls public final static len(String;)I @NotNull;() // invisible, parameter 0 LDC "str" INVOKESTATIC Intrinsics.checkParameterIsNotNull (Object;String;)V INVOKEVIRTUAL String.length ()I IRETURN public final static maybeLen(String;)I @Nullable;() // invisible, parameter 0 IFNULL L1 INVOKEVIRTUAL java/lang/String.length ()I GOTO L2 ICONST_0 L2 IRETURN Mitchell Tilbook @sir_tilbrook youtube.com/c/anzcoders
  • 13. No-Nulls public final static len(String;)I @NotNull;() // invisible, parameter 0 LDC "str" INVOKESTATIC Intrinsics.checkParameterIsNotNull (Object;String;)V INVOKEVIRTUAL String.length ()I IRETURN public final static maybeLen(String;)I @Nullable;() // invisible, parameter 0 IFNULL L1 INVOKEVIRTUAL java/lang/String.length ()I GOTO L2 ICONST_0 L2 IRETURN Mitchell Tilbook @sir_tilbrook youtube.com/c/anzcoders
  • 14. Extension Functions fun Context.color(@ColorRes color: Int) = ContextCompat.getColor(this, color) Mitchell Tilbook @sir_tilbrook youtube.com/c/anzcoders
  • 15. Extension Functions public final static color(Context;I)I @NotNull;() // invisible, parameter 0 @ColorRes;() // invisible, parameter 1 ALOAD 0 LDC "$receiver" INVOKESTATIC checkParameterIsNotNull (Object; String;)V ALOAD 0 ILOAD 1 INVOKESTATIC ContextCompat.getColor (Context;I)I IRETURN Mitchell Tilbook @sir_tilbrook youtube.com/c/anzcoders
  • 16. Extension Functions fun Context.color(@ColorRes color: Int) = ContextCompat.getColor(this, color) // sort of becomes fun color($receiver: Context, @ColorRes color: Int) = ContextCompat.getColor($receiver, color) Mitchell Tilbook @sir_tilbrook youtube.com/c/anzcoders
  • 17. Inline fun inline fun inlineFun(f: () -> Unit) { does() f() dat() } inlineFun { dis() } Mitchell Tilbook @sir_tilbrook youtube.com/c/anzcoders
  • 18. Inline fun public final inlineFun(Function0;)V @NotNull;() // invisible, parameter 0 INVOKEVIRTUAL InlineFuns.does ()V ALOAD 1 INVOKEINTERFACE Function0.invoke () INVOKEVIRTUAL InlineFuns.dat ()V RETURN Mitchell Tilbook @sir_tilbrook youtube.com/c/anzcoders
  • 19. Inline fun inlineFun { dis() } INVOKEVIRTUAL InlineFuns.does ()V INVOKEVIRTUAL InlineFuns.dis ()V INVOKEVIRTUAL InlineFuns.dat ()V Mitchell Tilbook @sir_tilbrook youtube.com/c/anzcoders
  • 20. Inline fun inlineFun { dis() } INVOKEVIRTUAL InlineFuns.does ()V INVOKEVIRTUAL InlineFuns.dis ()V INVOKEVIRTUAL InlineFuns.dat ()V Mitchell Tilbook @sir_tilbrook youtube.com/c/anzcoders
  • 21. Collection Map, Filter & Sum Mitchell Tilbook @sir_tilbrook youtube.com/c/anzcoders
  • 22. Collection Map, Filter & Sum class TopicFragment { fun twoX(x: Int) = x * 2 val numbers = arrayOf(0, 1, 2, 3, 4, 5) numbers.map(::twoX) } Mitchell Tilbook @sir_tilbrook youtube.com/c/anzcoders
  • 23. BIPUSH 10 ANEWARRAY Integer INVOKESTATIC Integer.valueOf (I)Integer; … INVOKESTATIC Integer.valueOf (I)Integer; CHECKCAST [LObject; NEW ArrayList ARRAYLENGTH INVOKESPECIAL ArrayList.<init> (I)V CHECKCAST Collection ARRAYLENGTH IF_ICMPGE L9 CHECKCAST Number INVOKEVIRTUAL Number.intValue ()I CHECKCAST TopicFragment INVOKESPECIAL TopicFragment.twoX (I)I INVOKESTATIC Integer.valueOf (I)Integer; INVOKEINTERFACE Collection.add (LObject;)GOTO L8 CHECKCAST List Mitchell Tilbook @sir_tilbrook youtube.com/c/anzcoders
  • 24. Integer[] numbers = new Integer[]{0, 1, 2, 3, 4, 5}; Object[] $receiver$iv = (Object[])numbers; TopicFragment var3 = this; Object[] $receiver$iv$iv = $receiver$iv; Collection destination$iv$iv = (Collection)( new ArrayList($receiver$iv.length) ); for(int var6 = 0; var6 < $receiver$iv$iv.length; ++var6) { Object item$iv$iv = $receiver$iv$iv[var6]; int p1 = ((Number)item$iv$iv).intValue(); Integer var13 = ((TopicFragment)var3).twoX(p1); destination$iv$iv.add(var13); } List var10000 = (List)destination$iv$iv; Mitchell Tilbook @sir_tilbrook youtube.com/c/anzcoders
  • 25. Integer[] numbers = new Integer[]{0, 1, 2, 3, 4, 5}; Object[] $receiver$iv = (Object[])numbers; TopicFragment var3 = this; Object[] $receiver$iv$iv = $receiver$iv; Collection destination$iv$iv = (Collection)( new ArrayList($receiver$iv.length) ); for(int var6 = 0; var6 < $receiver$iv$iv.length; ++var6) { Object item$iv$iv = $receiver$iv$iv[var6]; int p1 = ((Number)item$iv$iv).intValue(); Integer var13 = ((TopicFragment)var3).twoX(p1); destination$iv$iv.add(var13); } List var10000 = (List)destination$iv$iv; Mitchell Tilbook @sir_tilbrook youtube.com/c/anzcoders
  • 26. Integer[] numbers = new Integer[]{0, 1, 2, 3, 4, 5}; Object[] $receiver$iv = (Object[])numbers; TopicFragment var3 = this; Object[] $receiver$iv$iv = $receiver$iv; Collection destination$iv$iv = (Collection)( new ArrayList($receiver$iv.length) ); for(int var6 = 0; var6 < $receiver$iv$iv.length; ++var6) { Object item$iv$iv = $receiver$iv$iv[var6]; int p1 = ((Number)item$iv$iv).intValue(); Integer var13 = ((TopicFragment)var3).twoX(p1); destination$iv$iv.add(var13); } List var10000 = (List)destination$iv$iv; Mitchell Tilbook @sir_tilbrook youtube.com/c/anzcoders
  • 27. val numbers = intArrayOf(0, 1, 2, 3, 4, 5) Mitchell Tilbook @sir_tilbrook youtube.com/c/anzcoders
  • 28. int[] numbers = new int[]{0, 1, 2, 3, 4, 5}; TopicFragment var3 = this; int[] $receiver$iv$iv = numbers; Collection destination$iv$iv = (Collection)( new ArrayList(numbers.length)); for(int var6 = 0; var6 < $receiver$iv$iv.length; ++var6) { int item$iv$iv = $receiver$iv$iv[var6]; Integer var13 = ((TopicFragment)var3).twoX(item$iv$iv); destination$iv$iv.add(var13); } Mitchell Tilbook @sir_tilbrook youtube.com/c/anzcoders
  • 29. intArrayOf(0, 1, 2, 3, 4, 5) .filter(::isEven) .map(::twoX) Mitchell Tilbook @sir_tilbrook youtube.com/c/anzcoders
  • 30. int[] $receiver$iv = new int[]{0, 1, 2, 3, 4, 5}; // filter(::isEven) for(int var5 = 0; var5 < $receiver$iv$iv.length; ++var5) { int element$iv$iv = $receiver$iv$iv[var5]; if (((TopicFragment)var2).isEven(element$iv$iv)) { destination$iv$iv.add(element$iv$iv); } } // map(::twoX) while(var14.hasNext()) { Object item$iv$iv = var14.next(); int p1 = ((Number)item$iv$iv).intValue(); Integer var12 = ((TopicFragment)var2).twoX(p1); destination$iv$iv.add(var12); } Mitchell Tilbook @sir_tilbrook youtube.com/c/anzcoders
  • 31. intArrayOf(0, 1, 2, 3, 4, 5) .asSequence() .filter(::isEven) .map(::twoX) .toList() Mitchell Tilbook @sir_tilbrook youtube.com/c/anzcoders
  • 32. final class TopicFragment$1 extends FunctionReference implements Function1 { public synthetic bridge invoke(Object;) public final invoke(I)Z public final getOwner()KDeclarationContainer; public final getName()String; public final getSignature()String; } Mitchell Tilbook @sir_tilbrook youtube.com/c/anzcoders
  • 33. intArrayOf(0, 1, 2, 3, 4, 5) .asSequence() .filter { it % 2 == 0 } .map { it * 2} .toList() Mitchell Tilbook @sir_tilbrook youtube.com/c/anzcoders
  • 34. INVOKESTATIC ArraysKt.asSequence ([I)LSequence; GETSTATIC TopicFragment$1.INSTANCE : TopicFragment$1; INVOKESTATIC SequencesKt.filter (LSequence;Function1;) GETSTATIC TopicFragment$2.INSTANCE : TopicFragment$2; INVOKESTATIC SequencesKt.map (LSequence;Function1;) INVOKESTATIC SequencesKt.toList (LSequence;)List; Mitchell Tilbook @sir_tilbrook youtube.com/c/anzcoders
  • 35. INVOKESTATIC ArraysKt.asSequence ([I)LSequence; GETSTATIC TopicFragment$1.INSTANCE : TopicFragment$1; INVOKESTATIC SequencesKt.filter (LSequence;Function1;) GETSTATIC TopicFragment$2.INSTANCE : TopicFragment$2; INVOKESTATIC SequencesKt.map (LSequence;Function1;) INVOKESTATIC SequencesKt.toList (LSequence;)List; Mitchell Tilbook @sir_tilbrook youtube.com/c/anzcoders
  • 36. INVOKESTATIC ArraysKt.asSequence ([I)LSequence; GETSTATIC TopicFragment$1.INSTANCE : TopicFragment$1; INVOKESTATIC SequencesKt.filter (LSequence;Function1;) GETSTATIC TopicFragment$2.INSTANCE : TopicFragment$2; INVOKESTATIC SequencesKt.map (LSequence;Function1;) INVOKESTATIC SequencesKt.toList (LSequence;)List; Mitchell Tilbook @sir_tilbrook youtube.com/c/anzcoders
  • 37. INVOKESTATIC ArraysKt.asSequence ([I)LSequence; GETSTATIC TopicFragment$1.INSTANCE : TopicFragment$1; INVOKESTATIC SequencesKt.filter (LSequence;Function1;) GETSTATIC TopicFragment$2.INSTANCE : TopicFragment$2; INVOKESTATIC SequencesKt.map (LSequence;Function1;) INVOKESTATIC SequencesKt.toList (LSequence;)List; Mitchell Tilbook @sir_tilbrook youtube.com/c/anzcoders
  • 38. Data Classes data class Speaker( val description: String, val talks: List<Talk>, val profile: String ) Mitchell Tilbook @sir_tilbrook youtube.com/c/anzcoders
  • 39. De-structure data class val speaker = Speaker( talks = arrayListOf(), description = "Bytecode", profile = "" ) val (description, talks) = speaker Mitchell Tilbook @sir_tilbrook youtube.com/c/anzcoders
  • 40. public final component1()String; @NotNull;() // invisible ALOAD 0 GETFIELD Speaker.description : String; ARETURN // signature ()LList<LTalk;>; // declaration: java.util.List<Talk> component2() public final component2()LList; @NotNull;() // invisible ALOAD 0 GETFIELD Speaker.talks : LList; ARETURN Mitchell Tilbook @sir_tilbrook youtube.com/c/anzcoders
  • 41. // signature … // declaration: Speaker copy(java.lang.String, java.util.List<? extends Talk>) public final copy(String;LList;)LSpeaker; @NotNull;() // invisible @NotNull;() // invisible, parameter 0 @NotNull;() // invisible, parameter 1 INVOKESTATIC checkParameterIsNotNull (Object;String;)V INVOKESTATIC checkParameterIsNotNull (Object;String;)V NEW Speaker INVOKESPECIAL Speaker.<init> (String;LList;)V ARETURN Mitchell Tilbook @sir_tilbrook youtube.com/c/anzcoders
  • 42. val speaker2 = speaker.copy( description = "Second speaker" ) Mitchell Tilbook @sir_tilbrook youtube.com/c/anzcoders
  • 43. public static synthetic bridge copy$default(LSpeaker;String;LList;IObject;)LSpeaker; @NotNull;() // invisible ILOAD 3 ICONST_1 IAND IFEQ L0 ALOAD 0 GETFIELD Speaker.description : String; ASTORE 1 L0 ILOAD 3 ICONST_2 IAND IFEQ L1 ALOAD 0 GETFIELD Speaker.talks : LList; ASTORE 2 L1 ALOAD 0 ALOAD 1 ALOAD 2 INVOKEVIRTUAL Speaker.copy (String;LList;)LSpeaker; ARETURN Mitchell Tilbook @sir_tilbrook youtube.com/c/anzcoders
  • 44. public static Speaker copy$default( Speaker var0, String var1, List var2, String var3, int var4, Object var5 ) { if ((var4 & 1) != 0) { var1 = var0.description; } if ((var4 & 2) != 0) { var2 = var0.talks; } if ((var4 & 4) != 0) { var3 = var0.profile; } return var0.copy(var1, var2, var3); } Mitchell Tilbook @sir_tilbrook youtube.com/c/anzcoders
  • 45. Lambdas — SAM (Single Access Method) — Non-Capturing Lambdas — Capturing Lambdas Mitchell Tilbook @sir_tilbrook youtube.com/c/anzcoders
  • 47. SAMs final class Sam$1 implements View$OnClickListener { public final onClick(Landroid/view/View;)V LDC "Hello" INVOKEVIRTUAL PrintStream.print (Object;)V RETURN <init>()V INVOKESPECIAL Object.<init> ()V RETURN public final static Sam$1; INSTANCE static <clinit>()V NEW Sam$1 DUP INVOKESPECIAL Sam$1.<init> ()V PUTSTATIC Sam$1.INSTANCE : Sam$1; RETURN Mitchell Tilbook @sir_tilbrook youtube.com/c/anzcoders
  • 48. class Lmd { private val lambda = { "I'm a lambda" } } Mitchell Tilbook @sir_tilbrook youtube.com/c/anzcoders
  • 49. public final class Lmd { // signature Function0<String;>; // declaration: Function0<java.lang.String> private final Function0; lambda public <init>()V // … ALOAD 0 GETSTATIC Lmd$lambda$1.INSTANCE : Lmd$lambda$1; CHECKCAST Function0 PUTFIELD Lmd.lambda : Function0; RETURN } Mitchell Tilbook @sir_tilbrook youtube.com/c/anzcoders
  • 50. final class Lmd$lambda$1 extends Lambda implements Function0 { <init>()V INVOKESPECIAL Lambda.<init> (I)V RETURN public final static Lmd$lambda$1; INSTANCE static <clinit>()V NEW Lmd$lambda$1 DUP INVOKESPECIAL Lmd$lambda$1.<init> ()V PUTSTATIC Lmd$lambda$1.INSTANCE : Lmd$lambda$1; RETURN } Mitchell Tilbook @sir_tilbrook youtube.com/c/anzcoders
  • 51. public synthetic bridge invoke()Object; L0 LINENUMBER 3 L0 ALOAD 0 INVOKEVIRTUAL Lmd$lambda$1.invoke ()String; ARETURN // access flags 0x11 public final invoke()String; @NotNull;() // invisible L0 LINENUMBER 5 L0 LDC "I'm a lambda" L1 ARETURN Mitchell Tilbook @sir_tilbrook youtube.com/c/anzcoders
  • 52. class Lmd { private val lambda = { "I'm a lambda" } val value = lambda() } Mitchell Tilbook @sir_tilbrook youtube.com/c/anzcoders
  • 53. public final class Lmd { public <init>()V … ALOAD 0 GETFIELD Lmd.lambda : Function0; INVOKEINTERFACE Function0.invoke ()Object; CHECKCAST String } final class public Lmd$lambda$1 { public synthetic bridge invoke()Object; Lmd$lambda$1.invoke ()String; } Mitchell Tilbook @sir_tilbrook youtube.com/c/anzcoders
  • 54. Lambda s and Field class Lmd ( private val speaker: Speaker ) { private val lambda = { speaker.name } } Mitchell Tilbook @sir_tilbrook youtube.com/c/anzcoders
  • 55. final class Lmd$lambda$1 { final synthetic Lmd; this$0 public final invoke()String; @NotNull;() // invisible GETFIELD Lmd$lambda$1.this$0 : Lmd; INVOKESTATIC Lmd.access$getSpeaker$p (Lmd;)LSpeaker; INVOKEVIRTUAL Speaker.getName ()String; ARETURN <init>(Lmd;)V PUTFIELD Lmd$lambda$1.this$0 : Lmd; INVOKESPECIAL Lambda.<init> (I)V RETURN } Mitchell Tilbook @sir_tilbrook youtube.com/c/anzcoders
  • 56. final class Lmd$lambda$1 { final synthetic Lmd; this$0 public final invoke()String; @NotNull;() // invisible GETFIELD Lmd$lambda$1.this$0 : Lmd; INVOKESTATIC Lmd.access$getSpeaker$p (Lmd;)LSpeaker; INVOKEVIRTUAL Speaker.getName ()String; ARETURN <init>(Lmd;)V PUTFIELD Lmd$lambda$1.this$0 : Lmd; INVOKESPECIAL Lambda.<init> (I)V RETURN } Mitchell Tilbook @sir_tilbrook youtube.com/c/anzcoders
  • 57. public final class Lmd { public final static synthetic access$getSpeaker$p(Lmd;)Speaker; @NotNull;() // invisible ALOAD 0 GETFIELD Lmd.speaker : Speaker; ARETURN } Mitchell Tilbook @sir_tilbrook youtube.com/c/anzcoders
  • 58. class Lmd ( @JvmField protected private val speaker: Speaker ){ private val lambda = { speaker.name } } Mitchell Tilbook @sir_tilbrook youtube.com/c/anzcoders
  • 59. class Lmd ( @Suppress("WARNINGS") @JvmField protected private val speaker: Speaker = Speaker("speaker") ){ private val lambda = { speaker.name } } Mitchell Tilbook @sir_tilbrook youtube.com/c/anzcoders
  • 60. final class Lmd$lambda$1 { public final invoke()String; GETFIELD Lmd$lambda$1.this$0 : LLmd; GETFIELD Lmd.speaker : LSpeaker; INVOKEVIRTUAL Speaker.getName ()String; ARETURNdas.lambda : Function0; RETURN } Mitchell Tilbook @sir_tilbrook youtube.com/c/anzcoders
  • 61. File values and functions Mitchell Tilbook @sir_tilbrook youtube.com/c/anzcoders
  • 62. // file name Objects private val speaker = Speaker() public final class ObjectsKt { private final static Speaker; speaker static <clinit>()V NEW Speaker DUP INVOKESPECIAL Speaker.<init> ()V PUTSTATIC ObjectsKt.speaker : LSpeaker; RETURN } Mitchell Tilbook @sir_tilbrook youtube.com/c/anzcoders
  • 63. // file name Objects private val speaker = Speaker() public final class ObjectsKt { private final static Speaker; speaker static <clinit>()V NEW Speaker DUP INVOKESPECIAL Speaker.<init> ()V PUTSTATIC ObjectsKt.speaker : LSpeaker; RETURN } Mitchell Tilbook @sir_tilbrook youtube.com/c/anzcoders
  • 64. fun someStr() = "Some String" // Becomes public final class ObjectsKt { public final static someStr() String; @NotNull;() // invisible LDC "Some String" ARETURN } Mitchell Tilbook @sir_tilbrook youtube.com/c/anzcoders
  • 65. private val someStr = "Some String" Mitchell Tilbook @sir_tilbrook youtube.com/c/anzcoders
  • 66. public final class ObjectsKt { private final static String; someStr = "Some String" static <clinit>()V LDC "Some String" PUTSTATIC ObjectsKt.someStr : String; RETURN } Mitchell Tilbook @sir_tilbrook youtube.com/c/anzcoders
  • 67. private const val someStr = "Some String" Mitchell Tilbook @sir_tilbrook youtube.com/c/anzcoders
  • 68. public final class ObjectsKt { private final static String; someStr = "Some String" } Mitchell Tilbook @sir_tilbrook youtube.com/c/anzcoders
  • 69. Objects object AnObject Mitchell Tilbook @sir_tilbrook youtube.com/c/anzcoders
  • 70. public final class AnObject { public final static AnObject; INSTANCE private <init>()V INVOKESPECIAL Object.<init> ()V RETURN static <clinit>()V NEW AnObject DUP INVOKESPECIAL AnObject.<init> ()V PUTSTATIC AnObject.INSTANCE : AnObject; RETURN } Mitchell Tilbook @sir_tilbrook youtube.com/c/anzcoders
  • 71. object AnObject { val name = "Mitchell" } Mitchell Tilbook @sir_tilbrook youtube.com/c/anzcoders
  • 72. public final class AnObject { private final static String; name = "Mitchell" @NotNull;() // invisible public final getName()String; @NotNull;() // invisible GETSTATIC AnObject.name : String; ARETURN static <clinit>()V LDC "Mitchell" PUTSTATIC AnObject.name : String; RETURN } Mitchell Tilbook @sir_tilbrook youtube.com/c/anzcoders
  • 73. object AnObject { const val name = "Mitchell" } Mitchell Tilbook @sir_tilbrook youtube.com/c/anzcoders
  • 74. public final class AnObject { public final static String; name = "Mitchell" public final static LAnObject; INSTANCE private <init>()V INVOKESPECIAL Object.<init> ()V RETURN static <clinit>()V NEW AnObject DUP INVOKESPECIAL AnObject.<init> ()V PUTSTATIC AnObject.INSTANCE : LAnObject; Mitchell Tilbook @sir_tilbrook youtube.com/c/anzcoders
  • 75. object AnObject { fun speaker() = Speaker() } Mitchell Tilbook @sir_tilbrook youtube.com/c/anzcoders
  • 76. public final class AnObject { public final speaker() Speaker; @NotNull;() // invisible NEW Speaker DUP INVOKESPECIAL Speaker.<init> ()V ARETURN Mitchell Tilbook @sir_tilbrook youtube.com/c/anzcoders
  • 77. object AnObject { @JvmStatic fun speaker() = Speaker() } // With @JvmStatic public final class AnObject { public final static speaker() Speaker; @JvmStatic;() @NotNull;() // invisible } Mitchell Tilbook @sir_tilbrook youtube.com/c/anzcoders
  • 78. Companion Object Mitchell Tilbook @sir_tilbrook youtube.com/c/anzcoders
  • 79. class TopicFragment { companion object { } } Mitchell Tilbook @sir_tilbrook youtube.com/c/anzcoders
  • 80. public final class TopicFragment { public <init>()V static <clinit>()V NEW TopicFragment$Companion DUP ACONST_NULL INVOKESPECIAL TopicFragment$Companion.<init> ( DefaultConstructorMarker; )V PUTSTATIC TopicFragment.Companion : TopicFragment$Companion; RETURN public final static TopicFragment$Companion; Companion public final static INNERCLASS TopicFragment$Companion TopicFragment Companion } Mitchell Tilbook @sir_tilbrook youtube.com/c/anzcoders
  • 81. public final class TopicFragment$Companion { private <init>()V INVOKESPECIAL Object.<init> ()V RETURN public synthetic <init>(DefaultConstructorMarker;)V INVOKESPECIAL TopicFragment$Companion.<init> ()V RETURN public final static INNERCLASS TopicFragment$Companion TopicFragment Companion } Mitchell Tilbook @sir_tilbrook youtube.com/c/anzcoders
  • 82. class TopicFragment { companion object { val EXTRA_TOPIC_ID = "EXTRA_TOPIC_ID" } } Mitchell Tilbook @sir_tilbrook youtube.com/c/anzcoders
  • 83. class TopicFragment { init { EXTRA_TOPIC_ID } companion object { val EXTRA_TOPIC_ID = "EXTRA_TOPIC_ID" } } Mitchell Tilbook @sir_tilbrook youtube.com/c/anzcoders
  • 84. public final class TopicFragment { private final static String; EXTRA_TOPIC_ID = "EXTRA_TOPIC_ID" static <clinit>()V NEW TopicFragment$Companion … LDC "EXTRA_TOPIC_ID" PUTSTATIC TopicFragment .EXTRA_TOPIC_ID : String; RETURN } Mitchell Tilbook @sir_tilbrook youtube.com/c/anzcoders
  • 85. public final class TopicFragment { public <init>()V GETSTATIC Companion : $Companion; INVOKEVIRTUAL $Companion .getEXTRA_TOPIC_ID ()String; POP … } Mitchell Tilbook @sir_tilbrook youtube.com/c/anzcoders
  • 86. public final class TopicFragment$Companion { public final getEXTRA_TOPIC_ID()String; @NotNull;() // invisible L0 LINENUMBER 11 L0 INVOKESTATIC TopicFragment.access$getEXTRA_TOPIC_ID$cp ()String; ARETURN } public final class TopicFragment { public final static synthetic access$getEXTRA_TOPIC_ID$cp()String; @NotNull;() // invisible GETSTATIC TopicFragment.EXTRA_TOPIC_ID : String; ARETURN Mitchell Tilbook @sir_tilbrook youtube.com/c/anzcoders
  • 88. class TopicFragment { init { EXTRA_TOPIC_ID } companion object { const val EXTRA_TOPIC_ID = "EXTRA_TOPIC_ID" } } Mitchell Tilbook @sir_tilbrook youtube.com/c/anzcoders
  • 89. public final class TopicFragment { public <init>()V INVOKESPECIAL Object.<init> ()V // Now all we get is metadata LINENUMBER 6 L1 RETURN public final static String; EXTRA_TOPIC_ID = "EXTRA_TOPIC_ID" @NotNull;() // invisible Mitchell Tilbook @sir_tilbrook youtube.com/c/anzcoders
  • 90. package io.github.droidkaigi.confsched2018.data.api.response.mapper class LocalDateTimeAdapter : JsonAdapter<LocalDateTime>() { companion object { private val FORMATTER: DateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss") fun parseDateString(dateString: String?): LocalDateTime = LocalDateTime.parse(dateString, FORMATTER) } } Mitchell Tilbook @sir_tilbrook youtube.com/c/anzcoders
  • 91. private object FormatCompanion { @JvmField val FORMATTER: DateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss") } class LocalDateTimeAdapter : JsonAdapter<LocalDateTime>() { … companion object { fun parseDateString(dateString: String?): LocalDateTime = LocalDateTime.parse(dateString, FORMATTER) } } Mitchell Tilbook @sir_tilbrook youtube.com/c/anzcoders
  • 92. /* package private */ final class FormatCompanion { public final static DateTimeFormatter; FORMATTER } Mitchell Tilbook @sir_tilbrook youtube.com/c/anzcoders
  • 93. class TopicFragment { companion object { private const val EXTRA_TOPIC_ID = "EXTRA_TOPIC_ID" fun newInstance(topicId: Int) { } } } Mitchell Tilbook @sir_tilbrook youtube.com/c/anzcoders
  • 94. Reducing Synthetic Methods class TopicDetailViewModel @Inject constructor( private val repository: SessionRepository, private val schedulerProvider: SchedulerProvider ) : ViewModel(), LifecycleObserver { var topicId: Int = 0 val topicSessions: LiveDataSessions by lazy { repository.topicSessions .map { it .filter { it.key.id == topicId } .map { it.key to it.value } .first() } .toResult(schedulerProvider) .toLiveData() } Mitchell Tilbook @sir_tilbrook youtube.com/c/anzcoders
  • 95. public final class TopicDetailViewModel extends android/arch/lifecycle/ViewModel implements android/arch/lifecycle/LifecycleObserver { public final static synthetic access$getRepository $p(LTopicDetailViewModel;)SessionRepository; @NotNull;() // invisible L0 LINENUMBER 20 L0 ALOAD 0 GETFIELD TopicDetailViewModel.repository : SessionRepository; ARETURN public final static synthetic access$getSchedulerProvider $p(LTopicDetailViewModel;)SchedulerProvider; @NotNull;() // invisible L0 LINENUMBER 20 L0 ALOAD 0 GETFIELD TopicDetailViewModel.schedulerProvider : SchedulerProvider; ARETURN Mitchell Tilbook @sir_tilbrook youtube.com/c/anzcoders
  • 96. class TopicDetailViewModel @Inject constructor( private val repository: SessionRepository, private val schedulerProvider: SchedulerProvider ) : ViewModel(), LifecycleObserver { var topicId: Int = 0 val topicSessions: LiveDataSessions by lazy { repository.topicSessions .map { it .filter { it.key.id == topicId } .map { it.key to it.value } .first() } .toResult(schedulerProvider) .toLiveData() } Mitchell Tilbook @sir_tilbrook youtube.com/c/anzcoders
  • 97. class TopicDetailViewModel @Inject constructor( @JvmField protected val repository: SessionRepository, @JvmField protected val schedulerProvider: SchedulerProvider ) Mitchell Tilbook @sir_tilbrook youtube.com/c/anzcoders
  • 98. // protected is effectively private in final classes class TopicDetailViewModel @Inject @Suppress("warnings") constructor( @JvmField protected val repository: SessionRepository, @JvmField protected val schedulerProvider: SchedulerProvider ) Mitchell Tilbook @sir_tilbrook youtube.com/c/anzcoders
  • 99. Mitchell Tilbrook @sir_tilbrook Sydney Tech Talks youtube.com/c/anzcoders Moneytree Android Developer moneytree.jp Mitchell Tilbook @sir_tilbrook youtube.com/c/anzcoders