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