Kotlin 1.7.0 正式發(fā)布拗军!主要新特性一覽

6月9號(hào)憾筏,Kotlin 發(fā)布了1.7.0正式版嚎杨。本文將大致過(guò)一遍主要的新特性。

本文主要來(lái)自 What's new in Kotlin 1.7.0 | Kotlin氧腰,部分來(lái)自 Kotlin 1.7.0-Beta 現(xiàn)已發(fā)布 | The Kotlin Blog 枫浙,完整內(nèi)容也請(qǐng)參考這些鏈接。受限于本人水平古拴,難免有誤箩帚,敬請(qǐng)諒解。

作者:FunnySaltyFish (github.com)

以下是此版本主要更新:

新的 Kotlin K2 編譯器

此 Kotlin 版本引入了新的 Kotlin K2 編譯器的 Alpha 版本锰蓬。新的編譯器旨在加快新語(yǔ)言功能的開(kāi)發(fā)幔睬,統(tǒng)一Kotlin支持的所有平臺(tái),帶來(lái)性能改進(jìn)芹扭,并為編譯器擴(kuò)展提供API麻顶。

我們已經(jīng)發(fā)布了一些關(guān)于我們的新編譯器及其優(yōu)點(diǎn)的詳細(xì)說(shuō)明:

需要強(qiáng)調(diào)的是,對(duì)于新K2編譯器的Alpha版本舱卡,我們主要關(guān)注性能改進(jìn)辅肾,并且它僅適用于JVM項(xiàng)目。它不支持Kotlin / JS轮锥,Kotlin / Native 或其他多平臺(tái)項(xiàng)目矫钓,并且包括 kapt 在內(nèi)的編譯器插件都無(wú)法使用它。

我們的基準(zhǔn)測(cè)試顯示了我們內(nèi)部項(xiàng)目的一些杰出成果:

Project 現(xiàn)版本 Kotlin 編譯器 新的 K2 Kotlin 編譯器 相對(duì)提升
Kotlin 2.2 KLOC/s 4.8 KLOC/s ~ x2.2
YouTrack 1.8 KLOC/s 4.2 KLOC/s ~ x2.3
IntelliJ IDEA 1.8 KLOC/s 3.9 KLOC/s ~ x2.2
Space 1.2 KLOC/s 2.8 KLOC/s ~ x2.3

KLOC/s 為每秒鐘編譯器處理的源代碼行數(shù)(千行)

您可以查看 JVM 項(xiàng)目的性能提升舍杜,并將其與舊編譯器的結(jié)果進(jìn)行比較新娜。要啟用 Kotlin K2 編譯器,請(qǐng)使用以下編譯器選項(xiàng):

-Xuse-k2

此外既绩,K2 編譯器 還包括許多錯(cuò)誤修復(fù): fixed-in-frontend-ir sort by: Priority, votes, updated)概龄。請(qǐng)注意,此列表中以 State: Open 開(kāi)頭的 bugs 實(shí)際上在 K2 里也已得到修復(fù)饲握。

下一個(gè) Kotlin 版本將提高 K2 編譯器的穩(wěn)定性并提供更多功能私杜,敬請(qǐng)期待并提供您的反饋!

語(yǔ)法

內(nèi)聯(lián)類的內(nèi)聯(lián)值也能委托了

如果要為值或類實(shí)例創(chuàng)建輕量級(jí)wrapper救欧,則必須手動(dòng)實(shí)現(xiàn)所有接口方法歪今,委托實(shí)現(xiàn)解決了這個(gè)問(wèn)題。但在 1.7.0 之前颜矿,它不適用于內(nèi)聯(lián)類寄猩。此限制已被刪除,因此您現(xiàn)在可以創(chuàng)建在大多數(shù)情況下不分配內(nèi)存的輕量級(jí)wrapper骑疆。

// 接口田篇,唯一的方法返回一個(gè)字符串
interface Bar {
    fun foo() = "foo"
}

@JvmInline
// kt1.7之前,對(duì)內(nèi)聯(lián)類不能如此寫(xiě)
// 否則會(huì)報(bào) "Value class cannot implement an interface by delegation if expression is not a parameter"
// kt1.7 解除了這個(gè)限制
value class BarWrapper(val bar: Bar): Bar by bar

fun main() {
    val bw = BarWrapper(object: Bar {})
    println(bw.foo())
}

類型參數(shù)的下劃線運(yùn)算符

Kotlin 1.7.0 為類型參數(shù)引入了一個(gè)下劃線運(yùn)算符 箍铭〔醇恚可以使用它在指定其他類型時(shí)自動(dòng)推斷類型參數(shù):_

abstract class SomeClass<T> {
    abstract fun execute(): T
}

class SomeImplementation : SomeClass<String>() {
    override fun execute(): String = "Test"
}

class OtherImplementation : SomeClass<Int>() {
    override fun execute(): Int = 42
}

object Runner {
    inline fun <reified S: SomeClass<T>, T> run(): T {
        return S::class.java.getDeclaredConstructor().newInstance().execute()
    }
}

fun main() {
    // T 被推斷為 String,因?yàn)?SomeImplementation 繼承自 SomeClass<String>
    val s = Runner.run<SomeImplementation, _>()
    assert(s == "Test")

    // T 被推斷為 Int 诈火,因?yàn)?OtherImplementation 繼承自 SomeClass<Int>
    val n = Runner.run<OtherImplementation, _>()
    assert(n == 42)
}

構(gòu)建器推斷變更

構(gòu)建器推斷 (Builder inference) 是一種特殊的類型推斷兽赁,在調(diào)用泛型構(gòu)建器函數(shù)時(shí)很有幫助。 它可以幫助編譯器推斷調(diào)用的類型實(shí)參,方法是使用其 lambda 實(shí)參中其他調(diào)用的相關(guān)類型信息刀崖。

在此版本中惊科,如果常規(guī)類型推斷無(wú)法獲得有關(guān)類型的足夠信息,即可自動(dòng)激活構(gòu)建器推斷亮钦。(以前需額外指定 -Xenable-builder-inference 編譯器選項(xiàng)——在 1.6.0 版本中引入)馆截。這意味著現(xiàn)在您無(wú)需應(yīng)用任何額外的注解或選項(xiàng),即可編寫(xiě)自己的使用構(gòu)建器類型推斷的構(gòu)建器蜂莉。

FunnySaltyFish:放幾個(gè)栗子:

val result = buildList {
    // Type argument is inferred into Float based on the expected type
    val x: Float = get(0)
} // result has the List<Float> type

fun takeMyLong(x: Long) { ... }

fun String.isMoreThat3() = length > 3

fun takeListOfStrings(x: List<String>) { ... }

fun main() {
    val result1 = buildList {
        val x = get(0)
        takeMyLong(x)
    } // result1 has the List<Long> type

    val result2 = buildList {
        val x = get(0)
        val isLong = x.isMoreThat3()
    // ...
    } // result2 has the List<String> type

    val result3 = buildList {
        takeListOfStrings(this)
    } // result3 has the List<String> type
}

更多內(nèi)容詳見(jiàn): 了解如何編寫(xiě)自定義通用構(gòu)建器蜡娶。

穩(wěn)定的 opt-in requirements

Opt-in requirements 已為 Stable ,無(wú)需添加額外的編譯器參數(shù).

在 1.7.0 之前, opt-in 需要指定參數(shù) -opt-in=kotlin.RequiresOptIn 以避免 warning映穗,現(xiàn)在不需要了; 不過(guò)窖张,您仍然可使用 -opt-in 選擇加入其他 annotations、 module-wise.

穩(wěn)定的明確非空類型

在 Kotlin 1.7.0 中蚁滋,絕對(duì)不可為 null 的類型已提升為 Stable荤堪。它們?cè)跀U(kuò)展通用 Java 類和接口時(shí)提供了更好的互操作性。

使用新語(yǔ)法 T & Any 標(biāo)記此為明確非空(絕對(duì)不可空)類型枢赔。 此語(yǔ)法來(lái)自 intersection types 的符號(hào)澄阳。在 & 左側(cè)為可空的類型參數(shù),右側(cè)為不可空的Any踏拜。

fun <T> elvisLike(x: T, y: T & Any): T & Any = x ?: y

fun main() {
    // OK
    elvisLike<String>("", "").length
    // 錯(cuò)誤: 'null' 無(wú)法用于 non-null 值
    elvisLike<String>("", null).length

    // OK
    elvisLike<String?>(null, "").length
    // 錯(cuò)誤: 'null' 無(wú)法用于 non-null 值
    elvisLike<String?>(null, null).length
}

在此 KEEP 中了解有關(guān)絕對(duì)不可為 null 的類型的更多信息碎赢。

標(biāo)準(zhǔn)庫(kù)

在 Kotlin 1.7.0 中,標(biāo)準(zhǔn)庫(kù)進(jìn)行了一系列更改和改進(jìn)速梗。它們引入了新功能肮塞,穩(wěn)定了實(shí)驗(yàn)性功能,并統(tǒng)一了對(duì) Native姻锁、JS 和 JVM 的命名捕獲組的支持:

min() 和 max() 集合函數(shù)回歸

Kotlin 1.4 中枕赵,我們將 min()max() 集合函數(shù)重命名為 minOrNull()maxOrNull()。 這些新的名稱能夠更好地反映它們的行為 – 如果接收器集合為空位隶,則返回 null拷窜。 它還有助于使函數(shù)的行為與整個(gè) Kotlin Collections API 中使用的命名慣例保持一致。

minBy()涧黄、maxBy()篮昧、minWith()maxWith() 同樣如此,在 Kotlin 1.4 中均具有自己的 *OrNull() 同義詞笋妥。 受此變更影響的舊函數(shù)已逐漸棄用懊昨。

Kotlin 1.7.0-Beta 重新引入了原始的函數(shù)名稱枚尼,但加入了不可空返回類型鸯隅。 現(xiàn)在,更新后的 min()登颓、max()minBy()躏惋、maxBy()幽污、minWith()maxWith() 會(huì)嚴(yán)格返回集合元素或拋出異常。

fun main() {
    val numbers = listOf<int>()
    println(numbers.maxOrNull()) // "null"
    println(numbers.max()) // "Exception in… Collection is empty."
}

正則表達(dá)式特定位置匹配

在 1.5.30 中引入Regex.matchAt()Regex.matchesAt() 函數(shù)現(xiàn)已達(dá)到穩(wěn)定版本其掂。 它們提供了一種方式來(lái)檢查正則表達(dá)式在 StringCharSequence 中的特定位置是否具有精確匹配油挥。

  • matchesAt() 可以檢查匹配并返回布爾結(jié)果:
fun main(){
    val releaseText = "Kotlin 1.7.0 is on its way!"
    // 正則表達(dá)式: 一個(gè)數(shù)字, “.”, 一個(gè)數(shù)字, “.”, 一個(gè)或多個(gè)數(shù)字
    val versionRegex = "\\d[.]\\d[.]\\d+".toRegex()

    println(versionRegex.matchesAt(releaseText, 0)) // "false"
    println(versionRegex.matchesAt(releaseText, 7)) // "true"
}

  • matchAt() 會(huì)在找到匹配的情況下返回匹配潦蝇,在未找到匹配的情況下返回 null
fun main(){
    val releaseText = "Kotlin 1.7.0 is on its way!"
    val versionRegex = "\\d[.]\\d[.]\\d+".toRegex()

    println(versionRegex.matchAt(releaseText, 0)) // "null"
    println(versionRegex.matchAt(releaseText, 7)?.value) // "1.7.0"
}

對(duì)以前語(yǔ)言和 API 版本的擴(kuò)展支持

為了支持庫(kù)作者 開(kāi)發(fā)可在各種舊 Kotlin 版本中使用的庫(kù)款熬,并解決 Kotlin 主版本更新頻率增加的問(wèn)題,我們擴(kuò)展了對(duì)以前語(yǔ)言和 API 版本的支持攘乒。

在 Kotlin 1.7.0 中贤牛,我們支持三個(gè)以前的語(yǔ)言和 API 版本,而不是兩個(gè)则酝。這意味著 Kotlin 1.7.0 支持針對(duì) 1.4.0 的 Kotlin 版本的庫(kù)開(kāi)發(fā)殉簸。有關(guān)向后兼容性的詳細(xì)信息,請(qǐng)參閱兼容性模式沽讹。

通過(guò)反射獲取注解

1.6.0 首次引入的 拓展函數(shù) KAnnotatedElement.findAnnotations() 現(xiàn)已進(jìn)入 Stable. 此 反射 函數(shù)返回某元素特定類型的所有注解, 包括 獨(dú)立使用 和 重復(fù)使用 的注解.

@Repeatable
annotation class Tag(val name: String)

@Tag("First Tag")
@Tag("Second Tag")
fun taggedFunction() {
    println("I'm a tagged function!")
}

fun main() {
    val x = ::taggedFunction
    val foo = x as KAnnotatedElement
    println(foo.findAnnotations<Tag>())
    // [@Tag(name=First Tag), @Tag(name=Second Tag)]
}

穩(wěn)定的深度遞歸函數(shù)

深度遞歸函數(shù) (DeepRecursiveFunction) 自 Kotlin 1.4.0 以來(lái)一直作為實(shí)驗(yàn)性功能提供般卑,現(xiàn)在它們?cè)?Kotlin 1.7.0 中是穩(wěn)定的。使用DeepRecursiveFunction 可以定義一個(gè)函數(shù)爽雄,該函數(shù)將其堆棧保留在堆上蝠检,而不是實(shí)際的調(diào)用堆棧。這允許您運(yùn)行非常深的遞歸計(jì)算挚瘟。使用invoke以調(diào)用這類函數(shù)叹谁。

在此示例中,深度遞歸函數(shù)用于以遞歸方式計(jì)算二叉樹(shù)的深度乘盖。即使此示例函數(shù)以遞歸方式調(diào)用自身 100焰檩,000 次,也不會(huì)拋出 StackOverflowError

class Tree(val left: Tree?, val right: Tree?)

val calculateDepth = DeepRecursiveFunction<Tree?, Int> { t ->
    if (t == null) 0 else maxOf(
        callRecursive(t.left),
        callRecursive(t.right)
    ) + 1
}

fun main() {
    // 生成一顆深度為 100000 的二叉樹(shù)
    val deepTree = generateSequence(Tree(null, null)) { prev ->
        Tree(prev, null)
    }.take(100_000).last()

    println(calculateDepth(deepTree)) // 100000
}

若遞歸深度超過(guò)1000订框, 請(qǐng)考慮在代碼中使用深度遞歸函數(shù)析苫。

基于默認(rèn)時(shí)間源的時(shí)間標(biāo)記現(xiàn)在基于內(nèi)聯(lián)類

Kotlin 1.7.0 通過(guò)將 返回的時(shí)間標(biāo)記更改為內(nèi)聯(lián)類,提高了時(shí)間測(cè)量功能的性能穿扳。這意味著調(diào)用像TimeSource.Monotonic藤违、markNow()elapsedNow()纵揍、measureTime()顿乒、measureTimedValue()TimeMark 這樣的函數(shù)不會(huì)為其實(shí)例分配包裝類泽谨。特別是在測(cè)量作為hot path一部分的代碼段時(shí)璧榄,這有助于最大限度地減少測(cè)量對(duì)性能的影響:

@OptIn(ExperimentalTime::class)
fun main() {
    val mark = TimeSource.Monotonic.markNow() // 返回的 `TimeMark` 為內(nèi)聯(lián)類
    val elapsedDuration = mark.elapsedNow()
}

僅當(dāng)從 TimeMark 中獲取的時(shí)間源對(duì) TimeSource.Monotonic 為靜態(tài)時(shí)特漩,此優(yōu)化才可用。

Java Optionals 的新實(shí)驗(yàn)性擴(kuò)展函數(shù)

Kotlin 1.7.0 附帶了新的便利函數(shù)骨杂,簡(jiǎn)化了 Java 中Optional類的使用涂身。這些新功能可用于在 JVM 上拆箱和轉(zhuǎn)換可選對(duì)象,并幫助使 Java API 的使用更加簡(jiǎn)潔搓蚪。

拓展函數(shù)getOrNull()蛤售、getOrDefault()getOrElse() 允許您獲取 Optional 的值(如果有的話)妒潭。否則悴能,將視情況獲得null、默認(rèn)值或函數(shù)返回的值:

val presentOptional = Optional.of("FunnySaltyFish")

println(presentOptional.getOrNull())
// "FunnySaltyFish"

val absentOptional = Optional.empty<String>()

println(absentOptional.getOrNull()) // null
println(absentOptional.getOrDefault("給個(gè)默認(rèn)值")) // "給個(gè)默認(rèn)值"
println(absentOptional.getOrElse {
    println("Optional 值缺失")
    "默認(rèn)值"
})
// "Optional 值缺失"
// "默認(rèn)值"

擴(kuò)展函數(shù) toList()雳灾、toSet()漠酿、asSequence()將現(xiàn)有 Optional的值轉(zhuǎn)換為列表、集合或序列谎亩,否則返回空集合炒嘲。擴(kuò)展函數(shù) toCollection()將值追加到已存在的目標(biāo)集合:

val presentOptional = Optional.of("I'm here!")
val absentOptional = Optional.empty<String>()
println(presentOptional.toList() + "," + absentOptional.toList())
// ["I'm here!"], []
println(presentOptional.toSet() + "," + absentOptional.toSet())
// ["I'm here!"], []
val myCollection = mutableListOf<String>()
absentOptional.toCollection(myCollection)
println(myCollection)
// []
presentOptional.toCollection(myCollection)
println(myCollection)
// ["I'm here!"]
val list = listOf(presentOptional, absentOptional).flatMap { it.asSequence() }
println(list)
// ["I'm here!"]

這些擴(kuò)展函數(shù)在 Kotlin 1.7.0 中作為實(shí)驗(yàn)性引入。您可以在此 KEEP 中了解有關(guān)Optional擴(kuò)展的更多信息匈庭。與往常一樣夫凸,我們歡迎您在 Kotlin 問(wèn)題跟蹤器中提供反饋。

支持 JS 和本機(jī)中的命名捕獲組

從 Kotlin 1.7.0 開(kāi)始阱持,命名捕獲組不僅在 JVM 上受支持夭拌,在 JS 和 Native 平臺(tái)上也受支持。

若要為捕獲組命名紊选,請(qǐng)?jiān)谡齽t表達(dá)式中使用 (?<name>group) 語(yǔ)法啼止。若要獲取與組匹配的文本,請(qǐng)調(diào)用新引入的 MatchGroupCollection.get() 函數(shù)并傳遞組名兵罢。

按名稱檢索匹配的組值

fun dateReplace() {
    val dateRegex = Regex("(?<dd>\\d{2})-(?<mm>\\d{2})-(?<yyyy>\\d{4})")
    val input = "Date of birth: 27-04-2022"
    println(dateRegex.replace(input, "\${yyyy}-\${mm}-\${dd}")) // "Date of birth: 2022-04-27" — by name
    println(dateRegex.replace(input, "\$3-\$2-\$1")) // "Date of birth: 2022-04-27" — by number
}

命名反向引用

現(xiàn)在献烦,您還可以在反向引用組時(shí)使用組名。反向引用與捕獲組先前匹配的相同文本匹配卖词。為此巩那,請(qǐng)使用正則表達(dá)式中的語(yǔ)法:\k<name>

fun backRef() {
    val regex = "(?<title>\\w+), yes \\k<title>".toRegex()
    val match = regex.find("Do you copy? Sir, yes Sir!")!!
    println(match.value) // "Sir, yes Sir"
    println(match.groups["title"]?.value) // "Sir"
}

換表達(dá)式中的命名組

命名組引用可與替換表達(dá)式一起使用。請(qǐng)考慮 replace() 函數(shù)此蜈,該函數(shù)將輸入中指定正則表達(dá)式的所有匹配項(xiàng)替換為替換表達(dá)式即横;以及僅替換第一個(gè)匹配項(xiàng)的 replaceFirst() 函數(shù)。

替換字符串中出現(xiàn)的 ${name} 將替換為與具有指定名稱的捕獲組相對(duì)應(yīng)的子序列裆赵。您可以按名稱和索引比較組引用中的替換項(xiàng):

fun dateReplace() {
    val dateRegex = Regex("(?<dd>\\d{2})-(?<mm>\\d{2})-(?<yyyy>\\d{4})")
    val input = "Date of birth: 27-04-2022"
    println(dateRegex.replace(input, "\${yyyy}-\${mm}-\${dd}")) // "Date of birth: 2022-04-27" — by name
    println(dateRegex.replace(input, "\$3-\$2-\$1")) // "Date of birth: 2022-04-27" — by number
}

Gradle

好多东囚,不翻了。見(jiàn) kotlinlang.org/docs/whatsn…

除上述之外战授,還有一些涉及到 JS/Native 的部分沒(méi)有翻譯页藻,感興趣的可自行參閱原鏈接桨嫁。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市份帐,隨后出現(xiàn)的幾起案子璃吧,更是在濱河造成了極大的恐慌,老刑警劉巖废境,帶你破解...
    沈念sama閱讀 212,686評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件畜挨,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡噩凹,警方通過(guò)查閱死者的電腦和手機(jī)巴元,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,668評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)栓始,“玉大人务冕,你說(shuō)我怎么就攤上這事血当』米” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 158,160評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵臊旭,是天一觀的道長(zhǎng)落恼。 經(jīng)常有香客問(wèn)我,道長(zhǎng)离熏,這世上最難降的妖魔是什么佳谦? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,736評(píng)論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮滋戳,結(jié)果婚禮上钻蔑,老公的妹妹穿的比我還像新娘。我一直安慰自己奸鸯,他們只是感情好咪笑,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,847評(píng)論 6 386
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著娄涩,像睡著了一般窗怒。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上蓄拣,一...
    開(kāi)封第一講書(shū)人閱讀 50,043評(píng)論 1 291
  • 那天扬虚,我揣著相機(jī)與錄音,去河邊找鬼球恤。 笑死辜昵,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的咽斧。 我是一名探鬼主播堪置,決...
    沈念sama閱讀 39,129評(píng)論 3 410
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼贷洲,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了晋柱?” 一聲冷哼從身側(cè)響起优构,我...
    開(kāi)封第一講書(shū)人閱讀 37,872評(píng)論 0 268
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎雁竞,沒(méi)想到半個(gè)月后钦椭,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,318評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡碑诉,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,645評(píng)論 2 327
  • 正文 我和宋清朗相戀三年彪腔,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片进栽。...
    茶點(diǎn)故事閱讀 38,777評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡德挣,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出快毛,到底是詐尸還是另有隱情格嗅,我是刑警寧澤,帶...
    沈念sama閱讀 34,470評(píng)論 4 333
  • 正文 年R本政府宣布唠帝,位于F島的核電站屯掖,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏襟衰。R本人自食惡果不足惜贴铜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,126評(píng)論 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望瀑晒。 院中可真熱鬧绍坝,春花似錦、人聲如沸苔悦。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,861評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)间坐。三九已至灾挨,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間竹宋,已是汗流浹背劳澄。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,095評(píng)論 1 267
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留蜈七,地道東北人秒拔。 一個(gè)月前我還...
    沈念sama閱讀 46,589評(píng)論 2 362
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像飒硅,于是被迫代替她去往敵國(guó)和親砂缩。 傳聞我的和親對(duì)象是個(gè)殘疾皇子作谚,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,687評(píng)論 2 351

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