Share
Embed
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
Márton Braun
May 08, 2018
Transcript
168 slides
-
Array<Int> vs IntArray Array<Int> Integer[] IntArray val arrayOfInts: Array<Int> =
arrayOf(1, 2, 3, 4, 5) -
Array<Int> vs IntArray Array<Int> Integer[] IntArray int[] val arrayOfInts: Array<Int>
= arrayOf(1, 2, 3, 4, 5) -
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) -
Array<Int> vs IntArray • IntArray Avoids boxing Easier
to initialize val intArray = IntArray(10) val arrayOfInts = Array<Int>(5) { i -> i * 2 } -
Array<Int> vs IntArray • IntArray Avoids boxing Easier
to initialize • Array<Int> val intArray = IntArray(10) val arrayOfInts = Array<Int>(5) { i -> i * 2 } -
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 } -
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) -
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) -
val people: List<Person> = getPeople() val allowedEntrance = people .filter
{ it.age >= 21 } .map { it.name } .take(5) Iterable vs Sequence -
val people: List<Person> = getPeople() val allowedEntrance = people .filter
{ it.age >= 21 } .map { it.name } .take(5) Iterable vs Sequence -
val people: List<Person> = getPeople() val allowedEntrance = people .filter
{ it.age >= 21 } .map { it.name } .take(5) Iterable vs Sequence -
val people: List<Person> = getPeople() val allowedEntrance = people .filter
{ it.age >= 21 } .map { it.name } .take(5) Iterable vs Sequence -
val people: List<Person> = getPeople() val allowedEntrance = people .filter
{ it.age >= 21 } .map { it.name } .take(5) Iterable vs Sequence -
val people: List<Person> = getPeople() val allowedEntrance = people .filter
{ it.age >= 21 } .map { it.name } .take(5) Iterable vs Sequence -
val people: List<Person> = getPeople() val allowedEntrance = people .filter
{ it.age >= 21 } .map { it.name } .take(5) Iterable vs Sequence -
val people: List<Person> = getPeople() val allowedEntrance = people .filter
{ it.age >= 21 } .map { it.name } .take(5) Iterable vs Sequence -
val people: List<Person> = getPeople() val allowedEntrance = people .filter
{ it.age >= 21 } .map { it.name } .take(5) Iterable vs Sequence -
val people: List<Person> = getPeople() val allowedEntrance = people .filter
{ it.age >= 21 } .map { it.name } .take(5) Iterable vs Sequence -
val people: List<Person> = getPeople() val allowedEntrance = people .filter
{ it.age >= 21 } .map { it.name } .take(5) Iterable vs Sequence -
val people: List<Person> = getPeople() val allowedEntrance = people .filter
{ it.age >= 21 } .map { it.name } .take(5) Iterable vs Sequence -
val people: List<Person> = getPeople() val allowedEntrance = people .filter
{ it.age >= 21 } .map { it.name } .take(5) Iterable vs Sequence -
val people: List<Person> = getPeople() val allowedEntrance = people .filter
{ it.age >= 21 } .map { it.name } .take(5) Iterable vs Sequence -
val people: List<Person> = getPeople() val allowedEntrance = people .filter
{ it.age >= 21 } .map { it.name } .take(5) Iterable vs Sequence -
val people: List<Person> = getPeople() val allowedEntrance = people .filter
{ it.age >= 21 } .map { it.name } .take(5) Iterable vs Sequence -
val people: List<Person> = getPeople() val allowedEntrance = people .filter
{ it.age >= 21 } .map { it.name } .take(5) Iterable vs Sequence -
val people: List<Person> = getPeople() val allowedEntrance = people .filter
{ it.age >= 21 } .map { it.name } .take(5) Iterable vs Sequence -
val people: List<Person> = getPeople() val allowedEntrance = people .filter
{ it.age >= 21 } .map { it.name } .take(5) Iterable vs Sequence -
val people: List<Person> = getPeople() val allowedEntrance = people .filter
{ it.age >= 21 } .map { it.name } .take(5) Iterable vs Sequence -
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() -
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() -
Iterable vs Sequence val people: List<Person> = getPeople() val allowedEntrance
= people.asSequence() .filter { it.age >= 21 } .map { it.name } .take(5) .toList() -
Iterable vs Sequence val people: List<Person> = getPeople() val allowedEntrance
= people.asSequence() .filter { it.age >= 21 } .map { it.name } .take(5) .toList() -
Iterable vs Sequence val people: List<Person> = getPeople() val allowedEntrance
= people.asSequence() .filter { it.age >= 21 } .map { it.name } .take(5) .toList() -
Iterable vs Sequence val people: List<Person> = getPeople() val allowedEntrance
= people.asSequence() .filter { it.age >= 21 } .map { it.name } .take(5) .toList() -
Iterable vs Sequence val people: List<Person> = getPeople() val allowedEntrance
= people.asSequence() .filter { it.age >= 21 } .map { it.name } .take(5) .toList() -
Iterable vs Sequence val people: List<Person> = getPeople() val allowedEntrance
= people.asSequence() .filter { it.age >= 21 } .map { it.name } .take(5) .toList() -
Iterable vs Sequence val people: List<Person> = getPeople() val allowedEntrance
= people.asSequence() .filter { it.age >= 21 } .map { it.name } .take(5) .toList() -
Iterable vs Sequence val people: List<Person> = getPeople() val allowedEntrance
= people.asSequence() .filter { it.age >= 21 } .map { it.name } .take(5) .toList() -
Iterable vs Sequence val people: List<Person> = getPeople() val allowedEntrance
= people.asSequence() .filter { it.age >= 21 } .map { it.name } .take(5) .toList() -
Iterable vs Sequence val people: List<Person> = getPeople() val allowedEntrance
= people.asSequence() .filter { it.age >= 21 } .map { it.name } .take(5) .toList() -
Iterable vs Sequence val people: List<Person> = getPeople() val allowedEntrance
= people.asSequence() .filter { it.age >= 21 } .map { it.name } .take(5) .toList() -
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() -
Iterable vs Sequence val people: List<Person> = getPeople() val allowedEntrance
= people.asSequence() .filter { it.age >= 21 } .map { it.name } .take(5) .toList() -
Iterable vs Sequence val people: List<Person> = getPeople() val allowedEntrance
= people.asSequence() .filter { it.age >= 21 } .map { it.name } .take(5) .toList() -
Iterable vs Sequence val people: List<Person> = getPeople() val allowedEntrance
= people.asSequence() .filter { it.age >= 21 } .map { it.name } .take(5) .toList() -
Iterable vs Sequence val people: List<Person> = getPeople() val allowedEntrance
= people.asSequence() .filter { it.age >= 21 } .map { it.name } .take(5) .toList() -
Iterable vs Sequence val people: List<Person> = getPeople() val allowedEntrance
= people.asSequence() .filter { it.age >= 21 } .map { it.name } .take(5) .toList() -
Iterable vs Sequence val people: List<Person> = getPeople() val allowedEntrance
= people.asSequence() .filter { it.age >= 21 } .map { it.name } .take(5) .toList() -
Iterable vs Sequence val people: List<Person> = getPeople() val allowedEntrance
= people.asSequence() .filter { it.age >= 21 } .map { it.name } .take(5) .toList() -
Iterable vs Sequence val people: List<Person> = getPeople() val allowedEntrance
= people.asSequence() .filter { it.age >= 21 } .map { it.name } .take(5) .toList() -
Iterable vs Sequence • Iterable Use by default
Usually the best choice -
Iterable vs Sequence • Iterable Use by default
Usually the best choice • Sequence -
Iterable vs Sequence • Iterable Use by default
Usually the best choice • Sequence To handle an infinite number of elements -
Iterable vs Sequence • Iterable Use by default
Usually the best choice • Sequence To handle an infinite number of elements For huge collections, judiciously -
Iterable vs Sequence • Iterable Use by default
Usually the best choice • Sequence To handle an infinite number of elements For huge collections, judiciously • Stream -
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 -
Iteration for (i in 0..args.size - 1) { println(args[i]) }
for (i in 0..args.lastIndex) { println(args[i]) } -
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]) } -
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]) } -
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) } -
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) } -
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) } -
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) } -
SAM conversions public interface OnClickListener { void onClick(Button button); }
public class Button { public void setListener(OnClickListener listener) { ... } } -
SAM conversions button.setListener(object : OnClickListener { override fun onClick(button: Button?)
{ println("Clicked!") } }) -
SAM conversions button.setListener(object : OnClickListener { override fun onClick(button: Button?)
{ println("Clicked!") } }) button.setListener { println("Clicked!") } -
SAM conversions button.setListener(object : OnClickListener { override fun onClick(button: Button?)
{ println("Clicked!") } }) button.setListener { println("Clicked!") } -
SAM conversions button.setListener(object : OnClickListener { override fun onClick(button: Button?)
{ println("Clicked!") } }) button.setListener { button: Button? -> println("Clicked!") } -
SAM conversions #1 button.setListener { object : OnClickListener { override
fun onClick(button: Button) { println("Clicked!") } }) } -
SAM conversions #1 button.setListener { object : OnClickListener { override
fun onClick(button: Button) { println("Clicked!") } }) } -
SAM conversions #1 button.setListener(object : OnClickListener { override fun onClick(button:
Button?) { object : OnClickListener { override fun onClick(button: Button) { println("Clicked!") } }) } }) -
SAM conversions #1 button.setListener(object : OnClickListener { override fun onClick(button:
Button?) { val listener = object : OnClickListener { override fun onClick(button: Button) { println("Clicked!") } }) } }) -
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(...) } }) -
SAM conversions #1 button.setListener(object : OnClickListener { override fun onClick(button:
Button?) { object : OnClickListener { override fun onClick(button: Button) { println("Clicked!") } }) } }) -
SAM conversions #1 button.setListener { object : OnClickListener { override
fun onClick(button: Button) { println("Clicked!") } }) } -
SAM conversions #1 button.setListener { object : OnClickListener { override
fun onClick(button: Button) { println("Clicked!") } }) } button.setListener { fun onClick(button: Button) { println("Clicked!") } } -
SAM conversions #2 public interface OnClickListener { boolean onClick(Button button);
} button.setListener { println("Clicked!") } -
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 -
SAM conversions #2 public interface OnClickListener { boolean onClick(Button button);
} button.setListener { println("Clicked!") true } -
SAM conversions #2 public interface OnClickListener { boolean onClick(Button button);
} button.setListener { println("Clicked!") true } -
Replacing statics class Foo { companion object { fun x()
{ ... } } fun y() { ... } } -
Replacing statics class Foo { companion object { fun x()
{ ... } } fun y() { ... } } Foo.x() -
Replacing statics class Foo { companion object { fun x()
{ ... } } fun y() { ... } } object Foo { fun x() { ... } } Foo.x() Foo.x() -
Replacing statics class Foo { companion object { fun x()
{ ... } } fun y() { ... } } object Foo { fun x() { ... } } fun x() { ... } Foo.x() Foo.x() x() -
Replacing statics class Foo { companion object { fun x()
{ ... } } fun y() { ... } } object Foo { fun x() { ... } } fun x() { ... } Foo.x() Foo.x() x() -
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 -
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 -
Smart casts on mutable properties class Dog(var toy: Toy? =
null) { fun play() { if (toy != null) { toy.chew() } } } -
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 -
Smart casts on mutable properties class Dog(val toy: Toy? =
null) { fun play() { if (toy != null) { toy.chew() } } } -
Smart casts on mutable properties class Dog(var toy: Toy? =
null) { fun play() { if (toy != null) { toy.chew() } } } -
Smart casts on mutable properties class Dog(var toy: Toy? =
null) { fun play() { val _toy = toy if (_toy != null) { _toy.chew() } } } -
Smart casts on mutable properties class Dog(var toy: Toy? =
null) { fun play() { toy?.let { it.chew() } } } -
Smart casts on mutable properties class Dog(var toy: Toy? =
null) { fun play() { toy?.chew() } } -
Smart casts on mutable properties class Dog(var toy: Toy? =
null) { fun play() { toy?.let { it.chew() it.chew() it.chew() } } } -
null!! class Episode { var airdate: Date = null!! }
fun getWeekDay(date: Date?): WeekDay { return date!!.getWeekDay() } -
null!! class Episode { var airdate: Date = null!! }
fun getWeekDay(date: Date?): WeekDay { return date!!.getWeekDay() } Date? -
null!! class Episode { var airdate: Date = null!! }
fun getWeekDay(date: Date?): WeekDay { return date!!.getWeekDay() } WeekDay Date? -
null!! class Episode { var airdate: Date = null!! }
fun getWeekDay(date: Date?): WeekDay { return date!!.getWeekDay() } Date WeekDay Date? -
null!! class Episode { var airdate: Date = null!! }
fun getWeekDay(date: Date?): WeekDay { return date!!.getWeekDay() } Date -
null!! class Episode { var airdate: Date = null!! }
fun getWeekDay(date: Date?): WeekDay { return date!!.getWeekDay() } Date date as Date -
null!! class Episode { var airdate: Date = null!! }
fun getWeekDay(date: Date?): WeekDay { return date!!.getWeekDay() } Date date as Date throw NullPointerException() -
null!! class Episode { var airdate: Date = null!! }
fun getWeekDay(date: Date?): WeekDay { return date!!.getWeekDay() } Date -
Platform types in overrides How do I choose the right
type when overriding Java methods? -
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}") } } -
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}") } } -
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}") } } -
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}") } } -
Import aliases package com.example.code fun indent(str: String) : String {
... } package com.example.square fun indent(str: String) : String { ... } -
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") -
Import aliases package com.example.code fun String.indent() : String { ...
} package com.example.square fun String.indent() : String { ... } -
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() -
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() -
Import aliases import java.util.Date as UtilDate import java.sql.Date as SqlDate
fun matches(date1: UtilDate, date2: SqlDate): Boolean { ... } -
Recap • 1. Array<Int> 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 -
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