Single Abstract Method 实际上这是java8中提出的概念,你就把他理解为是一个方法的接口的就能够了java
看一下咱们天天都在使用的线程池bash
ExecutorService executorService= Executors.newScheduledThreadPool(3);
executorService.execute(new Runnable() {
@Override
public void run() {
System.out.println("hello world");
}
});
复制代码
用下面的java8中的lambda 来写 也是能够的。ide
executorService.execute(()->System.out.println("hello world"));
复制代码
因此说 这两种写法是等价的。 可是这里要强调的是 java中的lambda是没有类型的,因此他必须须要一个接口来接受他。函数
val executorService: ExecutorService = Executors.newScheduledThreadPool(3)
//kotlin中的 匿名内部类的标准写法
executorService.submit(object :Runnable{
override fun run() {
System.out.println("hello world")
}
})
复制代码
kotlin中的lambda 这里能够这么写spa
executorService.submit { System.out.println("hello world") }
复制代码
这里要注意的是 java的lambda是没有类型的,可是kotlin的lambda有类型。线程
上文中的例子 这个kotlin的lambda的类型就是 ()->Unit 是一个没有参数也没有返回值的类型3d
对于kotlin中的lambda来讲,仔细看上面的图 就能够知道。code
这里其实是建立了一个runnable 而且在这个runnable里面包装了一下lambda,并非直接转换的。cdn
//kotlin中 匿名内部类 还能够这么写
executorService.submit(Runnable { println("hello world") })
复制代码
上面的代码 咱们再解释一下 ,kotlin的编译器 再遇到上面的代码的时候 实际上 是帮咱们生成了 一个函数对象
这个函数的做用就是接收一个 lambda表达式 而后帮咱们生成对应的代码
java中的lambda是假的,只是一个sam而已。 kotlin的lambda是真的,只不过他还支持sam。是支持sam转换的。
下面定义一个kotlin的接口 以及kotlin的方法
interface Invokable{
fun invoke()
}
fun submit(invokable: Invokable){
invokable.invoke()
}
复制代码
而后咱们看看调用:
看看报错的缘由
Type mismatch: inferred type is () -> Unit but Invokable was expected
提示咱们 这里 是须要一个invokable,可是给了一个lambda ,不符合要求,因此编译不能经过。
这个能够理解吧,前面已经讲过了。
fun submit2(block:()->Unit){
block.invoke()
}
复制代码
若是咱们定义一个这样的函数 那显然就是能够的了。就能够直接使用lambda了。
固然若是每次这么写,函数参数也比较难写,因此咱们干脆 就起个别名
typealias Funtionx = () -> Unit
fun submit2(block: Funtionx) {
block.invoke()
}
复制代码
另外就是在kotlin中使用sam转换的时候 必定要当心remove的写法,例如:
咱们定义一个简单的event类:
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);
}
}
复制代码
如今 kotlin代码 咱们要add 一个监听
val eventManager = EventManager()
eventManager.addOnEventListener {
println("onEvent$it")
}
复制代码
lambda写起来很方便,可是你要当心了,你这么写的话 你是没办法remove的。 你仔细想想,上面的写法 等因而
eventManager.addOnEventListener(object : EventManager.OnEventListener {
override fun onEvent(event: Int) {
{
println("onEvent$event")
}()
}
})
复制代码
也等因而
eventManager.addOnEventListener(object : EventManager.OnEventListener {
override fun onEvent(event: Int) {
println("onEvent$event")
}
})
复制代码
这个建立匿名对象的过程 被编译器作了,你是接触不到这个object的。
因此天然也就没办法去remove了。
遇到这种须要remove的状况 咱们就能够用以下写法:
val onEvent = EventManager.OnEventListener {
println("onEvent$it")
}
eventManager.addOnEventListener(onEvent)
eventManager.removeEventListener(onEvent)
复制代码
或者
val onEvent2 = object : EventManager.OnEventListener {
override fun onEvent(event: Int) {
println("onEvent$event")
}
}
复制代码
这种写法虽然丑是丑了一点,可是言简意赅,不会出歧义 也不会出错。