I’m trying to figure out the exact rules for Single-Abstract-Method (SAM) conversion in kotlin.
Here’s the example from the Try Kotlin Page:
fun getList(): List<Int> {
val arrayList = arrayListOf(1, 5, 2)
Collections.sort(arrayList, { x, y -> y - x })
return arrayList
}
This compiles fine, as it should. Now, if we pull out the function argument into a variable:
fun getList(): List<Int> {
val arrayList = arrayListOf(1, 5, 2)
val compare: (Int, Int) -> Int = { x, y -> y - x }
Collections.sort(arrayList, compare)
return arrayList
}
… it still compiles, as expected.
Now, consider the following example:
fun thisDoesNotCompile(){
val handlers = mutableListOf<java.util.function.Consumer<String>>()
val handler: (String)->Unit = {s: String ->println(s)}
handlers.add(handler) // <- compile error here, "handler" has wrong type
}
I can’t really spot the difference to the previous example. (String)->Unit
should be equivalent to Consumer<String>
in terms of SAM conversion, yet the compiler complains that:
Required:
Consumer<String>
Found:
(String) -> Unit
Can anybody explain to me what happens here, specifically: why does the call to Collections.sort(...)
compile with SAM conversion, but the call to List#add(...)
does not? In Java, both are fine and it puzzles me that the kotlin compiler disagrees here.