Comparison of SAM conversion between Kotlin and java8

What is sam conversion

Single Abstract Method is actually a concept proposed in java8. You can understand it as a method interface

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");
            }
        });

 


It is also possible to write with the lambda in java8 below.

executorService.execute(()->System.out.println("hello world"));

 



So the two writing methods are equivalent. But the point to be stressed here is that there is no type of lambda in java, so he must need an interface to accept it.

sam in kotlin

 val executorService: ExecutorService = Executors.newScheduledThreadPool(3)
    //kotlin The standard writing method of anonymous inner class in
    executorService.submit(object :Runnable{
        override fun run() {
            System.out.println("hello world")
        }

    })

 

    


lambda in kotlin can be written here

 executorService.submit { System.out.println("hello world") }

 



Note here that java's lambda has no type, but kotlin's lambda has type.

In the example above, the type of kotlin's lambda is () - > unit, which has no parameters and no return value

 

 

For lambda in kotlin, look at the above figure carefully.

In fact, a runnable is created and a lambda is wrapped in the runnable, which is not directly transformed.

  //kotlin Anonymous inner classes in can also be written in this way
    executorService.submit(Runnable { println("hello world") })
 

Let's explain the above code again. When the compiler of kotlin encounters the above code again, it actually helps us generate a function

The purpose of this function is to receive a lambda expression and generate the corresponding code for us

Pit of sam conversion in kotlin

The lambda in java is fake, just a sam. kotlin's lambda is true, but he supports sam. It supports sam conversion.

Here is a kotlin interface and kotlin method

interface Invokable{
    fun invoke()
}


fun submit(invokable: Invokable){
    invokable.invoke()
}
 

Then let's look at the call:

Look at the cause of the error

Type mismatch: inferred type is () -> Unit but Invokable was expected

It indicates that we need an invokable here, but give a lambda, which does not meet the requirements, so the compilation cannot pass.

That's understandable. I've already talked about it.

fun submit2(block:()->Unit){
    block.invoke()
}
 

If we define such a function, it is obviously OK. You can use lambda directly.

Of course, if you write this every time, the function parameters are also hard to write, so let's just create an alias

typealias Funtionx = () -> Unit

fun submit2(block: Funtionx) {
    block.invoke()
}
 

In addition, when using sam conversion in kotlin, you must be careful with the write method of remove, for example:

We 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);
    }


}

 

Now, kotlin code, we need to add a monitor

 val eventManager = EventManager()
    eventManager.addOnEventListener {
        println("onEvent$it")
    }
 

lambda is very convenient to write, but you should be careful. You can't remove it if you write like this. If you think about it carefully, the above formula is

 eventManager.addOnEventListener(object : EventManager.OnEventListener {
        override fun onEvent(event: Int) {
            {
                println("onEvent$event")
            }()
        }
    })
 

It's the same as

 eventManager.addOnEventListener(object : EventManager.OnEventListener {
        override fun onEvent(event: Int) {
            println("onEvent$event")
        }
    })
 

This process of creating anonymous objects has been done by the compiler. You can't touch this object.

So naturally there is no way to remove.

In this case, we can write as follows:

 val onEvent = EventManager.OnEventListener {
        println("onEvent$it")

    }

    eventManager.addOnEventListener(onEvent)
    eventManager.removeEventListener(onEvent)

 

perhaps
val onEvent2 = object : EventManager.OnEventListener {
        override fun onEvent(event: Int) {
            println("onEvent$event")
        }

    }
 

Although this kind of writing is ugly, it is concise and comprehensive, without ambiguity or error.

 

"The Qing Dynasty was closed to the outside world, and learning technology required exchanges and information.". Here I have prepared a lot of learning materials for you to get for free, including but not limited to java advanced learning materials, technical dry goods, large factory interview questions series, technical trends, career and other related programmer sharing

java advanced method notes, learning materials, interview questions, e-books for free, let you become the God of java Go to the top of life

Tags: Java Lambda

Posted on Wed, 03 Jun 2020 05:42:37 -0400 by TempleDMDKrazd