kotlin語法概覽

kotlin 是用于現(xiàn)代多平臺(tái)應(yīng)用的靜態(tài)編程語言,可以與 Java? 和 Android? 100% 可互操作。

基本語法

表達(dá)式和語句

表達(dá)式:有值,并且能作為另一個(gè)表達(dá)式的一部分使用玩裙。
語句:總是包含著它的代碼塊中的頂層元素,并且沒有自己的值段直。
當(dāng)函數(shù)體是由單個(gè)表達(dá)式構(gòu)成時(shí)吃溅,可以用這個(gè)表達(dá)式作為完整的函數(shù)體,并且去掉花括號(hào)和 return 語句

    fun max(x: Int, y: Int): Int {
        return if (x > y) x else y
    }

    fun min(x: Int, y: Int) = if (x > y) y else x

可變變量和不可變變量 : var 和 val

使用 val 聲明的變量不能在初始化之后再次賦值
這種變量的值可以改變鸯檬,但是它的類型卻是改變不了的

屬性

當(dāng)聲明屬性的時(shí)候决侈,就聲明了對(duì)應(yīng)的訪問器(只讀屬性有一個(gè) gettter,而可變屬性則有 getter/setter)

class Person(
        val name: String,
        var isMarried: Boolean
)
fun personFun() {
    val person = Person("andy", true)
    print("${person.name}是不是${person.isMarried}")
}
class Rectangle(var width: Int, var height: Int) {
    val isSquare = width == height
}
fun main(args: ArrayList<String>) {
    personFun()
    val rectangle = Rectangle(12, 12)
    print(rectangle.isSquare)
}

field

class LengthCounter {
    var str: String = ""
        set(value) {
            if (value == "") {
                println("no value")
            } else {
                field = value
            }
        }
    var counter = 0
        private set

    fun addWord(word: String) {
        str += word
        counter += word.length
    }
}

枚舉

enum class Color {
    RED, ORANGE, GREEN
}

enum class ColorValue(private val r: Int, private val g: Int, private val b: Int) {
    RED(255, 0, 0), ORANGE(255, 265, 0), GREEN(0, 255, 0);

    fun rgb() = (r * 256 + g) * 256 + b
}

fun main(args: ArrayList<String>) {
    print(Color.RED)
    print(ColorValue.GREEN)
    print(ColorValue.GREEN.rgb())
}

enum class DeviceStatus(val value: String) {
    POWER("來電"),
    NO_POWER("斷電");
}

循環(huán)與迭代

fun forFun(start: Int, end: Int) {
    for (i in start..end) {
        print(i)
    }
    for (i in end downTo start step 2) {
        print(i)
    }
    for (i in start until end) {
        print(i)
    }
    //map集合的存取
    val hashMap = HashMap<Char, String>()
    for (c in 'A'..'Z') {
        val binaryString = Integer.toBinaryString(c.toInt())
        hashMap[c] = binaryString
    }
    for ((k, v) in hashMap) {
        print("key = $k, value = $v")
    }
}

@Test
fun testForeach() {
    //continue
    (1..20).forEach {
        println(it)
        if (it >= 10) {
            return@forEach
        }
        println("=$it")
    }
    //break
    run outside@{
        (1..20).forEach inside@{
            println(it)
            if (10 <= it) return@outside
            println("=$it")
        }
    }
}

異常處理

fun verifyNum(str: String) = {
    val num = try {
        Integer.parseInt(str)
    } catch (e: NumberFormatException) {
        null
    }
    print(num)
}

NULL 檢查機(jī)制

//類型后面加?表示可為空
var age: String? = "23"
//拋出空指針異常
val ages = age!!.toInt()
//不做處理返回 null
val ages1 = age?.toInt()
//age為空返回-1
val ages2 = age?.toInt() ?: -1

集合

fun collectionDemo() {
    val arrayListOf = arrayListOf("andy", "tom", "json")
    val hashMapOf = hashMapOf<String, String>("name" to "andy", "grade" to "一年級(jí)")
}

函數(shù)

定義一個(gè)函數(shù)

fun <T> joinToString(collection: Collection<T>, sep: String, pre: String, end: String) {
    val sb = StringBuilder(pre)
    for ((index, value) in collection.withIndex()) {
        if (index > 0) {
            sb.append(sep)
        }
        sb.append(value)
    }
    sb.append(end)
    print(sb)
}

命名參數(shù)

  • 增加函數(shù)的可讀性
  • 以想要的順序指定需要的參數(shù)

可以這樣調(diào)用上面的函數(shù)

    val list = listOf(1, 2, 3)
    joinToString(end = "}", pre = "{", sep = ",", collection = list)
    joinToString(list, end = "}", pre = "{", sep = ",")

如果在調(diào)用一個(gè)函數(shù)時(shí)喧务,指明了一個(gè)參數(shù)的名稱赖歌,那它之后的所有參數(shù)都要表明名稱枉圃。
當(dāng)調(diào)用 Java 函數(shù)時(shí),不能使用命名參數(shù)庐冯。

默認(rèn)參數(shù)

可以避免創(chuàng)建重裝函數(shù)

fun <T> joinToString(collection: Collection<T>, sep: String = ",", pre: String = "{", end: String = "}") {
    ... ...
}

頂層函數(shù)和屬性

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

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

    fun Context.toast(message: CharSequence) = Toast.makeText(this, message, Toast.LENGTH_LONG).show()
    fun String.getLastChar(): Char = this[this.length - 1]
    //在kotlin中使用
    val lastChar = "andy".getLastChar()
    print(lastChar)
    //在java類中使用
    char lastChar = KotlinDemoKt.getLastChar("andy");
  • 擴(kuò)展函數(shù)不存在重寫
open class MyView {
    open fun click() {
        println("this is button")
    }
}

class MyButton : MyView() {
    override fun click() {
        println("this is button")
    }
}

fun MyView.showName() = println("my view")
fun MyButton.showName() = println("my button")

fun testDemo() {
    val myButton = MyButton()
    myButton.showName()
    myButton.click()
    val aBtn: MyView = MyButton()
    aBtn.showName()
    aBtn.click()
}
/*
my button
this is button
my view
this is button
*/

擴(kuò)展屬性

//擴(kuò)展屬性
var TextView.leftMargin:Int
get():Int {
     return (layoutParams as ViewGroup.MarginLayoutParams).leftMargin
    }
set(value) {
        (layoutParams as ViewGroup.MarginLayoutParams).leftMargin=value
    }

//================//
var StringBuilder.lastChar: Char
    get() = this[length - 1]
    set(value) = this.setCharAt(length - 1, value)
//   set(value) {
//       this.setCharAt(length - 1, value)
//   }

可變參數(shù)

fun varargFun(vararg args: Int) {
    args.forEach {
        println("var =$it")
    }
}

fun testDemo(args: ArrayList<String>) {
    //將參數(shù)打包成一個(gè)數(shù)組,傳參數(shù)時(shí)需要使用*解包
    val ints = intArrayOf(2, 4, 6, 7)
    varargFun(*ints)
}

中綴調(diào)用

    val pair0 = 1.to("one")
    val pair1 = 3 to "three"
    val hashMap = HashMap<Int, String>()
    hashMap.plus(pair0)
    hashMap.plus(pair1)

定義中綴調(diào)用孽亲,需要使用 infix 修飾符來標(biāo)記

class Student(val name: String, val isMarried: Boolean)

infix fun String.factory(isMarried: Boolean) = Student(this, isMarried)

fun testInFix() {
    val andy: Student = "andy" factory true
    println("name = ${andy.name},isMarried = ${andy.isMarried}")
    println(andy.isMarried)
    val tom = "Tom" factory false
    println("name = ${tom.name},isMarried = ${tom.isMarried}")
}

局部函數(shù)

可以在函數(shù)中嵌套這些提取的函數(shù),局部函數(shù)定義方式和普通函數(shù)是相同的

正則表達(dá)式

println("23.1|21-6.AB".split("[.|-]".toRegex()))

//第一組(.+)包含最后一個(gè)斜線之前的子串
fun parsePath(path: String) {
    val dir = path.substringBeforeLast("/")
    val fileFullName = path.substringAfterLast("/")
    val fileName = fileFullName.substringBefore(".")
    val ext = fileFullName.substringAfter(".")
    println("dir = $dir ,fileName = $fileName ,ext = $ext")
}

fun parsePathByRegex(path: String) {
    var regex = """(.+)/(.+)\.(.+)""".toRegex()
    val entire = regex.matchEntire(path)
    if (entire != null) {
        val (dir, fileName, ext) = entire.destructured
        println("dir = $dir ,fileName = $fileName ,ext = $ext")
    }
}

對(duì)象

接口

可以包含默認(rèn)實(shí)現(xiàn)的抽象方法

訪問性修飾符

open展父、final 和 abstract 這三個(gè)訪問修飾符都 只適用于類返劲,不能用在接口。

  1. open:用于聲明一個(gè)類可以被繼承栖茉,或者方法可以被子類重寫篮绿。
  2. final:不允許類被繼承,或者不允許方法被重寫吕漂。
  3. abstract:聲明抽象類搔耕,或者抽象類中的抽象方法。
  4. 當(dāng)我們需要重寫方法時(shí)痰娱,必須加上 override 修飾符弃榨。

可見性修飾符

修飾符 類成員 頂層聲明
public 所有地方可見 所有地方可見
internal 模塊中可見 模塊中可見
protected 子類中可見 ---
private 類中可見 文件中可見

內(nèi)部類和嵌套類

在 Kotlin 中,如果我們像 Java 一樣梨睁,在一個(gè)類的內(nèi)部定義一個(gè)類鲸睛,那么它并不是一個(gè) 內(nèi)部類,而是 嵌套類坡贺,區(qū)別在于嵌套類不會(huì)持有外部類的引用官辈,也就是說它實(shí)際上是一個(gè)靜態(tài)內(nèi)部類。

class Outer {
    inner class Inner {
        fun getOutReference(): Outer = this@Outer
    }
}

如果要把它嵌套類變成一個(gè) 內(nèi)部類 來持有一個(gè)外部類的引用的話需要使用 inner 修飾符遍坟,并且訪問外部類時(shí)拳亿,需要使用 this@{外部類名}的方式

密封類 sealed

sealed class Expr {
    class Num(val value: Int) : Expr()
    class Sum(val width: Expr, val height: Expr) : Expr()
}

fun eval(expr: Expr): Int =
        when (expr) {
            is Expr.Num -> expr.value
            is Expr.Sum -> eval(expr.width) + eval(expr.height)
        }

構(gòu)造方法

主構(gòu)造方法:主要而簡潔的初始化類的方法,并且在 類體外部聲明愿伴。
從構(gòu)造方法:在類體內(nèi)部聲明肺魁。

class User constructor(name: String) {
    val userName: String

    init {
        userName = name
    }
}

constructor:用來開始一個(gè)主構(gòu)造方法和從構(gòu)造方法的聲明。
init:引入一個(gè)初始化塊語句隔节,這種語句塊包含了在類被創(chuàng)建時(shí)執(zhí)行的代碼鹅经,并會(huì)與主構(gòu)造方法一起使用,因?yàn)橹鳂?gòu)造方法有語法限制怎诫,這就是為什么要使用初始化語句塊的原因瘾晃。

如果主構(gòu)造方法沒有注解或可見性修飾符,可以取消 constructor 關(guān)鍵字幻妓。

class User(val name: String)

必須顯示地調(diào)用父類的構(gòu)造方法蹦误,即使它沒有任何的參數(shù)

open class User(val name: String)

class TimeUser(name: String) : User(name) {
    fun printUserInfo() = print("user name =${this.name}")
}

從構(gòu)造方法 constructor

子類調(diào)用父類的從構(gòu)造方法:super
子類調(diào)用自己的另一個(gè)構(gòu)造方法:this

數(shù)據(jù)類

使用 data 修飾符生成通用方法

copy

    val client = Client("tom", 12)
    println(client.toString())
    val copyClient = client.copy("andy")
    println(copyClient)

委托

package cn.timeface

import kotlin.properties.ReadOnlyProperty
import kotlin.reflect.KProperty

/**
 * Created by zhangsheng on 2017/10/28.
 */
class ResourceID {
    val image_id: String = "101"
    val text_id: String = "102"
}

class ResourceLoader(id: ResourceID) {
    private val d: ResourceID = id
    operator fun provideDelegate(thisRef: MyUI, prop: KProperty<*>): ReadOnlyProperty<MyUI, String> {
        if (checkProperty(prop.name)) {
            return DellImpl(d)
        } else {
            throw Exception("Error ${prop.name}")
        }
    }

    private fun checkProperty(name: String): Boolean {
        return name == "image" || name == "text"
    }
}

class DellImpl(d: ResourceID) : ReadOnlyProperty<MyUI, String> {
    val id: ResourceID = d

    override fun getValue(thisRef: MyUI, property: KProperty<*>): String {
        return if (property.name == "image")
            property.name + "  " + id.image_id
        else
            property.name + "  " + id.text_id
    }
}

fun bindResource(id: ResourceID): ResourceLoader {
    return ResourceLoader(id)
}

class MyUI {
    val image by bindResource(ResourceID())
    val text by bindResource(ResourceID())
}

fun main(args: Array<String>) {
    try {
        val ui = MyUI()
        println(ui.image)
        println(ui.text)
    } catch (e: Exception) {
        println(e.message)
    }
}

object

以一句話來定義一個(gè)類和一個(gè)該類的變量

object Singleton {
    var name: String = "singleton"
    var age: Int = 0
}

fun testSingleTon() {
    println("${Singleton.name}的年齡${Singleton.age}")
}

application 實(shí)現(xiàn)單例

class App : Application() {
    companion object {
        lateinit var instance: App //延遲加載,不需要初始化,否則需要在構(gòu)造函數(shù)初始化
            private set
    }
    override fun onCreate() {
        super.onCreate()
        instance = this
    }
}
  1. 創(chuàng)建單例 object

    class LazySingleton private constructor(){
        companion object {
            val instance: LazySingleton by lazy { LazySingleton() }
        }
    }
    
  2. 伴生對(duì)象 companion

    伴生對(duì)象所在的類被加載强胰,伴生對(duì)象被初始化尚镰,與 Java 靜態(tài)成員一樣

    工廠方法和靜態(tài)成員的實(shí)現(xiàn)

    使用伴生對(duì)象來實(shí)現(xiàn)工廠方法

    如果你需要寫一個(gè)在沒有類實(shí)例的情況下,調(diào)用但是需要訪問類內(nèi)部的函數(shù),可以將其寫成那個(gè)類中的 對(duì)象聲明的成員.
    在類中定義的對(duì)象之一可以使用一個(gè)特殊的關(guān)鍵字來標(biāo)記 companion哪廓,如果這樣做狗唉,就獲得了直接 通過容器類名稱來訪問這個(gè)對(duì)象的方法和屬性的能力,不再需要顯示地指明對(duì)象的名稱

    class Response(val name: String) {
        companion object Loader {
            fun toJson(response: Response) = "name : ${response.name}"
        }
    }
    
    fun testResponse() {
        Response.Loader.toJson(Response("andy"))
        Response.toJson(Response("Tom"))
    }
    
  3. 在伴生對(duì)象中實(shí)現(xiàn)接口

    就像其它對(duì)象聲明一樣涡真,伴生對(duì)象也可以實(shí)現(xiàn)接口分俯,可以將包含它的類的名字當(dāng)做實(shí)現(xiàn)了該接口的對(duì)象實(shí)例來使用。

    class Response(val name: String) {
        companion object
    }
    
    fun Response.Companion.toJson(response: Response) = "name : ${response.name}"
    fun testResponse() {
        Response.Companion.toJson(Response("andy"))
    }
    
  4. 對(duì)象表達(dá)式

object 關(guān)鍵字不僅能夠用來表明單例式的對(duì)象哆料,還能用來聲明匿名對(duì)象缸剪,它替代了 Java 中匿名內(nèi)部類的用法。

lambda 表達(dá)式

        btnLogin.setOnClickListener { v ->
            val id = v.id
        }
        btnLogin.setOnClickListener {

        }

如果 lambda 剛好是 函數(shù)或者屬性的委托东亦,可以用 成員引用 替換杏节。

data class TimeBook(val name: String, val count: Int)

fun testLambda() {
    val listOf = listOf(TimeBook("andy", 12), TimeBook("tom", 14))
    println(listOf.maxBy { it.count })
    println(listOf.maxBy(TimeBook::count))
}

語法

一個(gè) Lambda 表達(dá)式把一小段行為進(jìn)行編碼,你能把它 當(dāng)做值到處傳遞典阵,它可以被獨(dú)立地聲明并存儲(chǔ)到一個(gè)變量中奋渔,但是最常見的還是直接聲明它并傳遞給函數(shù)

class DiagramTest {
    @Test
    fun testApply() {
        val lam1 = lam("hello", { hello(it) })
        println(lam1)
        val lam2 = lam("hello", {
            it + "world"
        })
        println(lam2)

        val testLam = testLam(10, {
            101
        })
        println(testLam)
    }

    private fun lam(string: String, p: (num: String) -> String): String {
        return p(string)
    }

    private fun hello(string: String): String {
        return string + " world"
    }

    private fun testLam(num: Int, p: () -> Int): Int {
        return p() + num
    }
}

方法參數(shù)

    fun functionAbs(x: Int, y: Int, absAction: (Int) -> Int): Int {
        return absAction(x) + absAction(y)
    }

    var absSum: (Int) -> Int = {
        Math.abs(it)
    }

    fun test() {
        functionAbs(1, -2, absSum)
    }

存儲(chǔ)到變量中

    val sum = { x: Int, y: Int -> x + y }
    println(sum(1, 3))

直接調(diào)用 run

fun main(args : ArrayList<String>){
    run {
        println("hello world")
    }
}

joinToString

    val toString = listOf.joinToString("==", "[", "]",
            transform = { timeBook: TimeBook -> timeBook.name })
    println(toString)

    @Test
    fun testKotlin() {
        val listStr = (1..5).joinToString(",") { "$it:$it" }
        println(listStr)
        //1:1,2:2,3:3,4:4,5:5
        val list = arrayListOf<String>()
        list.add("8")
        list.add("9")
        val str = list.joinToString(",") { "${list.indexOf(it)}:$it" }
        println(str)
        //0:8,1:9
        val result = listStr
                    .split(",".toRegex())
                    .map { it.split(":")[1] }
                    .filter { !it.isEmpty() }
        println(result)
        //1,2,3,4,5
    }

包含多條語句

lambda 表達(dá)式可以包含更多的語句,最后一個(gè)表達(dá)式就是 lambda 的結(jié)果

    val total = { x: Int, y: Int ->
        println("start count")
        x + y
        }
    println(total(1, 4))
    bookList.forEach {
        print("${it.name} has ${it.count}")
    }

引用頂層函數(shù)

直接以:開頭壮啊,成員引用::salute 被當(dāng)作實(shí)參傳遞給庫函數(shù) run

fun salute() = print("hello")
fun main1(args: ArrayList<String>) {
    run(::salute)
}

存儲(chǔ)或者延期執(zhí)行創(chuàng)建類實(shí)例的動(dòng)作

    val createBook = ::TimeBook
    println(createBook("tommao", 12))

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

fun TimeBook.hasMore() = count > 0

fun main1(args: ArrayList<String>){
    bookList.filter { it.count > 0 }
    val hasNext = TimeBook::hasMore
    bookList.filter(hasNext)
    println(list)
}

also\run\apply\with\let

also\run\apply\with\let

collections

list to map

 val myMap = myList.map { it.name to it.age }.toMap()
 val myMap = myList.associateBy({ it.name }, { it.hobbies })
 val myMap = myList.associate{ it to it }
//1.
 val myMap = mutableMapOf<String, String>()
 myList.associateTo(myMap) {it to it}
//2.
val myMap = mutableMapOf<String, User>()
myList.associateByTo(myMap) {it.name}
//3.
val myMap = mutableMapOf<String, Int>()
myList.associateByTo(myMap, {it.name}, {it.age})

** 知識(shí)索引 **
kotlin 語言中文站

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末嫉鲸,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子歹啼,更是在濱河造成了極大的恐慌玄渗,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,826評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件狸眼,死亡現(xiàn)場離奇詭異藤树,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)拓萌,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,968評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門岁钓,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人司志,你說我怎么就攤上這事甜紫〗嫡” “怎么了骂远?”我有些...
    開封第一講書人閱讀 164,234評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長腰根。 經(jīng)常有香客問我激才,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,562評(píng)論 1 293
  • 正文 為了忘掉前任瘸恼,我火速辦了婚禮劣挫,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘东帅。我一直安慰自己压固,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,611評(píng)論 6 392
  • 文/花漫 我一把揭開白布靠闭。 她就那樣靜靜地躺著帐我,像睡著了一般。 火紅的嫁衣襯著肌膚如雪愧膀。 梳的紋絲不亂的頭發(fā)上拦键,一...
    開封第一講書人閱讀 51,482評(píng)論 1 302
  • 那天,我揣著相機(jī)與錄音檩淋,去河邊找鬼芬为。 笑死,一個(gè)胖子當(dāng)著我的面吹牛蟀悦,可吹牛的內(nèi)容都是我干的媚朦。 我是一名探鬼主播,決...
    沈念sama閱讀 40,271評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼日戈,長吁一口氣:“原來是場噩夢(mèng)啊……” “哼莲镣!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起涎拉,我...
    開封第一講書人閱讀 39,166評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤瑞侮,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后鼓拧,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體半火,經(jīng)...
    沈念sama閱讀 45,608評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,814評(píng)論 3 336
  • 正文 我和宋清朗相戀三年季俩,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了钮糖。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,926評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡酌住,死狀恐怖店归,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情酪我,我是刑警寧澤消痛,帶...
    沈念sama閱讀 35,644評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站都哭,受9級(jí)特大地震影響秩伞,放射性物質(zhì)發(fā)生泄漏逞带。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,249評(píng)論 3 329
  • 文/蒙蒙 一纱新、第九天 我趴在偏房一處隱蔽的房頂上張望展氓。 院中可真熱鬧,春花似錦脸爱、人聲如沸遇汞。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,866評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽勺疼。三九已至,卻和暖如春捏鱼,著一層夾襖步出監(jiān)牢的瞬間执庐,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,991評(píng)論 1 269
  • 我被黑心中介騙來泰國打工导梆, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留轨淌,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,063評(píng)論 3 370
  • 正文 我出身青樓看尼,卻偏偏與公主長得像递鹉,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子藏斩,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,871評(píng)論 2 354

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