Marton Braun
May 08, 2018
310

# Top 10 Kotlin Stack Overflow Questions (Google I/O Extended 2018 Budapest)

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.

Talk recording (Hungarian): https://youtu.be/-UMqYBoUlJc?t=4h7m38s

May 08, 2018

## Transcript

1. TOP 10 KOTLIN
STACK OVERFLOW
QUESTIONS
Márton Szabolcs Braun
zsmb.co zsmb13
[email protected]

2. Why do this talk?

3. Why do this talk?

4. Array vs
IntArray
What’s the difference? When do I use which one?

5. Array vs IntArray

6. Array vs IntArray
Array

7. Array vs IntArray
Array Integer[]

8. Array vs IntArray
Array Integer[]
val arrayOfInts: Array = arrayOf(1, 2, 3, 4, 5)

9. Array vs IntArray
Array Integer[]
IntArray
val arrayOfInts: Array = arrayOf(1, 2, 3, 4, 5)

10. Array vs IntArray
Array Integer[]
IntArray int[]
val arrayOfInts: Array = arrayOf(1, 2, 3, 4, 5)

11. Array vs IntArray
Array Integer[]
IntArray int[]
val intArray: IntArray = intArrayOf(1, 2, 3, 4, 5)
val arrayOfInts: Array = arrayOf(1, 2, 3, 4, 5)

12. Array vs IntArray

13. Array vs IntArray
• IntArray

14. Array vs IntArray
• IntArray
 Avoids boxing

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

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

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

18. Array vs IntArray
• IntArray
 Avoids boxing
 Easier to initialize
• Array
 Might be required by an API
 Can store nullable values
val intArray = IntArray(10)
val arrayOfInts = Array(5) { i -> i * 2 }
val notPeople: Array = arrayOfNulls(13)

19. Iterable vs
Sequence
What’s the difference? When do I use which one?

20. Iterable vs Sequence

21. Iterable vs Sequence
Iterable

22. Iterable vs Sequence
Iterable java.lang.Iterable

23. Iterable vs Sequence
 Eager evaluation
Iterable java.lang.Iterable

24. Iterable vs Sequence
 Eager evaluation
Iterable java.lang.Iterable
val people: List = getPeople()
val allowedEntrance = people
.filter { it.age >= 21 }
.map { it.name }
.take(5)

25. Iterable vs Sequence

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

46. Iterable vs Sequence

47. Iterable vs Sequence
Sequence

48. Iterable vs Sequence
Sequence
 Lazy evaluation

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

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

51. Iterable vs Sequence

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

72. Iterable vs Sequence

73. Iterable vs Sequence
• Iterable

74. Iterable vs Sequence
• Iterable
 Use by default

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

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

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

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

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

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

81. Iteration
How can / should I iterate over collections?

82. Iteration

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

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

85. 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])
}

86. 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])
}

87. 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)
}

88. 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)
}

89. 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)
}

90. 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)
}

91. SAM conversions
What are SAM conversions?

92. SAM conversions

93. SAM conversions
public interface OnClickListener {
void onClick(Button button);
}

94. SAM conversions
public interface OnClickListener {
void onClick(Button button);
}
public class Button {
public void setListener(OnClickListener listener) {
...
}
}

95. SAM conversions

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

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

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

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

100. SAM conversions #1
Why are my listeners not being called?

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

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

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

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

105. 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(...)
}
})

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

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

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

109. SAM conversions #2
Why am I getting a return type error?

110. SAM conversions #2
public interface OnClickListener {
void onClick(Button button);
}

111. SAM conversions #2
public interface OnClickListener {
boolean onClick(Button button);
}

112. SAM conversions #2
public interface OnClickListener {
boolean onClick(Button button);
}
button.setListener {
println("Clicked!")
}

113. SAM conversions #2
public interface OnClickListener {
boolean onClick(Button button);
}
button.setListener {
println("Clicked!")
}
Kotlin: Type mismatch: inferred type is Unit but
Boolean was expected

114. SAM conversions #2
public interface OnClickListener {
boolean onClick(Button button);
}
button.setListener {
println("Clicked!")
true
}

115. SAM conversions #2
public interface OnClickListener {
boolean onClick(Button button);
}
button.setListener {
println("Clicked!")
true
}

116. Replacing statics
How do I create static functions and variables in Kotlin?

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

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

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

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

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

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

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

124. Smart casts on
mutable properties
Why are smart casts not working?

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

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

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

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

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

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

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

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

133. null!!
Why am I getting NullPointerExceptions?

134. null!!

135. null!!
class Episode {
var airdate: Date = null!!
}

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

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

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

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

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

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

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

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

144. null!!
class Episode {
var airdate: Date = null!!
}

145. null!!
class Episode {
var airdate: Date = null!!
}

146. null!!
class Episode {
var airdate: Date = throw KotlinNullPointerException()
}

147. null!!
class Episode {
lateinit var airdate: Date
}

148. Platform types in
overrides
How do I choose the right type when overriding Java methods?

149. Platform types in overrides

150. Platform types in overrides
public interface OnClickListener {
void onClick(Button button);
}

151. 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}")
}
}

152. 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}")
}
}

153. 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}")
}
}

154. 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}")
}
}

155. Import aliases
What can I do about imports with conflicting names?

156. Import aliases

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

158. 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")

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

160. 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()

161. 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()

162. Import aliases
import java.util.Date as UtilDate
import java.sql.Date as SqlDate
fun matches(date1: UtilDate, date2: SqlDate): Boolean {
...
}

163. Kotlin vs Java for
Android development

164. Kotlin vs Java for Android development

165. Kotlin vs Java for Android development

166. Recap
• 1. Array vs IntArray
• 2. Iterable vs Sequence
• 3. Iteration
• 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

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

168. Photo:
Alexey Sergeev
Questions?
zsmb.co zsmb13
[email protected]