Kotlin與java8的SAM轉(zhuǎn)換對(duì)比(進(jìn)階)
什么是sam 轉(zhuǎn)換
Single Abstract Method 實(shí)際上這是java8中提出的概念,你就把他理解為是 一個(gè)方法的接口 的就可以了
看一下我們每天都在使用的線程池
ExecutorService executorService= Executors.newScheduledThreadPool(3);
executorService.execute(new Runnable() {
@Override
public void run() {
System.out.println("hello world");
}
});
用下面的java8中的lambda 來寫 也是可以的。
xecutorService.execute(()->System.out.println("hello world"));
所以說 這兩種寫法是 等價(jià) 的。 但是這里要強(qiáng)調(diào)的是 java中的lambda是沒有類型的,所以他必須需要一個(gè)接口來接受他。
kotlin中的sam
val executorService: ExecutorService = Executors.newScheduledThreadPool(3)
//kotlin中的 匿名內(nèi)部類的標(biāo)準(zhǔn)寫法
executorService.submit(object :Runnable{
override fun run() {
System.out.println("hello world")
}
})
kotlin中的lambda 這里可以這么寫
executorService.submit { System.out.println("hello world") }
這里要注意的是 java的lambda是沒有類型的,但是kotlin的lambda有類型 。
上文中的例子 這個(gè)kotlin的lambda的類型就是 ()->Unit 是一個(gè)沒有參數(shù)也沒有返回值的類型

對(duì)于kotlin中的lambda來說,仔細(xì)看上面的圖 就可以知道。
這里實(shí)際上是創(chuàng)建了一個(gè)runnable 并且在這個(gè)runnable里面 包裝了一下lambda,并不是直接轉(zhuǎn)換的 。
//kotlin中 匿名內(nèi)部類 還可以這么寫
executorService.submit(Runnable { println("hello world") })
上面的代碼 我們?cè)俳忉屢幌?,kotlin的編譯器 再遇到上面的代碼的時(shí)候 實(shí)際上 是 幫我們生成了 一個(gè)函數(shù)

這個(gè)函數(shù)的作用就是接收一個(gè) lambda表達(dá)式 然后幫我們生成對(duì)應(yīng)的代碼
kotlin中sam 轉(zhuǎn)換的坑
java中的lambda是假的,只是一個(gè)sam而已。 kotlin的lambda是真的,只不過他還支持sam。是支持sam轉(zhuǎn)換的。
下面定義一個(gè)kotlin的接口 以及kotlin的方法
interface Invokable{
fun invoke()
}
fun submit(invokable: Invokable){
invokable.invoke()
}
然后我們看看調(diào)用:

看看報(bào)錯(cuò)的原因
Type mismatch: inferred type is () -> Unit but Invokable was expected
提示我們 這里 是需要一個(gè)invokable,但是給了一個(gè)lambda ,不符合要求,所以編譯不能通過。
這個(gè)可以理解吧,前面已經(jīng)講過了。
fun submit2(block:()->Unit){
block.invoke()
}
如果我們定義一個(gè)這樣的函數(shù) 那顯然就是可以的了。就可以直接使用lambda了。
當(dāng)然如果每次這么寫,函數(shù)參數(shù)也比較難寫,所以我們干脆 就起個(gè)別名
typealias Funtionx = () -> Unit
fun submit2(block: Funtionx) {
block.invoke()
}
另外就是在kotlin中使用sam轉(zhuǎn)換的時(shí)候 一定要小心remove的寫法,例如:
我們定義一個(gè)簡單的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);
}
}
現(xiàn)在 kotlin代碼 我們要add 一個(gè)監(jiān)聽
val eventManager = EventManager()
eventManager.addOnEventListener {
println("onEvent$it")
}
lambda寫起來很方便,但是你要小心了,你這么寫的話 你是沒辦法remove的。 你仔細(xì)想一想,上面的寫法 等于是
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")
}
})
這個(gè)創(chuàng)建匿名對(duì)象的過程 被編譯器做了,你是接觸不到這個(gè)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")
}
}
這種寫法雖然丑是丑了一點(diǎn),但是言簡意賅,不會(huì)出歧義 也不會(huì)出錯(cuò)。
到此這篇關(guān)于Kotlin與java8的SAM轉(zhuǎn)換對(duì)比的文章就介紹到這了,更多相關(guān)Kotlin與java8的SAM轉(zhuǎn)換 內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java Socket編程簡介_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理
這篇文章主要介紹了Java Socket編程簡介的相關(guān)知識(shí),非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下2017-05-05
Spring解決循環(huán)依賴的方法(三級(jí)緩存)
今天,我們要說的是spring是如何解決循環(huán)依賴的。對(duì)于一個(gè)問題說解決之前,我們首先要先明確形成問題的本因。那么循環(huán)依賴,何為循環(huán)依賴呢?感興趣的朋友跟隨小編一起看看吧2021-11-11
Spring?Boot?如何生成微信小程序短連接及發(fā)送短信在短信中打開小程序操作
最近遇到這樣的需求需要發(fā)送短信,通過短信中的短連接打開小程序操作,下面小編給大家分享Spring?Boot?如何生成微信小程序短連接發(fā)送短信在短信中打開小程序操作,感興趣的朋友跟隨小編一起看看吧2024-03-03
Spring?cloud?實(shí)現(xiàn)房源查詢功能的實(shí)例代碼
這篇文章主要介紹了Spring?cloud?實(shí)現(xiàn)房源查詢功能,本項(xiàng)目是一個(gè)多模塊項(xiàng)目,創(chuàng)建一個(gè) Spring Initializr 項(xiàng)目 不自動(dòng)添加依賴項(xiàng),完成創(chuàng)建后刪除自帶的src目錄,并在根目錄下創(chuàng)建新的maven模塊,需要的朋友可以參考下2022-09-09
java并發(fā)請(qǐng)求下數(shù)據(jù)插入重復(fù)問題的解決方法
現(xiàn)在遇到一個(gè)項(xiàng)目,移動(dòng)設(shè)備存儲(chǔ)數(shù)據(jù),然后一起上傳,那就出現(xiàn)了許多重復(fù)數(shù)據(jù),這篇文章主要給大家介紹了關(guān)于java并發(fā)請(qǐng)求下數(shù)據(jù)插入重復(fù)問題的解決方法,需要的朋友可以參考下2021-11-11
maven打包zip包含bin下啟動(dòng)腳本的完整代碼
這篇文章主要介紹了maven打包zip包含bin下啟動(dòng)腳本,本文給大家講解的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-10-10
SpringBoot Redis用注釋實(shí)現(xiàn)接口限流詳解
Redis 除了做緩存,還能干很多很多事情:分布式鎖、限流、處理請(qǐng)求接口冪等性。。。太多太多了~今天想和小伙伴們聊聊用 Redis 處理接口限流,這也是最近的 項(xiàng)目涉及到這個(gè)知識(shí)點(diǎn)了,我就拎出來和大家聊聊這個(gè)話題2022-07-07

