What is Sam transformation
Single Abstract Method is actually a java8 concept that you can think of as an interface to a Method
Take a look at the thread pool we use every day
ExecutorService executorService= Executors.newScheduledThreadPool(3);
executorService.execute(new Runnable() {
@Override
public void run() {
System.out.println("hello world"); }});Copy the code
It is also possible to write using lambda in java8 below.
executorService.execute(()->System.out.println("hello world"));
Copy the code
So these two ways are equivalent. But it is important to note that lambdas in Java are untyped, so they must need an interface to accept them.
Sam in the kotlin
val executorService: ExecutorService = Executors. NewScheduledThreadPool (3) / / kotlin anonymous inner class standard in writing the ExecutorService. Submit (object: a Runnable { override funrun() {
System.out.println("hello world")}})Copy the code
Lambda in Kotlin could be written this way
executorService.submit { System.out.println("hello world")}Copy the code
Note here that Java lambdas are untyped, but Kotlin lambdas are typed.
The type of kotlin’s lambda in the example above is ()->Unit is a type with no arguments and no return value
For the lambda in Kotlin, take a closer look at the figure above.
This is actually creating a runnable and wrapping a lambda around the runnable, not a direct conversion.
Executorservice. submit(Runnable {println())"hello world")})Copy the code
When kotlin’s compiler encounters the above code, it actually generates a function for us
All this does is take a lambda expression and help us generate the corresponding code
Pit for Sam conversion in Kotlin
Lambda in Java is fake, just a Sam. Kotlin’s lambda is real, except he supports Sam. Sam conversion is supported.
Let’s define a Kotlin interface and a Kotlin method
interface Invokable{
fun invoke()
}
fun submit(invokable: Invokable){
invokable.invoke()
}
Copy the code
Then let’s look at the call:
Look at the reason for the error
Type mismatch: inferred type is () -> Unit but Invokable was expected
We need an invokable, but we gave a lambda, so the compile failed.
This is understandable. We’ve already talked about this.
fun submit2(block:()->Unit){
block.invoke()
}
Copy the code
If we define a function that looks like this then obviously it works. You can use lambda directly.
Of course, if you do this every time, it’s going to be a little bit harder to write the parameters, so we’ll just give it a different name
typealias Funtionx = () -> Unit
fun submit2(block: Funtionx) {
block.invoke()
}
Copy the code
When using Sam conversions in Kotlin, be careful to write remove. For example:
Let’s define a simple event class:
public class EventManager { interface OnEventListener { void onEvent(int event); } private List<OnEventListener> onEventListeners=new ArrayList<OnEventListener>(); public void addOnEventListener(OnEventListener listener){ onEventListeners.add(listener); } public void removeEventListener(OnEventListener listener){ onEventListeners.remove(listener); }}Copy the code
Now kotlin code we’re going to add a listener
val eventManager = EventManager()
eventManager.addOnEventListener {
println("onEvent$it")}Copy the code
Lambda is easy to write, but be careful, you can’t remove lambda if you write it this way. If you think about it, the way it’s written is equivalent to
eventManager.addOnEventListener(object : EventManager.OnEventListener {
override fun onEvent(event: Int) {
{
println("onEvent$event")}}}) ()Copy the code
Also,
eventManager.addOnEventListener(object : EventManager.OnEventListener {
override fun onEvent(event: Int) {
println("onEvent$event")}})Copy the code
The process of creating an anonymous object is done by the compiler, so you can’t touch the object.
So there’s no way to remove it.
If you need remove, you can write it like this:
val onEvent = EventManager.OnEventListener {
println("onEvent$it")
}
eventManager.addOnEventListener(onEvent)
eventManager.removeEventListener(onEvent)
Copy the code
or
val onEvent2 = object : EventManager.OnEventListener {
override fun onEvent(event: Int) {
println("onEvent$event")}}Copy the code
Although this writing method is ugly ugly, but concise and comprehensive, no ambiguity will not make mistakes.