Kotlin. Decompiled.
Who am I?
• Klymenko Ruslan
• Software engineer at ‘zorallabs’
• Passionate about JVM
• Ternopil JUG co-founder
• Founder of ‘Dobroe IT’
Who knows about kotlin?
Who have worked with
kotlin?
Who use kotlin in everyday
practice?
So… What is Kotlin?
• Modern
• Jvm-based (not only! =) )
• Statically-typed
And… Why Kotlin?
Interoperability. Kotlin is same as java. It also
produces bytecode.
But… Wait a minute. What is bytecode?
What are mnemonics?
What is decompilation?
• The reverse process of compilation.
• Takes executable code as input.
• Produces high-level code as output.
What is this talk about?
• We’re going to decompile Kotlin code to Java analogue.
• It will give a better understanding of what’s going on under the hood.
What is this talk about?
• It will give a feeling when Kotlin is an appropriate solution which
minimizes boilerplate.
• It will show Kotlin’s weak points(if there any)
So… Let’s start from the beginning!
fun main(args: Array<String>) {
println("Hey, folks!")
} ????
Hello, world!
@Metadata(
mv = {1, 1, 9},
bv = {1, 0, 2},
k = 2,
d1 = {"u0000u0014nu0000n...."},
d2 = {"main", "", "args", "", "", …}
)
public final class Test1Kt {
public static final void main(@NotNull String[] args) {
Intrinsics.checkParameterIsNotNull(args, "args");
String var1 = "Hey, folks!";
System.out.println(var1);
}
}
What’s wrong here?
object Test {
fun main(args: Array<String>) {
}
}
What’s wrong here?
public final class Test {
public static final Test INSTANCE;
public final void main(@NotNull String[] args) {
Intrinsics.checkParameterIsNotNull(args, "args");
}
static {
Test var0 = new Test();
INSTANCE = var0;
}
}
@JvmStatic
object Test {
@JvmStatic
fun main(args: Array<String>) {
}
}
Extension methods or how to add functionality
even to final types in a natural way.
fun String.isTest() =
this == "test"
????
Extension methods or how to add functionality
even to final types in a natural way.
public final class Test2Kt {
public static final boolean isTest(@NotNull String
$receiver) {
Intrinsics.checkParameterIsNotNull($receiver,
"$receiver");
return Intrinsics.areEqual($receiver, "test");
}
}
Extension methods from client’s point of
view
fun testExtension() {
"".isTest()
}
Extension methods from client’s point of
view
public static final void testExtension() {
isTest("");
}
The simplest class ever. But wait.
What’s wrong here?
class Test3(test: String)
????
The simplest class ever.
public final class Test3 {
public Test3(@NotNull String test) {
Intrinsics.checkParameterIsNotNull(test, "test");
}
}
The simplest bean ever. The correct one
class Test4(val test: String)
The simplest bean ever. The correct one
public final class Test4 {
@NotNull
private final String test;
@NotNull
public final String getTest() {
return this.test;
}
public Test4(@NotNull String test) {
Intrinsics.checkParameterIsNotNull(test, "test");
this.test = test;
}
}
The simplest bean ever. The correct one
class Test4(var test: String) ????
The simplest bean ever + DEFAULT arg
class Test4(val test: String = "")
The simplest bean ever + DEFAULT arg
public final class Test4 {
…
// $FF: synthetic method
public Test4(String var1, int var2,DefaultConstructorMarker var3) {
if ((var2 & 1) != 0) {
var1 = "";
}
this(var1);
}
public Test4(@NotNull String test) {
...
this.test = test;
}
public Test4() {
this((String)null, 1, (DefaultConstructorMarker)null);
}
}
Default constructor args. Call from java code.
class Test4(val test: String = "")
void test() {
new Test4("test");
new Test4();
}
Default method args. Call from java code.
class Test5 {
fun x(x: Int = 5) { }
}
Default method args. Call from java code.
class Test5 {
fun x(x: Int = 5) { }
}
void test() {
new Test5().x();
}
Default method args. Call from java code.
class Test5 {
fun x(x: Int = 5) { }
}
void test() {
new Test5().x();
}
Default method args. Call from java code.
public final class Test5 {
public final void x(int x) {
}
public static void x$default(Test5 var0,
int var1,
int var2,
Object var3) {
if ((var2 & 1) != 0) {
var1 = 5;
}
var0.x(var1);
}
}
Default method args. Correct call from java
code.
void test() {
new Test5().x();
}
class Test5 {
@JvmOverloads
fun x(x: Int = 5) { }
}
Give me more DATA!!!
data class Test6(val x: Int = 0, val y: Int = 0)
Give me more DATA!!!
public final class Test6 {
private final int x; private final int y;
// + getX(), getY(), constructor with both parameters
// + toString(), hashCode(), equals(Object obj)
public final int component1() {
return this.x;
}
public final int component2() {
return this.y;
}
@NotNull
public final Test6 copy(int x, int y) {
return new Test6(x, y);
}
}
Destructurization
fun test() {
val (a,b,c) = Test6()
}
public final void test() {
Test6 var4 = new Test6(0, 0, (Test4)null, 7,
DefaultConstructorMarker)null);
int var1 = var4.component1();
int var2 = var4.component2();
Test4 c = var4.component3();
}
Let my Kotlin go
fun test7() = Any().let {
it.toString()
this.toString()
}
Let my Kotlin go
public final String test7() {
Object var1 = new Object();
var1.toString();
return this.toString();
}
Let’s think about it
????fun test() = null.let { println(it) }
Let’s think about it
public static final void test() {
Object var0 = null;
Void it = (Void)var0;
System.out.println(it);
}
The power of primitives
fun test() = 1
public final int test () {
return 1;
}
The power of primitives
fun test(): Int {
val x: Int = 1
return x
}
public final int test() {
int x = 1;
return x;
}
The power of primitives
fun test(): Int {
val x: Int = 1
x.toString()
x.compareTo(2)
x.hashCode()
return x
}
????
The power of primitives
fun test(): Int {
val x: Int = 1
x.toString()
x.compareTo(2)
x.hashCode()
return x
}
public final int test() {
int x = 1;
String.valueOf(x);
Intrinsics.compare(x, 2);
Integer.valueOf(x).hashCode();
return x;
}
Nullable types
fun test(value: Int?) {
val test1 = value ?: 0
}
????
Nullable types
public static final void test(@Nullable Integer value)
{
int test1 = value != null ? value.intValue() : 0;
}
Nullable types
fun test(value: Int?) {
val test1 = value!!
}
????
Nullable types
public static final void test(@Nullable Integer
value) {
if (value == null) {
Intrinsics.throwNpe();
}
int test1 = value.intValue();
}
Cast me babe
val x = Any() is String
val y: Any = 1
val z: Int = y as Int
Cast me babe
private static final boolean x =
new Object() instanceof String;
@NotNull
private static final Object y = Integer.valueOf(1);
private static final int z = 1;
Cast me babe. And please, be smart!
fun test() {
val any = "test" as Any
if(any is String) {
any.trim()
any.substringBefore("test")
}
}
Cast me babe. And please, be smart!
public static final void test() {
Object any = (Object)"test";
String var1 = (String)any;
StringsKt.trim((CharSequence)var1).toString();
StringsKt.substringBefore$default((String)any, "test",
(String)null, 2,
(Object)null);
}
When
fun test(x: Any) {
when(x) {
0 -> println(0)
is Int -> println("Int")
is Number -> println("Number")
else -> println("Not an int")
}
}
????
When
public static final void test(@NotNull Object x) {
Intrinsics.checkParameterIsNotNull(x, "x");
if (Intrinsics.areEqual(x, Integer.valueOf(0))) {
byte var2 = 0;
System.out.println(var2);
} else {
String var3;
if (x instanceof Integer) {
var3 = "Int";
System.out.println(var3);
} else if (x instanceof Number) {
var3 = "Number";
System.out.println(var3);
} else {
var3 = "Not an int";
System.out.println(var3);
}
}
}
Where is my ternary?
fun test (value: Int) = value == 1 ? 1 : 0
public static final int test (int value) {
return value == 1 ? 1 : 0;
}
Where is my ternary?
fun test (value: Int) = if(value == 1) 1 else 0
Range
public final class Test14Kt {
@NotNull
private static final IntRange range;
@NotNull
public static final IntRange
getRange() {
return range;
}
static {
byte var0 = 1;
range = new IntRange(var0, 100);
}
}
val range = 1 .. 100
Range
????val result = 50 in 1..100
Range
public final class Test14Kt {
private static final boolean result = true;
public static final boolean getResult() {
return result;
}
}
Range
fun test14(){
for(x in 1 .. 100) { }
}
Range
public static final void test14() {
int var0 = 1;
for(byte var1 = 101; var0 < var1; ++var0) {
;
}
}
Range
fun test14(){
for(x in 1 .. 100 step 1) { }
}
Range
public static final void test14() {
byte var3 = 1;
IntProgression var10000 =
RangesKt.step(
(IntProgression)(new IntRange(var3, 100)), 1);
int x = var10000.getFirst();
int var1 = var10000.getLast();
int var2 = var10000.getStep();
if (var2 > 0) {
if (x > var1) {
return;
}
} else if (x < var1) {
return;
}
while(x != var1) {
x += var2;
}
}
Inlines
fun test15() {
println(test15_1 { it * 2 })
}
fun test15_1(num: (Int) -> Int) = num(2)
Inlines
public static final void test15() {
int var0 = test15_1((Function1)null.INSTANCE);
System.out.println(var0);
}
public static final int test15_1(@NotNull Function1 num)
{
Intrinsics.checkParameterIsNotNull(num, "num");
return ((Number)num.invoke(2)).intValue();
}
Inlines
fun test15() {
println(test15_1 { it * 2 })
}
inline fun test15_1(num: (Int) -> Int) = num(2)
Inlines
public static final void test15() {
int it = 2;
int var3 = it * 2;
System.out.println(var3);
}
public static final int test15_1(@NotNull Function1 num)
{
Intrinsics.checkParameterIsNotNull(num, "num");
return ((Number)num.invoke(2)).intValue();
}
Inlines. Noinline
fun test15() {
println(test15_1({ it + 1 }, { it * 2 }))
}
inline fun test15_1(num: (Int) -> Int, noinline num2:
(Int) -> Int)
= num(1) + num2(1)
Inlines. Noinline
public static final void test15() {
Function1 num2$iv = (Function1)null.INSTANCE;
int it = 1;
int var4 = it + 1 +
((Number)num2$iv.invoke(1)).intValue();
System.out.println(var4);
}
public static final int test15_1(@NotNull Function1 num,
@NotNull Function1 num2) {
Intrinsics.checkParameterIsNotNull(num, "num");
Intrinsics.checkParameterIsNotNull(num2, "num2");
return ((Number)num.invoke(1)).intValue() +
((Number)num2.invoke(1)).intValue();
}
Overloading with generics
public void sort(List<String> x) {}
public void sort(List<Integer> x) {}
Overloading with generics
fun sort(x: List<Any>) {}
fun sort(x: List<Int>) {}
Overloading with generics
fun sort(x: List<Any>) {}
@JvmName("sortInt")
fun sort(x: List<Int>) {}
Overloading of operators
class IntArray(val data: Array<Int>) {
operator fun plus(value: Int) = data + value
fun test() {
val intArr = IntArray(arrayOf(1))
val newArr = intArr + 2
}
}
Overloading of operators
public final class IntArray {
@NotNull
private final Integer[] data;
@NotNull
public final Integer[] plus(int value) {
return (Integer[])ArraysKt.plus((Object[])this.data, value);
}
public final void test() {
IntArray intArr = new IntArray(new Integer[]{Integer.valueOf(1)});
Integer[] newArr = intArr.plus(2);
}
@NotNull
public final Integer[] getData() {
return this.data;
}
public IntArray(@NotNull Integer[] data) {
Intrinsics.checkParameterIsNotNull(data, "data");
super();
this.data = data;
}
}
Delegation using ‘by’
interface Interf {
fun xx(): Int
}
class A: Interf {
override fun xx() = 1
}
class B(a: A): Interf by a
????
Delegation using ‘by’
public interface Interf { int xx();}
public final class A implements Interf { public int xx() { return 1; }}
public final class B implements Interf {
private final A $$delegate_0;
public B(@NotNull A a) {
Intrinsics.checkParameterIsNotNull(a, "a");
super();
this.$$delegate_0 = a;
}
public int xx() {
return this.$$delegate_0.xx();
}
Recursion
fun factorial(value: Int): Int =
if(value <= 1) 1
else value * factorial(value -1)
Recursion
public static final int factorial(int value) {
return value <= 1 ?
1 :
value * factorial(value - 1);
}
Tail recursion
????tailrec fun factorial(value: Int)
: Int =
if(value <= 1) 1
else value * factorial(value -1)
Tail recursion
public static final int factorial(int value) {
return value <= 1 ?
1 :
value * factorial(value - 1);
}
Tail recursion
tailrec fun factorial(value: Int, acc: Int): Int =
if(value <= 1) acc * value
else factorial(value - 1, acc * value)
Tail recursion
public static final int factorial(int value, int acc) {
while(value > 1) {
int var10000 = value - 1;
acc *= value;
value = var10000;
}
return acc * value;
}
Cons of Kotlin
• Learning curve
• Slow compilation speed
• Smaller community with
comparison to java
Pros of Kotlin
• Reduces boilerplate
• Compatible with jvm
• Competitive performance
• Elegant
• Best IDE integration
• Choice №1 for android
Finish
Kotlin decompiled

Kotlin decompiled

  • 1.
  • 2.
    Who am I? •Klymenko Ruslan • Software engineer at ‘zorallabs’ • Passionate about JVM • Ternopil JUG co-founder • Founder of ‘Dobroe IT’
  • 3.
  • 4.
    Who have workedwith kotlin?
  • 5.
    Who use kotlinin everyday practice?
  • 6.
    So… What isKotlin? • Modern • Jvm-based (not only! =) ) • Statically-typed
  • 7.
  • 8.
    Interoperability. Kotlin issame as java. It also produces bytecode.
  • 9.
    But… Wait aminute. What is bytecode?
  • 10.
  • 11.
    What is decompilation? •The reverse process of compilation. • Takes executable code as input. • Produces high-level code as output.
  • 12.
    What is thistalk about? • We’re going to decompile Kotlin code to Java analogue. • It will give a better understanding of what’s going on under the hood.
  • 13.
    What is thistalk about? • It will give a feeling when Kotlin is an appropriate solution which minimizes boilerplate. • It will show Kotlin’s weak points(if there any)
  • 14.
    So… Let’s startfrom the beginning! fun main(args: Array<String>) { println("Hey, folks!") } ????
  • 15.
    Hello, world! @Metadata( mv ={1, 1, 9}, bv = {1, 0, 2}, k = 2, d1 = {"u0000u0014nu0000n...."}, d2 = {"main", "", "args", "", "", …} ) public final class Test1Kt { public static final void main(@NotNull String[] args) { Intrinsics.checkParameterIsNotNull(args, "args"); String var1 = "Hey, folks!"; System.out.println(var1); } }
  • 16.
    What’s wrong here? objectTest { fun main(args: Array<String>) { } }
  • 17.
    What’s wrong here? publicfinal class Test { public static final Test INSTANCE; public final void main(@NotNull String[] args) { Intrinsics.checkParameterIsNotNull(args, "args"); } static { Test var0 = new Test(); INSTANCE = var0; } }
  • 18.
    @JvmStatic object Test { @JvmStatic funmain(args: Array<String>) { } }
  • 19.
    Extension methods orhow to add functionality even to final types in a natural way. fun String.isTest() = this == "test" ????
  • 20.
    Extension methods orhow to add functionality even to final types in a natural way. public final class Test2Kt { public static final boolean isTest(@NotNull String $receiver) { Intrinsics.checkParameterIsNotNull($receiver, "$receiver"); return Intrinsics.areEqual($receiver, "test"); } }
  • 21.
    Extension methods fromclient’s point of view fun testExtension() { "".isTest() }
  • 22.
    Extension methods fromclient’s point of view public static final void testExtension() { isTest(""); }
  • 23.
    The simplest classever. But wait. What’s wrong here? class Test3(test: String) ????
  • 24.
    The simplest classever. public final class Test3 { public Test3(@NotNull String test) { Intrinsics.checkParameterIsNotNull(test, "test"); } }
  • 25.
    The simplest beanever. The correct one class Test4(val test: String)
  • 26.
    The simplest beanever. The correct one public final class Test4 { @NotNull private final String test; @NotNull public final String getTest() { return this.test; } public Test4(@NotNull String test) { Intrinsics.checkParameterIsNotNull(test, "test"); this.test = test; } }
  • 27.
    The simplest beanever. The correct one class Test4(var test: String) ????
  • 28.
    The simplest beanever + DEFAULT arg class Test4(val test: String = "")
  • 29.
    The simplest beanever + DEFAULT arg public final class Test4 { … // $FF: synthetic method public Test4(String var1, int var2,DefaultConstructorMarker var3) { if ((var2 & 1) != 0) { var1 = ""; } this(var1); } public Test4(@NotNull String test) { ... this.test = test; } public Test4() { this((String)null, 1, (DefaultConstructorMarker)null); } }
  • 30.
    Default constructor args.Call from java code. class Test4(val test: String = "") void test() { new Test4("test"); new Test4(); }
  • 31.
    Default method args.Call from java code. class Test5 { fun x(x: Int = 5) { } }
  • 32.
    Default method args.Call from java code. class Test5 { fun x(x: Int = 5) { } } void test() { new Test5().x(); }
  • 33.
    Default method args.Call from java code. class Test5 { fun x(x: Int = 5) { } } void test() { new Test5().x(); }
  • 34.
    Default method args.Call from java code. public final class Test5 { public final void x(int x) { } public static void x$default(Test5 var0, int var1, int var2, Object var3) { if ((var2 & 1) != 0) { var1 = 5; } var0.x(var1); } }
  • 35.
    Default method args.Correct call from java code. void test() { new Test5().x(); } class Test5 { @JvmOverloads fun x(x: Int = 5) { } }
  • 36.
    Give me moreDATA!!! data class Test6(val x: Int = 0, val y: Int = 0)
  • 37.
    Give me moreDATA!!! public final class Test6 { private final int x; private final int y; // + getX(), getY(), constructor with both parameters // + toString(), hashCode(), equals(Object obj) public final int component1() { return this.x; } public final int component2() { return this.y; } @NotNull public final Test6 copy(int x, int y) { return new Test6(x, y); } }
  • 38.
    Destructurization fun test() { val(a,b,c) = Test6() } public final void test() { Test6 var4 = new Test6(0, 0, (Test4)null, 7, DefaultConstructorMarker)null); int var1 = var4.component1(); int var2 = var4.component2(); Test4 c = var4.component3(); }
  • 39.
    Let my Kotlingo fun test7() = Any().let { it.toString() this.toString() }
  • 40.
    Let my Kotlingo public final String test7() { Object var1 = new Object(); var1.toString(); return this.toString(); }
  • 41.
    Let’s think aboutit ????fun test() = null.let { println(it) }
  • 42.
    Let’s think aboutit public static final void test() { Object var0 = null; Void it = (Void)var0; System.out.println(it); }
  • 43.
    The power ofprimitives fun test() = 1 public final int test () { return 1; }
  • 44.
    The power ofprimitives fun test(): Int { val x: Int = 1 return x } public final int test() { int x = 1; return x; }
  • 45.
    The power ofprimitives fun test(): Int { val x: Int = 1 x.toString() x.compareTo(2) x.hashCode() return x } ????
  • 46.
    The power ofprimitives fun test(): Int { val x: Int = 1 x.toString() x.compareTo(2) x.hashCode() return x } public final int test() { int x = 1; String.valueOf(x); Intrinsics.compare(x, 2); Integer.valueOf(x).hashCode(); return x; }
  • 48.
    Nullable types fun test(value:Int?) { val test1 = value ?: 0 } ????
  • 49.
    Nullable types public staticfinal void test(@Nullable Integer value) { int test1 = value != null ? value.intValue() : 0; }
  • 50.
    Nullable types fun test(value:Int?) { val test1 = value!! } ????
  • 51.
    Nullable types public staticfinal void test(@Nullable Integer value) { if (value == null) { Intrinsics.throwNpe(); } int test1 = value.intValue(); }
  • 52.
    Cast me babe valx = Any() is String val y: Any = 1 val z: Int = y as Int
  • 53.
    Cast me babe privatestatic final boolean x = new Object() instanceof String; @NotNull private static final Object y = Integer.valueOf(1); private static final int z = 1;
  • 54.
    Cast me babe.And please, be smart! fun test() { val any = "test" as Any if(any is String) { any.trim() any.substringBefore("test") } }
  • 55.
    Cast me babe.And please, be smart! public static final void test() { Object any = (Object)"test"; String var1 = (String)any; StringsKt.trim((CharSequence)var1).toString(); StringsKt.substringBefore$default((String)any, "test", (String)null, 2, (Object)null); }
  • 56.
    When fun test(x: Any){ when(x) { 0 -> println(0) is Int -> println("Int") is Number -> println("Number") else -> println("Not an int") } } ????
  • 57.
    When public static finalvoid test(@NotNull Object x) { Intrinsics.checkParameterIsNotNull(x, "x"); if (Intrinsics.areEqual(x, Integer.valueOf(0))) { byte var2 = 0; System.out.println(var2); } else { String var3; if (x instanceof Integer) { var3 = "Int"; System.out.println(var3); } else if (x instanceof Number) { var3 = "Number"; System.out.println(var3); } else { var3 = "Not an int"; System.out.println(var3); } } }
  • 58.
    Where is myternary? fun test (value: Int) = value == 1 ? 1 : 0 public static final int test (int value) { return value == 1 ? 1 : 0; }
  • 59.
    Where is myternary? fun test (value: Int) = if(value == 1) 1 else 0
  • 60.
    Range public final classTest14Kt { @NotNull private static final IntRange range; @NotNull public static final IntRange getRange() { return range; } static { byte var0 = 1; range = new IntRange(var0, 100); } } val range = 1 .. 100
  • 61.
  • 62.
    Range public final classTest14Kt { private static final boolean result = true; public static final boolean getResult() { return result; } }
  • 63.
  • 64.
    Range public static finalvoid test14() { int var0 = 1; for(byte var1 = 101; var0 < var1; ++var0) { ; } }
  • 65.
    Range fun test14(){ for(x in1 .. 100 step 1) { } }
  • 66.
    Range public static finalvoid test14() { byte var3 = 1; IntProgression var10000 = RangesKt.step( (IntProgression)(new IntRange(var3, 100)), 1); int x = var10000.getFirst(); int var1 = var10000.getLast(); int var2 = var10000.getStep(); if (var2 > 0) { if (x > var1) { return; } } else if (x < var1) { return; } while(x != var1) { x += var2; } }
  • 67.
    Inlines fun test15() { println(test15_1{ it * 2 }) } fun test15_1(num: (Int) -> Int) = num(2)
  • 68.
    Inlines public static finalvoid test15() { int var0 = test15_1((Function1)null.INSTANCE); System.out.println(var0); } public static final int test15_1(@NotNull Function1 num) { Intrinsics.checkParameterIsNotNull(num, "num"); return ((Number)num.invoke(2)).intValue(); }
  • 69.
    Inlines fun test15() { println(test15_1{ it * 2 }) } inline fun test15_1(num: (Int) -> Int) = num(2)
  • 70.
    Inlines public static finalvoid test15() { int it = 2; int var3 = it * 2; System.out.println(var3); } public static final int test15_1(@NotNull Function1 num) { Intrinsics.checkParameterIsNotNull(num, "num"); return ((Number)num.invoke(2)).intValue(); }
  • 71.
    Inlines. Noinline fun test15(){ println(test15_1({ it + 1 }, { it * 2 })) } inline fun test15_1(num: (Int) -> Int, noinline num2: (Int) -> Int) = num(1) + num2(1)
  • 72.
    Inlines. Noinline public staticfinal void test15() { Function1 num2$iv = (Function1)null.INSTANCE; int it = 1; int var4 = it + 1 + ((Number)num2$iv.invoke(1)).intValue(); System.out.println(var4); } public static final int test15_1(@NotNull Function1 num, @NotNull Function1 num2) { Intrinsics.checkParameterIsNotNull(num, "num"); Intrinsics.checkParameterIsNotNull(num2, "num2"); return ((Number)num.invoke(1)).intValue() + ((Number)num2.invoke(1)).intValue(); }
  • 73.
    Overloading with generics publicvoid sort(List<String> x) {} public void sort(List<Integer> x) {}
  • 74.
    Overloading with generics funsort(x: List<Any>) {} fun sort(x: List<Int>) {}
  • 75.
    Overloading with generics funsort(x: List<Any>) {} @JvmName("sortInt") fun sort(x: List<Int>) {}
  • 76.
    Overloading of operators classIntArray(val data: Array<Int>) { operator fun plus(value: Int) = data + value fun test() { val intArr = IntArray(arrayOf(1)) val newArr = intArr + 2 } }
  • 77.
    Overloading of operators publicfinal class IntArray { @NotNull private final Integer[] data; @NotNull public final Integer[] plus(int value) { return (Integer[])ArraysKt.plus((Object[])this.data, value); } public final void test() { IntArray intArr = new IntArray(new Integer[]{Integer.valueOf(1)}); Integer[] newArr = intArr.plus(2); } @NotNull public final Integer[] getData() { return this.data; } public IntArray(@NotNull Integer[] data) { Intrinsics.checkParameterIsNotNull(data, "data"); super(); this.data = data; } }
  • 78.
    Delegation using ‘by’ interfaceInterf { fun xx(): Int } class A: Interf { override fun xx() = 1 } class B(a: A): Interf by a ????
  • 79.
    Delegation using ‘by’ publicinterface Interf { int xx();} public final class A implements Interf { public int xx() { return 1; }} public final class B implements Interf { private final A $$delegate_0; public B(@NotNull A a) { Intrinsics.checkParameterIsNotNull(a, "a"); super(); this.$$delegate_0 = a; } public int xx() { return this.$$delegate_0.xx(); }
  • 80.
    Recursion fun factorial(value: Int):Int = if(value <= 1) 1 else value * factorial(value -1)
  • 81.
    Recursion public static finalint factorial(int value) { return value <= 1 ? 1 : value * factorial(value - 1); }
  • 82.
    Tail recursion ????tailrec funfactorial(value: Int) : Int = if(value <= 1) 1 else value * factorial(value -1)
  • 83.
    Tail recursion public staticfinal int factorial(int value) { return value <= 1 ? 1 : value * factorial(value - 1); }
  • 84.
    Tail recursion tailrec funfactorial(value: Int, acc: Int): Int = if(value <= 1) acc * value else factorial(value - 1, acc * value)
  • 85.
    Tail recursion public staticfinal int factorial(int value, int acc) { while(value > 1) { int var10000 = value - 1; acc *= value; value = var10000; } return acc * value; }
  • 86.
    Cons of Kotlin •Learning curve • Slow compilation speed • Smaller community with comparison to java
  • 87.
    Pros of Kotlin •Reduces boilerplate • Compatible with jvm • Competitive performance • Elegant • Best IDE integration • Choice №1 for android
  • 88.