Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Top 10 Kotlin Stack Overflow Questions (Kotlin ...

Top 10 Kotlin Stack Overflow Questions (Kotlin Budapest User Group meetup - May)

A selection of some of the most frequent questions about Kotlin on Stack Overflow, asked, answered and explained. Something in there for everyone, from beginners to experts.

Márton Braun

May 17, 2018
Tweet

More Decks by Márton Braun

Other Decks in Programming

Transcript

  1. Array<Int> vs IntArray Array<Int> Integer[] IntArray int[] val intArray: IntArray

    = intArrayOf(1, 2, 3, 4, 5) val arrayOfInts: Array<Int> = arrayOf(1, 2, 3, 4, 5)
  2. Array<Int> vs IntArray • IntArray  Avoids boxing  Easier

    to initialize val intArray = IntArray(10) val arrayOfInts = Array<Int>(5) { i -> i * 2 }
  3. Array<Int> vs IntArray • IntArray  Avoids boxing  Easier

    to initialize • Array<Int> val intArray = IntArray(10) val arrayOfInts = Array<Int>(5) { i -> i * 2 }
  4. Array<Int> vs IntArray • IntArray  Avoids boxing  Easier

    to initialize • Array<Int>  Might be required by an API val intArray = IntArray(10) val arrayOfInts = Array<Int>(5) { i -> i * 2 }
  5. Array<Int> vs IntArray • IntArray  Avoids boxing  Easier

    to initialize • Array<Int>  Might be required by an API  Can store nullable values val intArray = IntArray(10) val arrayOfInts = Array<Int>(5) { i -> i * 2 } val notPeople: Array<Person?> = arrayOfNulls<Person>(13)
  6. Iterable vs Sequence  Eager evaluation Iterable java.lang.Iterable val people:

    List<Person> = getPeople() val allowedEntrance = people .filter { it.age >= 21 } .map { it.name } .take(5)
  7. val people: List<Person> = getPeople() val allowedEntrance = people .filter

    { it.age >= 21 } .map { it.name } .take(5) Iterable vs Sequence
  8. val people: List<Person> = getPeople() val allowedEntrance = people .filter

    { it.age >= 21 } .map { it.name } .take(5) Iterable vs Sequence
  9. val people: List<Person> = getPeople() val allowedEntrance = people .filter

    { it.age >= 21 } .map { it.name } .take(5) Iterable vs Sequence
  10. val people: List<Person> = getPeople() val allowedEntrance = people .filter

    { it.age >= 21 } .map { it.name } .take(5) Iterable vs Sequence
  11. val people: List<Person> = getPeople() val allowedEntrance = people .filter

    { it.age >= 21 } .map { it.name } .take(5) Iterable vs Sequence
  12. val people: List<Person> = getPeople() val allowedEntrance = people .filter

    { it.age >= 21 } .map { it.name } .take(5) Iterable vs Sequence
  13. val people: List<Person> = getPeople() val allowedEntrance = people .filter

    { it.age >= 21 } .map { it.name } .take(5) Iterable vs Sequence
  14. val people: List<Person> = getPeople() val allowedEntrance = people .filter

    { it.age >= 21 } .map { it.name } .take(5) Iterable vs Sequence
  15. val people: List<Person> = getPeople() val allowedEntrance = people .filter

    { it.age >= 21 } .map { it.name } .take(5) Iterable vs Sequence
  16. val people: List<Person> = getPeople() val allowedEntrance = people .filter

    { it.age >= 21 } .map { it.name } .take(5) Iterable vs Sequence
  17. val people: List<Person> = getPeople() val allowedEntrance = people .filter

    { it.age >= 21 } .map { it.name } .take(5) Iterable vs Sequence
  18. val people: List<Person> = getPeople() val allowedEntrance = people .filter

    { it.age >= 21 } .map { it.name } .take(5) Iterable vs Sequence
  19. val people: List<Person> = getPeople() val allowedEntrance = people .filter

    { it.age >= 21 } .map { it.name } .take(5) Iterable vs Sequence
  20. val people: List<Person> = getPeople() val allowedEntrance = people .filter

    { it.age >= 21 } .map { it.name } .take(5) Iterable vs Sequence
  21. val people: List<Person> = getPeople() val allowedEntrance = people .filter

    { it.age >= 21 } .map { it.name } .take(5) Iterable vs Sequence
  22. val people: List<Person> = getPeople() val allowedEntrance = people .filter

    { it.age >= 21 } .map { it.name } .take(5) Iterable vs Sequence
  23. val people: List<Person> = getPeople() val allowedEntrance = people .filter

    { it.age >= 21 } .map { it.name } .take(5) Iterable vs Sequence
  24. val people: List<Person> = getPeople() val allowedEntrance = people .filter

    { it.age >= 21 } .map { it.name } .take(5) Iterable vs Sequence
  25. val people: List<Person> = getPeople() val allowedEntrance = people .filter

    { it.age >= 21 } .map { it.name } .take(5) Iterable vs Sequence
  26. val people: List<Person> = getPeople() val allowedEntrance = people .filter

    { it.age >= 21 } .map { it.name } .take(5) Iterable vs Sequence
  27. Iterable vs Sequence Sequence  Lazy evaluation val people: List<Person>

    = getPeople() val allowedEntrance = people.asSequence() .filter { it.age >= 21 } .map { it.name } .take(5) .toList()
  28. Iterable vs Sequence Sequence  Lazy evaluation val people: List<Person>

    = getPeople() val allowedEntrance = people.asSequence() .filter { it.age >= 21 } .map { it.name } .take(5) .toList()
  29. Iterable vs Sequence val people: List<Person> = getPeople() val allowedEntrance

    = people.asSequence() .filter { it.age >= 21 } .map { it.name } .take(5) .toList()
  30. Iterable vs Sequence val people: List<Person> = getPeople() val allowedEntrance

    = people.asSequence() .filter { it.age >= 21 } .map { it.name } .take(5) .toList()
  31. Iterable vs Sequence val people: List<Person> = getPeople() val allowedEntrance

    = people.asSequence() .filter { it.age >= 21 } .map { it.name } .take(5) .toList()
  32. Iterable vs Sequence val people: List<Person> = getPeople() val allowedEntrance

    = people.asSequence() .filter { it.age >= 21 } .map { it.name } .take(5) .toList()
  33. Iterable vs Sequence val people: List<Person> = getPeople() val allowedEntrance

    = people.asSequence() .filter { it.age >= 21 } .map { it.name } .take(5) .toList()
  34. Iterable vs Sequence val people: List<Person> = getPeople() val allowedEntrance

    = people.asSequence() .filter { it.age >= 21 } .map { it.name } .take(5) .toList()
  35. Iterable vs Sequence val people: List<Person> = getPeople() val allowedEntrance

    = people.asSequence() .filter { it.age >= 21 } .map { it.name } .take(5) .toList()
  36. Iterable vs Sequence val people: List<Person> = getPeople() val allowedEntrance

    = people.asSequence() .filter { it.age >= 21 } .map { it.name } .take(5) .toList()
  37. Iterable vs Sequence val people: List<Person> = getPeople() val allowedEntrance

    = people.asSequence() .filter { it.age >= 21 } .map { it.name } .take(5) .toList()
  38. Iterable vs Sequence val people: List<Person> = getPeople() val allowedEntrance

    = people.asSequence() .filter { it.age >= 21 } .map { it.name } .take(5) .toList()
  39. Iterable vs Sequence val people: List<Person> = getPeople() val allowedEntrance

    = people.asSequence() .filter { it.age >= 21 } .map { it.name } .take(5) .toList()
  40. Iterable vs Sequence val allowedEntrance = people.asSequence() .filter { it.age

    >= 21 } .map { it.name } .take(5) .toList() val people: List<Person> = getPeople() val allowedEntrance = people.asSequence() .filter { it.age >= 21 } .map { it.name } .take(5) .toList()
  41. Iterable vs Sequence val people: List<Person> = getPeople() val allowedEntrance

    = people.asSequence() .filter { it.age >= 21 } .map { it.name } .take(5) .toList()
  42. Iterable vs Sequence val people: List<Person> = getPeople() val allowedEntrance

    = people.asSequence() .filter { it.age >= 21 } .map { it.name } .take(5) .toList()
  43. Iterable vs Sequence val people: List<Person> = getPeople() val allowedEntrance

    = people.asSequence() .filter { it.age >= 21 } .map { it.name } .take(5) .toList()
  44. Iterable vs Sequence val people: List<Person> = getPeople() val allowedEntrance

    = people.asSequence() .filter { it.age >= 21 } .map { it.name } .take(5) .toList()
  45. Iterable vs Sequence val people: List<Person> = getPeople() val allowedEntrance

    = people.asSequence() .filter { it.age >= 21 } .map { it.name } .take(5) .toList()
  46. Iterable vs Sequence val people: List<Person> = getPeople() val allowedEntrance

    = people.asSequence() .filter { it.age >= 21 } .map { it.name } .take(5) .toList()
  47. Iterable vs Sequence val people: List<Person> = getPeople() val allowedEntrance

    = people.asSequence() .filter { it.age >= 21 } .map { it.name } .take(5) .toList()
  48. Iterable vs Sequence val people: List<Person> = getPeople() val allowedEntrance

    = people.asSequence() .filter { it.age >= 21 } .map { it.name } .take(5) .toList()
  49. Iterable vs Sequence Sequence  Lazy evaluation  Potentially infinite

    generateSequence(1) { n -> n * 2 } .take(20) .forEach(::println)
  50. Iterable vs Sequence • Iterable  Use by default 

    Usually the best choice • Sequence
  51. Iterable vs Sequence • Iterable  Use by default 

    Usually the best choice • Sequence  To handle an infinite number of elements
  52. Iterable vs Sequence • Iterable  Use by default 

    Usually the best choice • Sequence  To handle an infinite number of elements  For huge collections, judiciously
  53. Iterable vs Sequence • Iterable  Use by default 

    Usually the best choice • Sequence  To handle an infinite number of elements  For huge collections, judiciously • Stream
  54. Iterable vs Sequence • Iterable  Use by default 

    Usually the best choice • Sequence  To handle an infinite number of elements  For huge collections, judiciously • Stream  When interoperating with Java
  55. Iteration for (i in 0..args.size - 1) { println(args[i]) }

    for (i in 0..args.lastIndex) { println(args[i]) }
  56. Iteration for (i in 0..args.size - 1) { println(args[i]) }

    for (i in 0..args.lastIndex) { println(args[i]) } for (i in 0 until args.size) { println(args[i]) }
  57. Iteration for (i in 0..args.size - 1) { println(args[i]) }

    for (i in 0..args.lastIndex) { println(args[i]) } for (i in 0 until args.size) { println(args[i]) } for (i in args.indices) { println(args[i]) }
  58. Iteration for (i in 0..args.size - 1) { println(args[i]) }

    for (i in 0..args.lastIndex) { println(args[i]) } for (i in 0 until args.size) { println(args[i]) } for (i in args.indices) { println(args[i]) } for (arg in args) { println(arg) }
  59. Iteration for (i in 0..args.size - 1) { println(args[i]) }

    for (i in 0..args.lastIndex) { println(args[i]) } for (i in 0 until args.size) { println(args[i]) } for (i in args.indices) { println(args[i]) } for (arg in args) { println(arg) } args.forEach { arg -> println(arg) }
  60. Iteration for (i in 0..args.size - 1) { println(args[i]) }

    for (i in 0..args.lastIndex) { println(args[i]) } for (i in 0 until args.size) { println(args[i]) } for (i in args.indices) { println(args[i]) } for (arg in args) { println(arg) } args.forEach { arg -> println(arg) }
  61. Iteration for (i in 0..args.size - 1) { println(args[i]) }

    for (i in 0..args.lastIndex) { println(args[i]) } for (i in 0 until args.size) { println(args[i]) } for (i in args.indices) { println(args[i]) } for (arg in args) { println(arg) } args.forEach { arg -> println(arg) }
  62. Iteration with indexes for ((index, arg) in args.withIndex()) { println("$index:

    $arg") } args.forEachIndexed { index, arg -> println("$index: $arg") }
  63. Iteration with indexes for ((index, arg) in args.withIndex()) { println("$index:

    $arg") } args.forEachIndexed { index, arg -> println("$index: $arg") }
  64. Iteration with indexes for ((index, arg) in args.withIndex()) { println("$index:

    $arg") } args.forEachIndexed { index, arg -> println("$index: $arg") }
  65. SAM conversions public interface OnClickListener { void onClick(Button button); }

    public class Button { public void setListener(OnClickListener listener) { ... } }
  66. SAM conversions button.setListener(object : OnClickListener { override fun onClick(button: Button?)

    { println("Clicked!") } }) button.setListener { println("Clicked!") }
  67. SAM conversions button.setListener(object : OnClickListener { override fun onClick(button: Button?)

    { println("Clicked!") } }) button.setListener { println("Clicked!") }
  68. SAM conversions button.setListener(object : OnClickListener { override fun onClick(button: Button?)

    { println("Clicked!") } }) button.setListener { button: Button? -> println("Clicked!") }
  69. SAM conversions #1 button.setListener { object : OnClickListener { override

    fun onClick(button: Button) { println("Clicked!") } }) }
  70. SAM conversions #1 button.setListener { object : OnClickListener { override

    fun onClick(button: Button) { println("Clicked!") } }) }
  71. SAM conversions #1 button.setListener(object : OnClickListener { override fun onClick(button:

    Button?) { object : OnClickListener { override fun onClick(button: Button) { println("Clicked!") } }) } })
  72. SAM conversions #1 button.setListener(object : OnClickListener { override fun onClick(button:

    Button?) { val listener = object : OnClickListener { override fun onClick(button: Button) { println("Clicked!") } }) } })
  73. SAM conversions #1 button.setListener(object : OnClickListener { override fun onClick(button:

    Button?) { val listener = object : OnClickListener { override fun onClick(button: Button) { println("Clicked!") } }) listener.onClick(...) } })
  74. SAM conversions #1 button.setListener(object : OnClickListener { override fun onClick(button:

    Button?) { object : OnClickListener { override fun onClick(button: Button) { println("Clicked!") } }) } })
  75. SAM conversions #1 button.setListener { object : OnClickListener { override

    fun onClick(button: Button) { println("Clicked!") } }) }
  76. SAM conversions #1 button.setListener { object : OnClickListener { override

    fun onClick(button: Button) { println("Clicked!") } }) } button.setListener { fun onClick(button: Button) { println("Clicked!") } }
  77. SAM conversions #2 • What if I need to reference

    the listener instance? button.setListener { button.removeListener(this) }
  78. SAM conversions #2 • What if I need to reference

    the listener instance? button.setListener(object: OnClickListener { override fun onClick(button: Button) { button.removeListener(this) } }) button.setListener { button.removeListener(this) }
  79. SAM conversions #3 public interface OnClickListener { boolean onClick(Button button);

    } button.setListener { println("Clicked!") } Kotlin: Type mismatch: inferred type is Unit but Boolean was expected
  80. SAM conversions #4 • SAM constructor button.setListener(OnClickListener { println("Clicked!") })

    Java interface Kotlin interface Java method SAM conversion Object expression Kotlin method SAM constructor Object expression
  81. Replacing statics class Foo { companion object { fun x()

    { ... } } fun y() { ... } } Foo.x()
  82. Replacing statics class Foo { companion object { fun x()

    { ... } } fun y() { ... } } object Foo { fun x() { ... } } Foo.x() Foo.x()
  83. Replacing statics class Foo { companion object { fun x()

    { ... } } fun y() { ... } } object Foo { fun x() { ... } } fun x() { ... } Foo.x() Foo.x() x()
  84. Replacing statics class Foo { companion object { fun x()

    { ... } } fun y() { ... } } object Foo { fun x() { ... } } fun x() { ... } Foo.x() Foo.x() x()
  85. Function declaration reference Declaration Kotlin usage Java usage Companion object

    Foo.f() Foo.Companion.f(); Companion object with @JvmStatic Foo.f() Foo.f(); Object Foo.f() Foo.INSTANCE.f(); Object with @JvmStatic Foo.f() Foo.f(); Top level function f() UtilKt.f(); Top level function with @JvmName* f() Util.f(); * With the @JvmName annotation on the file use-site target
  86. Variable declaration reference Declaration Kotlin usage Java usage Companion object

    X.x X.Companion.getX(); Companion object with @JvmStatic X.x X.getX(); Companion object with @JvmField X.x X.x; Companion object with const X.x X.x; Object X.x X.INSTANCE.getX(); Object with @JvmStatic X.x X.getX(); Object with @JvmField X.x X.x; Object with const X.x X.x; Top level variable x ConstKt.getX(); Top level variable with @JvmField x ConstKt.x; Top level variable with const x ConstKt.x; Top level variable with @JvmName* x Const.getX(); Top level variable with @JvmName* and @JvmField x Const.x; Top level variable with @JvmName* and const x Const.x; * With the @JvmName annotation on the file use-site target
  87. Static initializers class X { companion object { init {

    println("Static initialization!") } } }
  88. Smart casts on mutable properties class Dog(var toy: Toy? =

    null) { fun play() { if (toy != null) { toy.chew() } } }
  89. Smart casts on mutable properties class Dog(var toy: Toy? =

    null) { fun play() { if (toy != null) { toy.chew() } } } Kotlin: Smart cast to 'Toy' is impossible, because 'toy' is a mutable property that could have been changed by this time
  90. Smart casts on mutable properties class Dog(val toy: Toy? =

    null) { fun play() { if (toy != null) { toy.chew() } } }
  91. Smart casts on mutable properties class Dog(var toy: Toy? =

    null) { fun play() { if (toy != null) { toy.chew() } } }
  92. Smart casts on mutable properties class Dog(var toy: Toy? =

    null) { fun play() { val _toy = toy if (_toy != null) { _toy.chew() } } }
  93. Smart casts on mutable properties class Dog(var toy: Toy? =

    null) { fun play() { toy?.let { it.chew() } } }
  94. Smart casts on mutable properties class Dog(var toy: Toy? =

    null) { fun play() { toy?.let { it.chew() it.chew() it.chew() } } }
  95. null!! class Episode { var airdate: Date = null!! }

    fun getWeekDay(date: Date?): WeekDay { return date!!.getWeekDay() }
  96. null!! class Episode { var airdate: Date = null!! }

    fun getWeekDay(date: Date?): WeekDay { return date!!.getWeekDay() } Date?
  97. null!! class Episode { var airdate: Date = null!! }

    fun getWeekDay(date: Date?): WeekDay { return date!!.getWeekDay() } WeekDay Date?
  98. null!! class Episode { var airdate: Date = null!! }

    fun getWeekDay(date: Date?): WeekDay { return date!!.getWeekDay() } Date WeekDay Date?
  99. null!! class Episode { var airdate: Date = null!! }

    fun getWeekDay(date: Date?): WeekDay { return date!!.getWeekDay() } Date
  100. null!! class Episode { var airdate: Date = null!! }

    fun getWeekDay(date: Date?): WeekDay { return date!!.getWeekDay() } Date date as Date
  101. null!! class Episode { var airdate: Date = null!! }

    fun getWeekDay(date: Date?): WeekDay { return date!!.getWeekDay() } Date date as Date throw NullPointerException()
  102. null!! class Episode { var airdate: Date = null!! }

    fun getWeekDay(date: Date?): WeekDay { return date!!.getWeekDay() } Date
  103. Platform types in overrides How do I choose the right

    type when overriding Java methods?
  104. Platform types in overrides public interface OnClickListener { void onClick(Button

    button); } class KtListener : OnClickListener { override fun onClick(button: Button?): Unit { val name = button?.name ?: "Unknown button" println("Clicked ${name}") } }
  105. Platform types in overrides public interface OnClickListener { void onClick(Button

    button); } class KtListener : OnClickListener { override fun onClick(button: Button?): Unit { val name = button?.name ?: "Unknown button" println("Clicked ${name}") } }
  106. Platform types in overrides public interface OnClickListener { void onClick(Button

    button); } class KtListener : OnClickListener { override fun onClick(button: Button?): Unit { val name = button?.name ?: "Unknown button" println("Clicked ${name}") } }
  107. Platform types in overrides public interface OnClickListener { void onClick(Button

    button); } class KtListener : OnClickListener { override fun onClick(button: Button): Unit { val name = button.name println("Clicked ${name}") } }
  108. Import aliases package com.example.code fun indent(str: String) : String {

    ... } package com.example.square fun indent(str: String) : String { ... }
  109. Import aliases package com.example.code fun indent(str: String) : String {

    ... } package com.example.square fun indent(str: String) : String { ... } import com.example.code.indent indent("hello") com.example.square.indent("world")
  110. Import aliases package com.example.code fun String.indent() : String { ...

    } package com.example.square fun String.indent() : String { ... }
  111. Import aliases package com.example.code fun String.indent() : String { ...

    } package com.example.square fun String.indent() : String { ... } import com.example.code.indent "hello".indent() "world".indent()
  112. Import aliases package com.example.code fun String.indent() : String { ...

    } package com.example.square fun String.indent() : String { ... } import com.example.code.indent as indent4 import com.example.square.indent as indent2 "hello".indent4() "world".indent2()
  113. Import aliases import java.util.Date as UtilDate import java.sql.Date as SqlDate

    fun matches(date1: UtilDate, date2: SqlDate): Boolean { ... }
  114. Recap • 1. Array<Int> vs IntArray • 2. Iterable vs

    Sequence • 3. Iteration (with indexes) • 4. SAM conversions • 5. Replacing statics • 6. Smart casts on mutable properties • 7. null!! • 8. Platform types in overrides • 9. Import aliases • 10. Kotlin vs Java for Android development
  115. References • Top 10 Kotlin Stack Overflow questions, article series

     https://zsmb.co/top-10-kotlin-stack-overflow-questions-1/ • Kotlin tag on Stack Overflow  https://stackoverflow.com/questions/tagged/kotlin