第一章 Kotlin基礎(chǔ)語法

一、常量與變量(val,var)

  • 1.什么是常量?

1 .val = value ,值類型;
2.類似Java的final;
3.不能重復(fù)賦值;
4.舉例:
運行時常量:val x = getX(); 也就是程序運行時才賦值喜每;
編譯期常量:const val x = 2 ;也就是在編譯時期就賦值了务唐;

  • 2.什么是變量?

1.var=variable ;
2.可以再次賦值带兜;
3.舉例:
var x = "HelloWorld"http://定義變量
x = "HiWorld"http://再次賦值

示例如下:

/**
 * 常量
 * 帶const為編譯期的常量
 * 不帶const的val為運行期常量
 * 不能再次賦值
 */
const val FINAL_HELLO_WORLD:String = "Hello world"

//變量 能夠再次賦值
var helloworld:String = FINAL_HELLO_WORLD

二枫笛、類型推導(dǎo)

val string = "Hello"http://推導(dǎo)出String類型
val int = 5 //Int類型
var x = getString()+5 //String類型,加號在這里是連接符

三刚照、函數(shù)--單一原則:

1.任何函數(shù)都是以fun開頭的刑巧,緊接著的是方法名字,緊接著的是參數(shù)列表无畔,緊接著的是返回值啊楚,緊接著是函數(shù)體;
fun <MethodName>(<ParamsName>:<ParamsType>):<returnValue>{}
2.如果無返回值浑彰,可以寫:Unit或者在參數(shù)列表后什么都寫特幔;Unit類型Java中的void;
3.如果參數(shù)有多個,以逗號分開闸昨;
4.如果一個函數(shù)只是返回一個函數(shù)的表達式的值蚯斯,直接可以等于表達式即可;
5.函數(shù)的名字不是必須的饵较,如果有個變量接受返回值即可編譯通過拍嵌;--請看下面的例子
6.函數(shù)作為類型的一種出現(xiàn)的,可以被用來賦值與傳遞的循诉;

/**
 * 函數(shù)
 * methodName
 * param1,param2是參數(shù)名
 * String Int 是參數(shù)類型
 * 備注:
 * 1.任何函數(shù)都是以fun開頭的横辆;
 * 2.如果參數(shù)有多個,以逗號分開茄猫;
 * 3沒有返回值在參數(shù)后添加:Unit狈蚤,也可以不寫,這個Unit相當(dāng)于java里面的void划纽;
 * 4如果一個函數(shù)只是返回一個函數(shù)的表達式的值脆侮,直接可以等于表達式即可;
 */
fun methodName(param1:String,param2:Int):Unit {

}

//帶返回值的函數(shù)
fun testMethod(args:String):String{
    return args
}

/**
 * 如果一個函數(shù)只是返回一個函數(shù)的表達式的值勇劣,直接可以等于表達式即可
 */
fun returnFun0(param1: Int, param2: Int):Int {
    return param1+param2
}
//上面的等價于下面的寫法:
fun returnFun(param1:Int,param2:Int) = param1+param2

/**
 * 函數(shù)可以沒有名字的靖避,如果有一個變量來接收的話即可
 */
val resultValue = fun(x: Int):Int {
    return x
}

四、Lambda表達式

1.也就是匿名函數(shù)比默;函數(shù)作為類型的一種出現(xiàn)的幻捏,可以被用來賦值與傳遞的;
2.寫法:{[參數(shù)列表] ->[函數(shù)體命咐,最后一行是返回值]}
3.() -> Unit
--無參篡九,返回值為Unit;
4.(Int) -> Int
--有參-傳入Int類型醋奠,返回一個整數(shù)榛臼;
5.(String,(String) -> String) -> Boolean
--傳入字符串伊佃、Lambda表達式,返回Boolean讽坏;

  • 1.Lambda表達式的調(diào)用

1.用括號()來表示方法的調(diào)用锭魔,是Kotlin中的運算符,等價于invoke();這個invoke其實是運算符重載的方法
2.Lambda表達式如果沒有參數(shù)路呜,箭頭 (->)就不用寫了迷捧;
3.Lambda表達式不是只有一行的,它的返回值是它表達式的最后一行的值胀葱;

val sum = {a:Int,b:Int ->a+b}
//用括號()來調(diào)用漠秋,等價于invoke();
sum(2,3)
或者使用:sum.invoke(2,3),二者完全等價抵屿;

//Lambda表達式?jīng)]有參數(shù)庆锦,箭頭可以不寫,如下:
val printHello = {
  println("hello")//相當(dāng)于函數(shù)的函數(shù)體
}

//Lambda表達式不是只有一行的轧葛,它的返回值是它表達式的最后一行的值
val sum = {a:Int,b:Int ->
  println("$a + $b = ${a+b}")//這一行也是表達式搂抒,不過返回的是Unit類型
  a+b//這一行最為Lambda的最后一行,它的值也是Lambda的返回值尿扯;
}
  • 2.Lambda表達式的簡化
  • 1.函數(shù)參數(shù)調(diào)用時最后一個Lambda可以移出去求晶;也就是說如果一個函數(shù)調(diào)用時,最后一個參數(shù)是Lambda表達式衷笋,我們傳入?yún)?shù)時芳杏,那么這個參數(shù)可以被移出去;
  • 2.函數(shù)的參數(shù)只有一個Lambda辟宗,調(diào)用時小括號可以省略爵赵;
  • 3.如果一個Lambda只有一個參數(shù),可以不寫泊脐,可默認為it空幻;
  • 4.入?yún)ⅰ⒎祷刂蹬c形參一致的函數(shù)可以用函數(shù)引用的方式作為實參傳入晨抡;
val sum = {a:Int,b:Int ->a+b}
//Lambda表達式在沒有參數(shù)時氛悬,箭頭就不用寫了,如下:
//如下面的寫法耘柱,因為沒有參數(shù),箭頭就不用寫了:
val printHello = {
   println("hello")//相當(dāng)于函數(shù)的函數(shù)體
}

//看下面的數(shù)組遍歷:
arg.forEach{element -> println(element) }
//如果一個Lambda傳入的參數(shù)只有一個棍现,可以不寫调煎,可默認為it;上面的等價于:
arg.forEach{ println(it) }
//函數(shù)的參數(shù)只有一個Lambda表達式時己肮,調(diào)用時可以將大括號移到小括號外面士袄;
//上面的等價于下面的:
arg.forEach(){println(it)}
//這個小括號沒有什么用悲关,可以把這個小括號省略
arg.forEach{println(it)}
//如果函數(shù)的參數(shù)和返回值與action的參數(shù)和返回類型一致,就可以用函數(shù)引用的方式娄柳,如下:
arg.forEach(::println)

五寓辱、循環(huán)語句

for循環(huán)如下:


    for (i in args) {
        println("輸出的是:$i")
    }


    for ((index, value) in args.withIndex()) {
        println("$index -> $value")
    }

    for (indexValue in args.withIndex()) {
        println("${indexValue.index}---->${indexValue.value}")
    }
//或者使用下面的方式
   args.forEach{
     println(it)
   }
}

//看下面的一個方法,return會把函數(shù)截斷赤拒,無法執(zhí)行到最后一行
fun main(args: Array<String>) {

    args.forEach {
        if (it == "c") return
        println(it)
    }
    //你會發(fā)現(xiàn)如果上面的if條件觸發(fā)了 秫筏,將跳出for循環(huán),并且執(zhí)行不到下面的代碼挎挖,原因是:
    //上面的是表達式这敬,而不是一個簡單的遍歷,return會調(diào)出整個函數(shù)的執(zhí)行
    println("The End")
}
//如果想只跳出it=="c"這個條件蕉朵,循環(huán)繼續(xù)進行崔涂,整個函數(shù)執(zhí)行完畢,可以如下:
fun main(args: Array<String>) {

    args.forEach ForEach@ {
        if (it == "c") return@ForEach
        println(it)
    }
    println("The End")
}

while循環(huán)

var int = 5 
    while (int > 0) {
        println("int---->$int")
        int-- 
    }
    
    do {
        println("int---->$int")
        int--
    }while (int>5)

如何跳出 或 跳過循環(huán)始衅?
跳出或終止循環(huán):break
跳過循環(huán):continue
多層嵌套循環(huán)的終止需要結(jié)合標簽來實現(xiàn)

 Outter@ for (i in args) {

        Inner@while (i.toInt() > 0) {
            break@Outter  //這里只是跳出外層的for循環(huán) break和@Outter之間不能有空格
        }
    }

六冷蚂、異常捕獲(try catch finally)

kotlin里面的異常捕獲和Java中的異常捕獲用法一樣,最后都會調(diào)用finally;但Kotlin中的try汛闸、catch也是表達式蝙茶,這點與Java中的不一樣,它可以有返回值蛉拙,返回值是表達式的最后一行的值尸闸;

  • catch分支匹配異常類型;
  • 它是一個表達式孕锄,可以用來賦值吮廉,與if else when 表達式是完全類似的;
  • finally 無論try catch 是否拋出異常都會執(zhí)行到畸肆;

注意此行代碼代表的含義:
return try{ x/y } catch(e:Exception){ 0 } finally{...}
代表:先執(zhí)行finally里面的代碼宦芦,再返回;如果無異常轴脐,返回x/y调卑;如果有異常,返回0大咱;

  //kotlin中的try catch也是表達式恬涧,可以有返回值;返回值是表達式的最后一行的值碴巾;
  val result = try {
        args[0]
    } catch (e: Exception) {
        println("jinlaile")
        0
    } finally {
        println("進入finally代碼塊")
    }
    println(result)

輸出結(jié)果:
jinlaile
進入finally代碼塊
0

七溯捆、成員方法、成員變量

  • 屬性:或者說是成員變量厦瓢,類范圍內(nèi)的變量提揍;構(gòu)造方法中val/var修飾的都是屬性啤月;類內(nèi)部也是可以定義屬性的的;
/**
 * aField和anotherField是類Hello的兩個屬性劳跃;
 * 而notField不是屬性谎仲,只是普通構(gòu)造方法的參數(shù);
 */
class Hello(val aField: Int, notField: Int){
    val anotherField:String = "hello"
}
  • 方法:或者說是成員函數(shù)刨仑,類范圍內(nèi)的函數(shù)郑诺;
    在kotlin的類中,自動為var修飾成員變量實現(xiàn)了get贸人、set方法间景,val修飾的只有g(shù)et方法,因為val修飾的是不可變的艺智;如果想要在get倘要、set方法中注入部分邏輯,需要我們重寫其get十拣、set方法封拧,如下;
/**
 * Created by serenitynanian on 2017/6/27.
 */
class ClassMemberAndField {

    //默認訪問控制是public
    var b = 0

    get() {
        println("執(zhí)行打印邏輯")
        //這個filed其實是上面b后真正的值0夭问,這個filed只有在get泽西、set方法中才能訪問的到
        return field
    }
        /**
         * 類型java中的set方法
         * 
         * public void setB(int b){
         *      
         *      this.b = b ;
         * }
         */
    set(value) {
        println("執(zhí)行打印邏輯")
        field = value
    }
}

如果想要控制get缰趋、set的訪問權(quán)限捧杉,可以在get、set方法前加訪問限制符秘血,比如protected

  protected set(value) {
            println("logic")
        field = value
    }

如果說get味抖、set中沒有部分邏輯,只是想要修改訪問控制符灰粮,只需要如下寫即可:

class ClassMemberAndField {

    //默認訪問控制是public
    protected var b = 0

//    get() {
//        //這個filed其實是上面b后真正的值0仔涩,這個filed只有在get、set方法中才能訪問的到
//        return field
//    }
//        /**
//         * 類型java中的set方法
//         *
//         * public void setB(int b){
//         *
//         *      this.b = b 粘舟;
//         * }
//         */
//    protected set(value) {
//            println("logic")
//        field = value
//    }
   
//如果只想要控制訪問權(quán)限熔脂,只需要這樣寫即可:
    protected get
    
    protected set

}

在kotlin中聲明成員變量時,編譯器提醒你必須初始化柑肴,否則報錯霞揉;與java不同的時,java會自動給你初始化初始值晰骑;但初始值也占內(nèi)存的零聚,所以有時我們只需要在使用時才想初始化,這樣怎么辦呢些侍?
只需要在聲明成員變量時指定一個lateinit特殊字符就行了隶症;但是在使用之前必須進行初始化,否則報錯岗宣;

var age:Int = 0 
    //如果不指定lateinit 編譯器會提醒必須初始化或者abstract蚂会,
    //指定后就是告訴編譯器,我后面會進行初始化耗式;
    //如果你在初始化它之前就使用這個變量胁住,會報錯的;
    lateinit var name:String

但是lateinit只能放在var修飾的可變變量前面刊咳,不能放在val修飾的變量前面彪见;如果想要達到延遲初始化必須使用delegate,如下:

   /**
     * lazy需要傳入一個lambda表達式,一個無參的表達式返回一個T類型娱挨,
     * 這個T類型就是下面的String類型余指;
     */
   val address:String by lazy {
       "dsfa"
   }

總結(jié)下屬性訪問控制:
var修飾的有g(shù)et、set方法跷坝;
val修飾的只有g(shù)et方法酵镜,沒有set方法,因為val修飾的變量是不可變的柴钻;

總結(jié)下屬性初始化:
屬性的初始化盡量在構(gòu)造方法中進行初始化完成淮韭;
無法在構(gòu)造方法中初始化,嘗試降級為局部變量贴届;
var用lateinit延遲初始化靠粪,val用lazy;
可空類型謹慎使用null直接初始化毫蚓;

八占键、表達式(中綴表達式、分支表達式绍些、when表達式)

  • 中綴表達式
  • 只有一個參數(shù)捞慌,且用infix修飾的函數(shù);
class Book {
   infix fun on(place: String) {

    }
}

fun main(args: Array<String>) {
    //函數(shù)前沒有使用infix關(guān)鍵字柬批,必須像平常調(diào)用函數(shù)一樣使用
    Book().on("my desk")
    
    //如果函數(shù)前面使用了infix啸澡,不用在方法前加. 不用在方法后加括號
    Book() on "my dest"
}
  • 2.使用了中綴表達式后,在調(diào)用時氮帐,可以直接使用[對象] <函數(shù)名> [參數(shù)對象] 如上示例嗅虏;

  • 分支表達式(if),而不只是分支語句
    分支表達式是可以有返回值的上沐,返回值是分支語句中最后一行的值 皮服;

private const val DEBUG = 1
private const val USER = 0
fun main(args: Array<String>) {

//    var mode = USER
//    if (args.isNotEmpty() && args[0] == "1") {
//        mode = DEBUG
//    }

    /**
     * 從下面可以看出來if可不只是一個簡單的分支語句,
     * 它還是一個表達式,它是有返回值的龄广,返回值是是分支表達式中最后一行的值硫眯;
     * 在上面的分支語句中,只能定義var的mode择同,因為后面要修改两入;
     * 如果使用分支表達式,就直接可以使用val修飾的mode了敲才,使用如下:
     */
    val mode =
            if (args.isNotEmpty() && args[0] == "1") {
                DEBUG
            }else{
                USER
            }

    println("請輸入用戶名:")
    val username = readLine()
    println("請輸入密碼:")
    val password = readLine()

    if (mode == DEBUG && username == USERNAME && password == PASSWORD) {
        println("超管登錄成功")
    } else if (username == USERNAME && password == PASSWORD) {
        println("普通用戶登錄成功")
    } else {
        println("登錄失敗")
    }

}
  • when表達式
    類似Java中的switch語句裹纳,由于case語句中只能判斷String,enum紧武,byte剃氧,int等,并且在每個分支語句中都要寫break阻星;在kotlin中沒有了switch語句了朋鞍,使用了when表達式來代替了;
    public void pause() {
        switch (state) {
            case BUFFERING:
            case PLAYING:
                doPause();
                break;
            default:
                //什么都不做
        }
    }

//下面是kotlin中的when表達式
    fun pause() {
        when (state) {
            PlayerKt.State.BUFFERING, PlayerKt.State.PLAYING -> doPause()
            else -> {

            }
        }
    }

when分支表達式只要第一個分支語句執(zhí)行了迫横,不用使用break番舆,后面的分支語句就不會執(zhí)行了

fun main(args: Array<String>) {
    var x = 5
    //when表達式只要第一個分支語句執(zhí)行了,不用使用break,后面的就不會執(zhí)行了
    when (x) {
        is Int -> println("Hello $x")
        in 1..100 -> println("$x is in 1..100")//x的值是否在[1,100]
        !in 1..100 -> println("$x is not in 1..100")//x的值不在[1,100]
        in 1 until 5 -> println("$x is in[0,5)")//x的值是否在[0,5)之間矾踱,取不到5
        args[0].toInt() -> println("x == args[0]")//這個是說args[0]是否與x一樣
    }
}

//when與if一樣恨狈,也有返回值,都是每一個分支最后一行表達式的值呛讲;
    val mode = when {
        args.isNotEmpty()&& args[0] == "1" -> 1
        else -> 0
    }

表達式總結(jié):

  • if ... else ...這個用法基本和Java中一致禾怠;
  • 表達式必須具備完整性,如果只有if沒有else編譯報錯;
 var b = if (mode == 0) {
        0
    } 
    //如果沒有下面的分支語句贝搁,編譯報錯
    //賦值時吗氏,分支必須完備
    else {
        1
    }
  • when表達式,加強版的switch雷逆,支持任意類型弦讽,也不用寫break;
    支持純表達式條件分支(類似if)
   val mode = when {
       args.isNotEmpty()&& args[0] == "1" -> 1
       else -> 0
   }

必須具備完備性膀哲;

九往产、具名參數(shù),變長參數(shù)某宪,默認參數(shù)

  • 具名參數(shù):就是在給函數(shù)傳入實參的時候仿村,把形參也賦值上,也就是下面在調(diào)用sum函數(shù)時兴喂,在傳入實參的時候蔼囊,把arg1 和 arg2也附帶上(arg1 = 1焚志,arg2 = 2);

具名參數(shù)的順序可以不是固定的畏鼓;

class ForDemo {

    fun sum(arg1:Int,arg2:Int) = arg1 + arg2
}

fun main(args: Array<String>) {


    var forDemo = ForDemo()
    /**
     * 在使用函數(shù)傳入實參的時候酱酬,把形參也賦上;
     * 因為是具名參數(shù),所以形參的順序可以不固定
     * 也就是明確告訴編譯器這個2是給arg2的滴肿,1是給arg1的
     */
    forDemo.sum(arg2 = 2, arg1 = 1)

}
  • 變長參數(shù)
    某個參數(shù)可以接收多個值岳悟;
    變長參數(shù)可以不為最后一個參數(shù);但是傳入實參時泼差,可以放在最后用具名參數(shù)表示即可;
    如果傳參有歧義呵俏,需要使用具名參數(shù)指定某個特定參數(shù)堆缘;
    最常見的就是main函數(shù),它里面是個數(shù)組普碎,我們可以將它改變?yōu)樽冮L參數(shù)吼肥;它的使用和數(shù)組完全一樣
   var array = intArrayOf(1,23,43,25,56)

    hello(3.0,1,123,321,2,string = "hello")
    //*:Spread Operator這個符號現(xiàn)在只支持變長參數(shù),且只支持array麻车,不支持list
    hello(3.0,*array,string = "hello")

fun hello(double:Double,vararg ints: Int,string:String) {
    ints.forEach { ::println }
}

在Java中變長參數(shù)只能是函數(shù)的最后一個參數(shù)缀皱,否則編譯器無法識別的;
在kotlin中因為存在具名函數(shù)动猬,因此它可以放在任意位置啤斗;在傳入實參的時候可以用具名函數(shù)放在最后一個位置;

*:Spread Operator 這個不是一般的運算符赁咙;
只支持展開Array;
只用于變長參數(shù)列表的實參钮莲;
不能重載;

  • 默認參數(shù)
    1.就是在函數(shù)編寫時彼水,可以給函數(shù)任意位置的形參一個默認值崔拥;在實際調(diào)用函數(shù)時,這個參數(shù)可以不傳凤覆;
    2.但是如果該默認參數(shù)不是最后一個链瓦,其他參數(shù)使用具名參數(shù)即可,不用寫默認的盯桦;
    3.傳參出現(xiàn)歧義時慈俯,也就是編譯器報錯,需要使用具名函數(shù)俺附,具體請看第二條肥卡;
    hello(3.0,1,123,321,2,string = "hello")
    //* 這個符號現(xiàn)在只支持變長參數(shù),且只支持array事镣,不支持list
    hello(ints = *array,string = "hello")

fun hello(double:Double = 3.0 ,vararg ints: Int,string:String) {
    ints.forEach { ::println }
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末步鉴,一起剝皮案震驚了整個濱河市揪胃,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌氛琢,老刑警劉巖喊递,帶你破解...
    沈念sama閱讀 212,383評論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異阳似,居然都是意外死亡骚勘,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,522評論 3 385
  • 文/潘曉璐 我一進店門撮奏,熙熙樓的掌柜王于貴愁眉苦臉地迎上來俏讹,“玉大人,你說我怎么就攤上這事畜吊≡蠼” “怎么了?”我有些...
    開封第一講書人閱讀 157,852評論 0 348
  • 文/不壞的土叔 我叫張陵玲献,是天一觀的道長殉疼。 經(jīng)常有香客問我,道長捌年,這世上最難降的妖魔是什么瓢娜? 我笑而不...
    開封第一講書人閱讀 56,621評論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮礼预,結(jié)果婚禮上眠砾,老公的妹妹穿的比我還像新娘。我一直安慰自己逆瑞,他們只是感情好荠藤,可當(dāng)我...
    茶點故事閱讀 65,741評論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著获高,像睡著了一般哈肖。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上念秧,一...
    開封第一講書人閱讀 49,929評論 1 290
  • 那天淤井,我揣著相機與錄音,去河邊找鬼摊趾。 笑死币狠,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的砾层。 我是一名探鬼主播漩绵,決...
    沈念sama閱讀 39,076評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼肛炮!你這毒婦竟也來了止吐?” 一聲冷哼從身側(cè)響起宝踪,我...
    開封第一講書人閱讀 37,803評論 0 268
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎碍扔,沒想到半個月后瘩燥,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,265評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡不同,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,582評論 2 327
  • 正文 我和宋清朗相戀三年厉膀,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片二拐。...
    茶點故事閱讀 38,716評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡服鹅,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出卓鹿,到底是詐尸還是另有隱情菱魔,我是刑警寧澤,帶...
    沈念sama閱讀 34,395評論 4 333
  • 正文 年R本政府宣布吟孙,位于F島的核電站,受9級特大地震影響聚蝶,放射性物質(zhì)發(fā)生泄漏杰妓。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 40,039評論 3 316
  • 文/蒙蒙 一碘勉、第九天 我趴在偏房一處隱蔽的房頂上張望巷挥。 院中可真熱鬧,春花似錦验靡、人聲如沸倍宾。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,798評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽高职。三九已至,卻和暖如春辞州,著一層夾襖步出監(jiān)牢的瞬間怔锌,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,027評論 1 266
  • 我被黑心中介騙來泰國打工变过, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留埃元,地道東北人。 一個月前我還...
    沈念sama閱讀 46,488評論 2 361
  • 正文 我出身青樓媚狰,卻偏偏與公主長得像岛杀,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子崭孤,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,612評論 2 350

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