Effective Java In Kotlin World

Effective Java In Kotlin World

Effective Java In Kotlin World presentation slides.

77a6451d320b030040b27d2f31dd54d0?s=128

Seyyed davud hosseiny

July 18, 2019
Tweet

Transcript

  1. Integer x = 300; Integer y = 300; if(x ==

    y) { println("Same Int"); } else { println("Diff Int”); } Video Link: https://www.youtube.com/playlist?list=PLT2xIm2X7W7jqdoYI5EXpYkuOPkWngOP3
  2. Integer x = 300; Integer y = 300; if(x ==

    y) { println("Same Int"); } else { println("Diff Int”); } prints Diff Int
  3. Integer x = 300; Integer y = 300; if(x.equals(y) {

    println("Same Int"); } else { println("Diff Int”); } prints Diff Int
  4. Integer x = 300; Integer y = 300; if(x.equals(y) {

    println("Same Int"); } else { println("Diff Int”); } prints Same Int
  5. Effective Java In Kotlin World ینیسح دواد دیس https://github.com/DHosseiny @Hosseinydavid

  6. None
  7. Item 3: Enforce the singleton property with a private constructor

    or an enum type
  8. public class Elvis { private static final Elvis INSTANCE =

    new Elvis(); private Elvis() { } public static Elvis getInstance() { return INSTANCE; } public void leaveTheBuilding() { ... } }
  9. object Elvis

  10. object Elvis

  11. object Elvis public final class Elvis { public static final

    Elvis INSTANCE; static { Elvis var0 = new Elvis(); INSTANCE = var0; } }
  12. Item 2: Consider a builder when faced with many constructor

    parameters
  13. public class NutritionFacts { private final int servingSize; // required

    private final int servings; // required private final int calories; // optional private final int fat; // optional private final int sodium; // optional private final int carbohydrate; // optional }
  14. public static class Builder { // Required parameters private final

    int servingSize; private final int servings; // Optional parameters - initialized to default values private int calories = 0; private int fat = 0; private int carbohydrate = 0; private int sodium = 0; public Builder(int servingSize, int servings) { this.servingSize = servingSize; this.servings = servings; } public Builder calories(int val) { calories = val; return this; } public Builder fat(int val) { fat = val; return this; } public Builder carbohydrate(int val) { carbohydrate = val; return this; } public Builder sodium(int val) { sodium = val; return this; } public NutritionFacts build() { return new NutritionFacts(this); } } public class NutritionFacts { private final int servingSize; private final int servings; private final int calories; private final int fat; private final int sodium; private final int carbohydrate;
  15. public static class Builder { // Required parameters private final

    int servingSize; private final int servings; // Optional parameters - initialized to default values private int calories = 0; private int fat = 0; private int carbohydrate = 0; private int sodium = 0; public Builder(int servingSize, int servings) { this.servingSize = servingSize; this.servings = servings; } public Builder calories(int val) { calories = val; return this; } public Builder fat(int val) { fat = val; return this; } public Builder carbohydrate(int val) { carbohydrate = val; return this; } public Builder sodium(int val) { sodium = val; return this; } public NutritionFacts build() { return new NutritionFacts(this); } } public class NutritionFacts { private final int servingSize; private final int servings; private final int calories; private final int fat; private final int sodium; private final int carbohydrate; private NutritionFacts(Builder builder) { servingSize = builder.servingSize; servings = builder.servings; calories = builder.calories; fat = builder.fat; sodium = builder.sodium; carbohydrate = builder.carbohydrate; } }
  16. NutritionFacts cocaCola = new NutritionFacts.Builder(240, 8) .calories(100) .sodium(35) .carbohydrate(27) .build();

  17. class NutritionFacts private val servingSize: Int, private val servings: Int,

    private val calories: Int = 0, private val fat: Int = 0, private val sodium: Int = 0, private val carbohydrates: Int = 0) (
  18. class NutritionFacts private val servingSize: Int, private val servings: Int,

    private val calories: Int = 0, private val fat: Int = 0, private val sodium: Int = 0, private val carbohydrates: Int = 0) // default value // default value // default value // default value (
  19. class NutritionFacts private val servingSize: Int, private val servings: Int,

    private val calories: Int = 0, private val fat: Int = 0, private val sodium: Int = 0, private val carbohydrates: Int = 0) // no default value // no default value // default value // default value // default value // default value (
  20. class NutritionFacts @JvmOverloads constructor( private val servingSize: Int, private val

    servings: Int, private val calories: Int = 0, private val fat: Int = 0, private val sodium: Int = 0, private val carbohydrates: Int = 0) // no default value // no default value // default value // default value // default value // default value
  21. val cocaCola = NutritionFacts( servingSize = 240, servings = 8)

  22. val cocaCola = NutritionFacts( servingSize = 240, servings = 8,

    fat = 240, calories = 100, carbohydrates = 27 ) val cocaCola = NutritionFacts( servingSize = 240, servings = 8)
  23. val cocaCola = NutritionFacts( servingSize = 240, servings = 8,

    fat = 240, calories = 100, carbohydrates = 27 ) val cocaCola = NutritionFacts( servingSize = 240, servings = 8)
  24. Item 19: Design and document for inheritance or else prohibit

    it
  25. class NewMainActivity

  26. class NewMainActivity

  27. class NewMainActivity

  28. class NewMainActivity open

  29. class NewMainActivity open

  30. Item 18: Favor composition over inheritance

  31. None
  32. None
  33. class EspressoCoffeeMachine : Boiler by DoubleBoiler, Pump by RotaryVane

  34. class EspressoCoffeeMachine : Boiler by DoubleBoiler, Pump by RotaryVane

  35. class EspressoCoffeeMachine : Boiler by DoubleBoiler, Pump by RotaryVane public

    final class EspressoCoffeeMachine implements Boiler, Pump { private final DoubleBoiler $$delegate_0; private final RotaryVane $$delegate_1; public EspressoCoffeeMachine() { this.$$delegate_0 = DoubleBoiler.INSTANCE; this.$$delegate_1 = RotaryVane.INSTANCE; } }
  36. Item 77: Don't ignore exceptions

  37. public void close(Closeable c) { try { c.close(); } catch

    (IOException ignored) { } }
  38. public int getCastValueToInt(String str) { int num = -1; try

    { num = Integer.parseInt(str); } catch (NumberFormatException ignored) {} return num; }
  39. public int getCastValueToInt(String str) { int num = -1; try

    { num = Integer.parseInt(str); } catch (NumberFormatException ignored) {} return num; } fun getCastValueToInt(string: String) = try { Integer.parseInt(string); } catch (e: NumberFormatException) { -1 }
  40. Item 17: Minimize mutability

  41. Item 10: Obey contract when overriding equals

  42. Item 9: Always override hashCode when you override Equals

  43. Item 12: Always Override toString

  44. public class ItemJava { @NotNull public final String id; @NotNull

    public final String name; @NotNull public final String description; public ItemJava(@NotNull String id, @NotNull String name, @NotNull String description) { Intrinsics.checkParameterIsNotNull(id, "id"); Intrinsics.checkParameterIsNotNull(name, "name"); Intrinsics.checkParameterIsNotNull(description, "description"); this.id = id; this.name = name; this.description = description; }A }
  45. public class ItemJava { @NotNull public final String id; @NotNull

    public final String name; @NotNull public final String description; public ItemJava(@NotNull String id, @NotNull String name, @NotNull String description) { Intrinsics.checkParameterIsNotNull(id, "id"); Intrinsics.checkParameterIsNotNull(name, "name"); Intrinsics.checkParameterIsNotNull(description, "description"); this.id = id; this.name = name; this.description = description; }A public boolean equals(Object var1) { if (this != var1) { if (var1 instanceof ItemJava) { ItemJava var2 = (ItemJava) var1; return Intrinsics.areEqual(this.id, var2.id) && Intrinsics.areEqual(this.name, var2.name) && Intrinsics.areEqual(this.description, var2.description); }B return false; } else { return true; }C }D } public int hashCode() {
  46. None
  47. data class Item(val id: String, val name: String, val description:

    String)
  48. data class Item(val id: String, val name: String, val description:

    String)
  49. public final class Item { @NotNull private final String id;

    @NotNull private final String name; @NotNull private final String description; @NotNull public final String getId() { return this.id; } @NotNull public final String getName() { return this.name; } @NotNull public final String getDescription() { return this.description; } public Item(@NotNull String id, @NotNull String name, @NotNull String description) { Intrinsics.checkParameterIsNotNull(id, "id"); Intrinsics.checkParameterIsNotNull(name, "name"); Intrinsics.checkParameterIsNotNull(description, "description"); super(); this.id = id; this.name = name; this.description = description; } @NotNull public final String component1() { return this.id; } @NotNull public final String component2() { return this.name; } @NotNull public final String component3() { return this.description; } @NotNull public final Item copy(@NotNull String id, @NotNull String name, @NotNull String description) { Intrinsics.checkParameterIsNotNull(id, "id"); Intrinsics.checkParameterIsNotNull(name, "name"); Intrinsics.checkParameterIsNotNull(description, "description"); return new Item(id, name, description); } // $FF: synthetic method // $FF: bridge method @NotNull public static Item copy$default(Item var0, String var1, String var2, String var3, int var4, Object var5) { if ((var4 & 1) != 0) { var1 = var0.id; } if ((var4 & 2) != 0) { var2 = var0.name; } if ((var4 & 4) != 0) { var3 = var0.description; } return var0.copy(var1, var2, var3); } public String toString() { return "Item(id=" + this.id + ", name=" + this.name + ", description=" + this.description + ")"; } public int hashCode() { return ((this.id != null ? this.id.hashCode() : 0) * 31 + (this.name != null ? this.name.hashCode() : 0)) * 31 + (this.description != null ? this.description.hashCode() : 0); } public boolean equals(Object var1) { if (this != var1) { if (var1 instanceof Item) { Item var2 = (Item)var1; if (Intrinsics.areEqual(this.id, var2.id) && Intrinsics.areEqual(this.name, var2.name) && Intrinsics.areEqual(this.description, var2.description)) { return true; } } return false; } else { return true; data class Item(val id: String, val name: String, val description: String)
  50. data class Item(val id: String, val name: String, val description:

    String) public Item(@NotNull String id, @NotNull String name, @NotNull String description) { Intrinsics.checkParameterIsNotNull(id, "id"); Intrinsics.checkParameterIsNotNull(name, "name"); Intrinsics.checkParameterIsNotNull(description, "description"); super(); this.id = id; this.name = name; this.description = description; }
  51. data class Item(val id: String, val name: String, val description:

    String) @NotNull public final String getId() { return this.id; } @NotNull public final String getName() { return this.name; } @NotNull public final String getDescription() { return this.description; }
  52. data class Item(val id: String, val name: String, val description:

    String) public boolean equals(Object var1) { if (this != var1) { if (var1 instanceof Item) { Item var2 = (Item)var1; if (Intrinsics.areEqual(this.id, var2.id) && Intrinsics.areEqual(this.name, var2.name) && Intrinsics.areEqual(this.description, var2.description)) { return true; } } return false; } else { return true; } }
  53. data class Item(val id: String, val name: String, val description:

    String) public int hashCode() { return ((this.id != null ? this.id.hashCode() : 0) * 31 + (this.name != null ? this.name.hashCode() : 0)) * 31 + (this.description != null ? this.description.hashCode() : 0); }
  54. data class Item(val id: String, val name: String, val description:

    String) @NotNull public final Item copy(@NotNull String id, @NotNull String name, @NotNull String description) { Intrinsics.checkParameterIsNotNull(id, "id"); Intrinsics.checkParameterIsNotNull(name, "name"); Intrinsics.checkParameterIsNotNull(description, "description"); return new Item(id, name, description); } public String toString() { return "Item(id=" + this.id + ", name=" + this.name + ", description=" + this.description + ")"; }
  55. data class Item(val id: String, val name: String, val description:

    String) @NotNull public final String component1() { return this.id; } @NotNull public final String component2() { return this.name; } @NotNull public final String component3() { return this.description; }
  56. data class Item(val id: String, val name: String, val description:

    String) @NotNull public final String component1() { return this.id; } @NotNull public final String component2() { return this.name; } @NotNull public final String component3() { return this.description; } val(id, name, description) = fooItem() fun fooItem(): Item { return Item("id", "name", "description") }
  57. data class Item(val id: String, val name: String, val description:

    String) @NotNull public final String component1() { return this.id; } @NotNull public final String component2() { return this.name; } @NotNull public final String component3() { return this.description; } @Parcelize
  58. data class Item(val id: String, val name: String, val description:

    String) @Parcelize public void writeToParcel(@NotNull Parcel parcel, int flags) { Intrinsics.checkParameterIsNotNull(parcel, "parcel"); parcel.writeString(this.id); parcel.writeString(this.name); parcel.writeString(this.description); } @Metadata( mv = {1, 1, 13}, bv = {1, 0, 3}, k = 3 ) public static class Creator implements Parcelable.Creator { @NotNull public final Object[] newArray(int size) { return new Item[size]; } @NotNull public final Object createFromParcel(@NotNull Parcel in) { Intrinsics.checkParameterIsNotNull(in, "in"); return new Item(in.readString(), in.readString(), in.readString()); }
  59. data class Item(val id: String, val name: String, val description:

    String) @Parcelize public final class Item { @NotNull private final String id; @NotNull private final String name; @NotNull private final String description; @NotNull public final String getId() { return this.id; } @NotNull public final String getName() { return this.name; } @NotNull public final String getDescription() { return this.description; } public Item(@NotNull String id, @NotNull String name, @NotNull String description) { Intrinsics.checkParameterIsNotNull(id, "id"); Intrinsics.checkParameterIsNotNull(name, "name"); Intrinsics.checkParameterIsNotNull(description, "description"); super(); this.id = id; this.name = name; this.description = description; } @NotNull public final String component1() { return this.id; } @NotNull public final String component2() { return this.name; } @NotNull public final String component3() { return this.description; } @NotNull public final Item copy(@NotNull String id, @NotNull String name, @NotNull String description) { Intrinsics.checkParameterIsNotNull(id, "id"); Intrinsics.checkParameterIsNotNull(name, "name"); Intrinsics.checkParameterIsNotNull(description, "description"); return new Item(id, name, description); } // $FF: synthetic method // $FF: bridge method @NotNull public static Item copy$default(Item var0, String var1, String var2, String var3, int var4, Object var5) { if ((var4 & 1) != 0) { var1 = var0.id; } if ((var4 & 2) != 0) { var2 = var0.name; } if ((var4 & 4) != 0) { var3 = var0.description; } return var0.copy(var1, var2, var3); } public String toString() { return "Item(id=" + this.id + ", name=" + this.name + ", description=" + this.description + ")"; } public int hashCode() { return ((this.id != null ? this.id.hashCode() : 0) * 31 + (this.name != null ? this.name.hashCode() : 0)) * 31 + (this.description != null ? this.description.hashCode() : 0); } public boolean equals(Object var1) { if (this != var1) { if (var1 instanceof Item) { Item var2 = (Item)var1; if (Intrinsics.areEqual(this.id, var2.id) && Intrinsics.areEqual(this.name, var2.name) && Intrinsics.areEqual(this.description, var2.description)) { return true; } } return false; } else { return true;
  60. public List<Item> getItem(String itemId) getItem(null)

  61. None
  62. None
  63. Item 54: Return empty collections or arrays, not nulls

  64. Handling Null references

  65. public List<Item> getItem(String itemId)

  66. @NotNull public List<Item> getItem(@NotNull String itemId)

  67. @NotNull public List<Item> getItem(@NotNull String itemId)

  68. @NotNull public List<Item> getItem(@NotNull String itemId)

  69. @NotNull public List<Item> getItem(@NotNull String itemId) fun getItem(itemId: String) :

    List<Item>
  70. fun getItem(itemId: String) : List<Item> @NotNull public final List getItem(@NotNull

    String itemId)
  71. fun getItem(itemId: String) : List<Item>

  72. fun getItem(itemId: String) : List<Item>

  73. fun getItem(itemId: String) : List<Item>

  74. fun getItem(itemId: String) : List<Item>

  75. Chapter 6: Enums and annotations

  76. None
  77. Sealed classes

  78. sealed class RemoteData

  79. sealed class RemoteData { class NotInitialized : RemoteData() }

  80. sealed class RemoteData { object NotInitialized : RemoteData() }

  81. sealed class RemoteData { object NotInitialized : RemoteData() class Loading

    } : RemoteData()
  82. sealed class RemoteData { object NotInitialized : RemoteData() class Loading

    } (val progress: Progress) : RemoteData()
  83. sealed class RemoteData { object NotInitialized : RemoteData() data class

    Loading(val progress: Progress) : RemoteData() class Success : RemoteData() }
  84. sealed class RemoteData { object NotInitialized : RemoteData() data class

    Loading(val progress: Progress) : RemoteData() } class Success: RemoteData() class Failure: RemoteData()
  85. sealed class RemoteData { object NotInitialized : RemoteData() data class

    Loading(val progress: Progress) : RemoteData() } class Success(result: Response): RemoteData() class Failure: RemoteData()
  86. sealed class RemoteData { object NotInitialized : RemoteData() data class

    Loading(val progress: Progress) : RemoteData() } class Success(result: Response): RemoteData() class Failure(exception: Exception): RemoteData()
  87. fun newState(request: RemoteData) = when (request) { RemoteData.NotInitialized -> request

    }
  88. fun newState(request: RemoteData) = when (request) { RemoteData.NotInitialized -> request

    is RemoteData.Loading -> { viewModel.loading(request.progress) } }
  89. fun newState(request: RemoteData) = when (request) { RemoteData.NotInitialized -> request

    is RemoteData.Loading -> { viewModel.loading(request.progress) } is RemoteData.Success -> { viewModel.transform(request.result) } }
  90. fun newState(request: RemoteData) = when (request) { RemoteData.NotInitialized -> request

    is RemoteData.Loading -> { viewModel.loading(request.progress) } is RemoteData.Success -> { viewModel.transform(request.result) } is RemoteData.Failure -> { viewModel.showError(request.exception) } }
  91. Generics

  92. Item 27: Favor generic methods

  93. Reified

  94. inline fun <reified T> Context.start() = startActivity(Intent(this, T::class.java))

  95. inline fun <reified T> Context.start() = startActivity(Intent(this, T::class.java))

  96. inline fun <reified T> Context.start() = startActivity(Intent(this, T::class.java))

  97. inline fun <reified T> Context.start() = startActivity(Intent(this, T::class.java)) start<PurchaseActivity>()

  98. Item 28: Prefer lists to arrays

  99. Java arrays are covariant

  100. public final class Integer extends Number

  101. public final class Integer extends Number Integer[] integers = new

    Integer[1]; Number[] numbers = integers; numbers[0] = 1L;
  102. public final class Integer extends Number Integer[] integers = new

    Integer[1]; Number[] numbers = integers; numbers[0] = 1L; java.lang.ArrayStoreException: Long cannot be stored in an array of type Integer[]
  103. Java List with generics are invariant and erased

  104. None
  105. List enforces type safety at compile time

  106. Arrays in Kotlin are invariant and allow generics

  107. Integer[] integers = new Integer[1]; Number[] numbers = integers; numbers[0]

    = 1L; java.lang.ArrayStoreException: Long cannot be stored in an array of type Integer[]
  108. Integer[] integers = new Integer[1]; Number[] numbers = integers; numbers[0]

    = 1L; java.lang.ArrayStoreException: Long cannot be stored in an array of type Integer[]
  109. Item 31: Use bounded wildcards to increase API flexibility

  110. class Stack<E> { public void pushAll(Iterable<E> src) { for (E

    e : src) push(e); } }
  111. class Stack<E> { public void pushAll(Iterable<E> src) { for (E

    e : src) push(e); } }
  112. ?

  113. <? extends T> <? super T>

  114. PECS stands for producer- extends, consumer-super.

  115. class Stack<E> { public void pushAll(Iterable<E> src) { for (E

    e : src) push(e); } }
  116. class Stack<E> { public void pushAll(Iterable<? extends E> src) {

    for (E e : src) push(e); } }
  117. Stack<Number> stack = new Stack<>(); List<Integer> integers = new ArrayList<>();

    stack.pushAll(integers); class Stack<E> { public void pushAll(Iterable<? extends E> src) { for (E e : src) push(e); } }
  118. class Stack<E> { public void pushAll(Iterable<? extends E> src) {

    for (E e : src) push(e); } public void popAll(Collection<? super E> dst) { while (!isEmpty()) dst.add(pop()); } }
  119. Use-site variance

  120. class Stack<E> { public void pushAll(Iterable<? extends E> src) {

    for (E e : src) push(e); } public void popAll(Collection<? super E> dst) { while (!isEmpty()) dst.add(pop()); } } class Stack<E> { fun pushAll(src: Iterable<out E>) { for (e in src) push(e) } fun popAll(dst: MutableList<in E>) { while (!isEmpty()) dst.add(pop()) } }
  121. Consumer in, Producer out!

  122. Declaration-site variance

  123. interface Source<out T> { fun next(): T } interface Consumer<in

    T> { fun consume(t: T) }
  124. <out T> T er<in T> { { t: T) interface

    Source fun next(): } interface Consum fun consume( }
  125. Generics

  126. Kotlin solves many of the Java language issues

  127. + =

  128. Less Boilerplate More Features

  129. IntelliJ

  130. IntelliJ Lambda expressions

  131. IntelliJ Lambda expressions Smart casts

  132. IntelliJ Lambda expressions Smart casts String templates

  133. IntelliJ Lambda expressions Smart casts String templates Type inference

  134. IntelliJ Lambda expressions Smart casts String templates Type inference Typealias

  135. IntelliJ Lambda expressions Smart casts String templates Type inference Typealias

    Range expressions
  136. IntelliJ Lambda expressions Smart casts String templates Type inference Typealias

    Range expressions Operator overloading
  137. IntelliJ Lambda expressions Smart casts String templates Type inference Typealias

    Range expressions Operator overloading Companion objects
  138. IntelliJ Lambda expressions Smart casts String templates Type inference Typealias

    Range expressions Operator overloading Companion objects Coroutines
  139. IntelliJ Lambda expressions Smart casts String templates Type inference Typealias

    Range expressions Operator overloading Companion objects Coroutines Contracts
  140. IntelliJ Lambda expressions Smart casts String templates Type inference Typealias

    Range expressions Operator overloading Companion objects Coroutines Contracts Inline classes
  141. Why are we still using Java?

  142. @Hosseinydavid + = Questions?