Kotlin入坑基礎(chǔ)篇二

Kotlin入坑基礎(chǔ)篇一

這一篇主要講解kotlin進(jìn)階抬驴,內(nèi)容主要有以下:
空安全
kotlin單例
函數(shù)擴(kuò)展
智能轉(zhuǎn)換

空安全

Kotlin中添加了對空的保護(hù)

fun testKotlinNPE() {
        var s: String = "Hubery"
        s = null//會導(dǎo)致編譯不過
        var s2: String? = "Hubery"
        s2 = null//s2可以為空瑟枫,能夠編譯通過

        print(s.length)//因?yàn)椴粸榭蘸酶郏灾苯诱{(diào)用length不會出現(xiàn)異常

        print(s2.length)//編譯不通過俭缓,會要求添加?.或者!!.進(jìn)行調(diào)用
        print(s2!!.length)//編譯能夠通過琴拧,不過s2如果是null踩衩,那么將會導(dǎo)致調(diào)用length的時候出現(xiàn)空指針
        print(s2?.length)//使用安全操作符责静,如果s2為null墨缘,那么就不會調(diào)用length星虹,也就不會導(dǎo)致異常零抬,不過需要注意的是s2?.length可能整體為null;如果別的地方使用需要注意

        //Elvis操作符   
        val i = s2?.length ?:0//如果s2為空宽涌,那么就不會調(diào)用.length方法平夜,而直接返回右邊的0
    }

使用Elvis操作符,可以val i = s2?.length ?:0如果s2為空卸亮,那么就不會調(diào)用.length方法忽妒,而直接返回右邊的0。

kotlin單例

我們都知道單例分為懶漢式與餓漢式兼贸,同時可以對單例進(jìn)行線程同步等段直;
我們先來看看一個java的例子:

/**
 * Created by hubery on 2018/7/18.
 * 餓漢模式
 */
public class DemoSingleton {
    private static DemoSingleton INSTANCE = new DemoSingleton();

    public static DemoSingleton getInstance() {
        return INSTANCE;
    }
}

上面展示的例子就是java的餓漢式模式;那么kotlin的餓漢模式是怎么樣的呢溶诞?

/**
 * Created by hubery on 2018/7/18.
 * kotlin的惡漢模式
 */
object DemoSingleton

沒有看錯就只有一句話鸯檬,關(guān)鍵字object修飾。當(dāng)然這里因?yàn)轭惱锩鏇]有方法因此省略了{},因?yàn)閼袧h式是非線程安全的螺垢,多線程中使用可能會出現(xiàn)創(chuàng)建多個對象喧务,因此,我們需要用到懶漢式單例枉圃,我們把上面的例子稍微改造一下:

public class DemoSingleton {
    private static DemoSingleton INSTANCE;

    public static DemoSingleton getInstance() {
        if(INSTANCE == null){
            INSTANCE = new DemoSingleton();
        }
        return INSTANCE;
    }
}

上面的java例子也就相比之前的餓漢式多了一個null的判斷蹂楣,再看看kotlin的實(shí)現(xiàn):

/**
 * Created by hubery on 2018/7/18.
 * kotlin的懶漢式單例
 */
class DemoSingleton {
    companion object {
        val INSTANCE by lazy(LazyThreadSafetyMode.NONE) {
            DemoSingleton()
        }
    }
}

kotlin的懶漢式單例中使用到了伴生對象companion object,它相當(dāng)于java中的公共靜態(tài)讯蒲,然后使用到了LazyThreadSafetyMode枚舉里面的NONE痊土;

public enum class LazyThreadSafetyMode {
    /**
     * Locks are used to ensure that only a single thread can initialize the [Lazy] instance.
     */
    SYNCHRONIZED,
    /**
     * Initializer function can be called several times on concurrent access to uninitialized [Lazy] instance value,
     * but only the first returned value will be used as the value of [Lazy] instance.
     */
    PUBLICATION,
    /**
     * No locks are used to synchronize an access to the [Lazy] instance value; if the instance is accessed from multiple threads, its behavior is undefined.
     *
     * This mode should not be used unless the [Lazy] instance is guaranteed never to be initialized from more than one thread.
     */
    NONE,
}

通過上面的注釋,可以看出NONE表示是沒有加鎖墨林,因此不是線程安全的赁酝,當(dāng)然也可以使用SYNCHRONIZED,PUBLICATION

上面的例子都會有線程安全問題旭等,現(xiàn)在我們繼續(xù)對代碼進(jìn)行改進(jìn)酌呆,使用SYNCHRONIZED進(jìn)行加鎖:

/**
 * Created by hubery on 2018/7/18.
 * 懶漢模式
 */
public class DemoSingleton {
    private static DemoSingleton INSTANCE;

    public static synchronized DemoSingleton getInstance() {
        if(INSTANCE == null){
            INSTANCE = new DemoSingleton();
        }
        return INSTANCE;
    }
}

同樣的kotlin也可以使用synchronized進(jìn)行加鎖:

/**
 * Created by hubery on 2018/7/18.
 * kotlin的懶漢式單例
 */
class DemoSingleton {
    companion object {
        private var INSTANCE:DemoSingleton? = null

        @Synchronized
        fun getInstance():DemoSingleton{
            if(INSTANCE == null){
                INSTANCE = DemoSingleton()
            }
            return INSTANCE!!
        }
    }
}

kotlin中使用的是@Synchronized注解方式達(dá)到同步的效果;同樣的搔耕,我們知道上面的例子同樣存在不足隙袁,我們要實(shí)現(xiàn)只有第一次獲取的時候才會加鎖,那么我們使用雙重檢測弃榨。

/**
 * Created by hubery on 2018/7/18.
 * 懶漢模式
 */
public class DemoSingleton {
    private static volatile DemoSingleton INSTANCE;
    public static DemoSingleton getInstance() {
        if (INSTANCE == null) {
            synchronized (DemoSingleton.class) {
                if (INSTANCE == null) {
                    INSTANCE = new DemoSingleton();
                }
            }
        }
        return INSTANCE;
    }
}

使用kotlin實(shí)現(xiàn)

/**
 * Created by hubery on 2018/7/18.
 * kotlin的懶漢式單例
 */
class DemoSingleton {
    companion object {
        val INSTANCE by lazy(LazyThreadSafetyMode.SYNCHRONIZED) {
            DemoSingleton()
        }
    }
}

最后說一下內(nèi)部類式

public class DemoSingleton {
    private DemoSingleton() {
    }

    private static class Instance {
        private static DemoSingleton singleton = new DemoSingleton();
    }

    public static DemoSingleton getInstance() {
        return Instance.singleton;
    }
}

kotlin的寫法

class DemoSingleton {
    companion object {
        fun getInstance() = Instance.INSTANCE
    }

    private object Instance {
        val INSTANCE = DemoSingleton()
    }
}

利用了classloader的機(jī)制來保證初始化instance時只有一個線程菩收,所以也是線程安全的,同時沒有性能損耗鲸睛。
對比kotlin和java的單例娜饵,總體說來kotlin的單例比java單例實(shí)現(xiàn)代碼更加的簡潔,且kotlin語言對單例的支持更加的友好官辈。

函數(shù)擴(kuò)展

擴(kuò)展函數(shù)可以在已有類中添加新的方法箱舞,不會對原類做修改遍坟,擴(kuò)展函數(shù)定義形式。其中擴(kuò)展函數(shù)的參數(shù)可以為空晴股。

fun 擴(kuò)展函數(shù)的對象.擴(kuò)展函數(shù)的名字(擴(kuò)展函數(shù)的參數(shù)){

}

先來看看基本的函數(shù)擴(kuò)展:

open class Personal(var name: String) {
}

/**
 * 擴(kuò)展函數(shù)
 */
fun Personal.test(name: String): String {
    return "這是一個擴(kuò)展類愿伴,名字=$name"
}

/**
 * 方法測試
 */
fun test(){
    var personal = Personal("Hubery")
    personal.test("test()")
}

上面的例子展示了為Personal對象擴(kuò)展一個test方法;

擴(kuò)展函數(shù)是靜態(tài)解析的电湘,并不是接收者類型的虛擬成員公般,在調(diào)用擴(kuò)展函數(shù)時,具體被調(diào)用的的是哪一個函數(shù)胡桨,由調(diào)用函數(shù)的的對象表達(dá)式來決定的官帘,而不是動態(tài)的類型決定的:

擴(kuò)展函數(shù)不僅可以擴(kuò)展方法,還可以對屬性進(jìn)行擴(kuò)展昧谊,或者伴生類進(jìn)行函數(shù)或者屬性進(jìn)行擴(kuò)展刽虹。

智能轉(zhuǎn)換

關(guān)于智能轉(zhuǎn)換,我們用一個例子來說明呢诬,先來看看java中的例子:

public interface Ball {
        void pay(String name);
    }

    class BasketBall implements Ball {
        @Override
        public void pay(String name) {
        }
    }

    class FootBall implements Ball {
        @Override
        public void pay(String name) {
        }
    }

    void test(Ball ball) {
        if (ball instanceof BasketBall) {//籃球
            BasketBall basketBall = (BasketBall) ball;
            basketBall.pay("籃球");
        } else if (ball instanceof FootBall) {
            FootBall footBall = (FootBall) ball;
            footBall.pay("足球");
        }
    }

定義一個Ball接口涌哲,那么分別用BasketBall,FootBall去實(shí)現(xiàn)它,在測試的時候尚镰,分別用instanceof去判斷阀圾,然后再分別強(qiáng)轉(zhuǎn)成相應(yīng)的類型。

interface Ball {
    fun pay(name: String) {
        print("pay() 我們正在玩$name")
    }
}

class BasketBall : Ball {
    override fun pay(name: String) {
        super.pay(name)
    }

    fun basketBallPay() {

    }
}

class FootBall : Ball {
    override fun pay(name: String) {
        super.pay(name)
    }

    fun footBallPay() {

    }
}

fun test(ball: Ball) {
    if (ball is BasketBall) {
        var basketBall = ball.basketBallPay()
        ball.pay("籃球")
    } else if (ball is FootBall) {
        var footBall = ball.footBallPay()
        ball.pay("足球")
    }
}

由上面可以看到狗唉,kotlin在使用的時候不同于java需要強(qiáng)制轉(zhuǎn)換初烘,kotlin它合并了類型檢查和轉(zhuǎn)換。這就是kotlin的智能轉(zhuǎn)換分俯。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末肾筐,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子缸剪,更是在濱河造成了極大的恐慌吗铐,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,639評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件杏节,死亡現(xiàn)場離奇詭異唬渗,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)奋渔,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,277評論 3 385
  • 文/潘曉璐 我一進(jìn)店門镊逝,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人卒稳,你說我怎么就攤上這事蹋半。” “怎么了充坑?”我有些...
    開封第一講書人閱讀 157,221評論 0 348
  • 文/不壞的土叔 我叫張陵减江,是天一觀的道長。 經(jīng)常有香客問我捻爷,道長辈灼,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,474評論 1 283
  • 正文 為了忘掉前任也榄,我火速辦了婚禮巡莹,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘甜紫。我一直安慰自己降宅,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,570評論 6 386
  • 文/花漫 我一把揭開白布囚霸。 她就那樣靜靜地躺著腰根,像睡著了一般。 火紅的嫁衣襯著肌膚如雪拓型。 梳的紋絲不亂的頭發(fā)上额嘿,一...
    開封第一講書人閱讀 49,816評論 1 290
  • 那天,我揣著相機(jī)與錄音劣挫,去河邊找鬼册养。 笑死,一個胖子當(dāng)著我的面吹牛压固,可吹牛的內(nèi)容都是我干的球拦。 我是一名探鬼主播,決...
    沈念sama閱讀 38,957評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼帐我,長吁一口氣:“原來是場噩夢啊……” “哼刘莹!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起焚刚,我...
    開封第一講書人閱讀 37,718評論 0 266
  • 序言:老撾萬榮一對情侶失蹤点弯,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后矿咕,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體抢肛,經(jīng)...
    沈念sama閱讀 44,176評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,511評論 2 327
  • 正文 我和宋清朗相戀三年碳柱,在試婚紗的時候發(fā)現(xiàn)自己被綠了捡絮。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,646評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡莲镣,死狀恐怖福稳,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情瑞侮,我是刑警寧澤的圆,帶...
    沈念sama閱讀 34,322評論 4 330
  • 正文 年R本政府宣布鼓拧,位于F島的核電站,受9級特大地震影響越妈,放射性物質(zhì)發(fā)生泄漏季俩。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,934評論 3 313
  • 文/蒙蒙 一梅掠、第九天 我趴在偏房一處隱蔽的房頂上張望酌住。 院中可真熱鬧,春花似錦阎抒、人聲如沸酪我。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,755評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽都哭。三九已至,卻和暖如春谴古,著一層夾襖步出監(jiān)牢的瞬間质涛,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,987評論 1 266
  • 我被黑心中介騙來泰國打工掰担, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留汇陆,地道東北人。 一個月前我還...
    沈念sama閱讀 46,358評論 2 360
  • 正文 我出身青樓带饱,卻偏偏與公主長得像毡代,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子勺疼,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,514評論 2 348

推薦閱讀更多精彩內(nèi)容