六,類的進(jìn)階

1,類的構(gòu)造器

當(dāng)我們定義一個(gè)Person類時(shí)

class Person(var name:String,age:Int)
  • 帶 var/val 字段的屬性 是類內(nèi)全局可見的
  • 而后面age 不帶var/val 該屬性僅在構(gòu)造器內(nèi)可見(init塊,屬性初始化)

上面的定義相當(dāng)于

class Person(var name: String, age: Int) {
    var age = 0
    init {
        this.age = age
        println(this.age)
    }
}
<1>init塊
  • init塊跟Java中的構(gòu)造塊基本類似,唯一的區(qū)別是Kotlin中init塊中能訪問到構(gòu)造函數(shù)中的不帶var/val 的變量

例如

class Person(var name: String, age: Int) {
    var age = 0
    init {
        this.age = age
        println(this.age)
    }
    var testa=3
    init {
        this.age=testa
        println(this.age)  
    }
}

他們會(huì)一起編譯到函數(shù)的構(gòu)造函數(shù)中一起執(zhí)行

<2>類的屬性必須初始化

Kotlin類的屬性必須初始化,類的生命周期和屬性的相同,這樣使用者在調(diào)用類的屬性時(shí)不會(huì)有負(fù)擔(dān)

<3>類的繼承

子類繼承父類必須調(diào)用父類的構(gòu)造方法

abstract class Anim

class Pig(var name: String):Anim(){
    //必須調(diào)用父類構(gòu)造函數(shù)
}
<4>副構(gòu)造器
  • 副構(gòu)造器:定義在主構(gòu)造器后在類內(nèi)部定義的構(gòu)造器都被成為福構(gòu)造器
  • 副構(gòu)造器必須調(diào)用到主構(gòu)造器,確保構(gòu)造路徑唯一性
abstract class Anim

class Pig(var name: String) : Anim() {
    //必須調(diào)用父類構(gòu)造函數(shù)
    var age = 0;
    constructor(age: Int) : this("fff") {
        this.age = age
    }
}
不定義主構(gòu)造器(不推薦)
abstract class Anim
class Dog : Anim{
    var name:String
    var age:Int
    constructor(name: String,age:Int):super(){
        this.name=name
        this.age= age
    }
}
一般情況下有這種情況的,比較推薦使用:主構(gòu)造器+默認(rèn)參數(shù)的形式
<5>工廠函數(shù)
fun main() {
    //Person的工廠方法
    Person("1111111")
    //String中系統(tǒng)的工廠方法
    String(charArrayOf('1'))
    //自定義String
    String(IntArray(2){ it })
}

val persons=HashMap<String,Person>()

fun Person(name: String):Person{
    //緩存person對(duì)象
    return persons[name]?:Person(name,25).also { persons[name] = it }
}

fun String(ints:IntArray):String{
    return ints.contentToString()
}

工廠函數(shù)和擴(kuò)展方法:個(gè)人理解擴(kuò)展方法的場(chǎng)景更大一些,而工廠函數(shù)的意義就是為了創(chuàng)建該類的對(duì)象,擴(kuò)展方法可以返回該類對(duì)象也可以返回為Unit

2,類與成員的可見性

<1>模塊的概念
  • Intelij IDEA 模塊
  • Maven工程
  • Gradle SourceSet
  • Ant 任務(wù)中一次調(diào)用<kotlinc>的文件
  • 直觀的講模塊的可以認(rèn)為是一個(gè)jar包,一個(gè)aar包,通常一個(gè)jar包或者aar包里面所有的源文件會(huì)一次通過<kotlinc>通過編譯
<2> internal VS default
  • 一般由SDK或者公共組件開發(fā)者用于隱藏內(nèi)部實(shí)現(xiàn)細(xì)節(jié)
  • default 可通過外部創(chuàng)建相同的包名進(jìn)行訪問,訪問控制比較弱
  • default 會(huì)導(dǎo)致不同抽象層次的類聚集到相同的包之下
  • internal 可方便處理內(nèi)外隔離,提升模塊代碼內(nèi)聚減少接口暴露
  • internal 修飾的Kotlin類或者成員在Java中可直接訪問
針對(duì)Kotlin中被internal修飾的類能被Java訪問,可以通過一些特殊手段讓其不能訪問,例如下例:
internal class CoreApiKotlinA {
    @JvmName("%abcd")
    internal fun a(){
        println("Hello A")
    }
}
<3>構(gòu)造器可見性
class Cat :Anim {
    var name: String
    var age: Int
    private constructor(name: String, age: Int):super() {
        this.name = name
        this.age = age
    }
}

可用于單例

<4>類的屬性可見性
class Half (private var name: String,var age: Int){
    private var sex:Boolean=true
    init {
        println("$name---$age")
    }
}
//只能訪問到age和sex
var half = Half("111", 2)
half.age=11

屬性的getter和setter

- 屬性的getter必須和屬性的可見 一致

下例中 sex是public 所以不能把getter設(shè)置為private

class Half (private var name: String,var age: Int){
    var sex:Boolean=true
    private set
    //private get
}
- 屬性的setter可見性不得大于屬性的可見性
class Half(private var name: String, var age: Int) {
    private var firstName: String = ""
//    public set
}
<5>頂級(jí)聲明的可見性(Kotlin獨(dú)有)
  • 頂級(jí)聲明指文件內(nèi)直接定義的屬性,函數(shù),類等
  • 頂級(jí)聲明不支持protect
  • 頂級(jí)聲明被private修飾表示文件內(nèi)可見

3,類屬性的延遲初始化

為什么要延遲初始化?

  • 類屬性必須在構(gòu)造時(shí)進(jìn)行初始化
  • 某些成員只有在類初始化后才會(huì)別初始化
class Beer(var name: String,var age: Int){
   lateinit var firstName:String
}

常見的例子有:在Android中控件的初始化是在Activity的onCreate()方法中才能初始化,可以使用lateinit進(jìn)行延遲初始化

lateinit的注意事項(xiàng)
  • lateinit 會(huì)讓編譯器忽略變量的初始化,不支持Int等基本類型
  • 開發(fā)者必須能夠在完全確定變量的生命周期下使用lateinit
  • 不要在復(fù)雜的邏輯中使用lateinit,它只會(huì)讓代碼變得更加脆弱
  • Kotlin在1.2引入判斷l(xiāng)ateinit屬性是否初始化的api 最好不要用
lazy

4蚓聘,代理 Delegate

接口代理

對(duì)象X 代替當(dāng)前類A 實(shí)現(xiàn)接口B的方法

我 代替 你 處理了 它

屬性代理

對(duì)象X代替屬性a實(shí)現(xiàn)getter/setter方法

<1>接口代理

定義接口

interface InterFace {
    fun funA()
    fun funB()
    fun funC()
}

定義增強(qiáng)接口類

 class InterfaceWrapper(var inter:InterFace):InterFace{
     override fun funA() {
         inter.funA()
     }

     override fun funB() {
         inter.funB()
     }

     override fun funC() {
         println("---------------")
         inter.funC()
     }

代理形式

 class InterWrapper (private val inter: InterFace):InterFace by inter{
         override fun funC() {
             println("---------------")
         }
     }

接口 inter 代理 InterWrapper 實(shí)現(xiàn) 接口 InterFace 的方法

對(duì)于對(duì)象inter的唯一要求就是實(shí)現(xiàn)被代理的接口,因?yàn)槿绻鹖nter沒有實(shí)現(xiàn)接口方法的話,就不具有代理的能力

小案例 創(chuàng)建一個(gè)SupportArray

class SupperArray<E>(
    private val list: MutableList<E?> = ArrayList(),
    private val map: MutableMap<String, E> = HashMap()
) : MutableList<E?> by list, MutableMap<String, E> by map {
    override fun isEmpty(): Boolean {
        return list.isEmpty() && map.isEmpty()
    }

    override fun clear() {
        list.clear()
        map.clear()
    }

    override val size: Int
        get() = list.size + map.size

    override fun set(index: Int, element: E?): E? {
        if (list.size <= index) {
            repeat(index - list.size + 1) {
                list.add(null)
            }
        }
        return list.set(index, element)
    }

    override fun toString(): String {
        return "list:${list};map:${map}"
    }
}

SupportArray

  • 實(shí)現(xiàn) MutableList 被list代理了接口的實(shí)現(xiàn)
  • 實(shí)現(xiàn)MutableMap 被map代理了接口的實(shí)現(xiàn)

使用SupperArray

fun main() {
    val supperArray = SupperArray<String>()
    supperArray.add("Hello")
    supperArray["Hello"] = "wwwwwwwwww"
    supperArray["Word"] = "fffffffffffff"
    supperArray[4] = "$$$$$$$$$"
    println(supperArray)
}

輸出

list:[Hello, null, null, null, $$$$$$$$$];
map:{Word=fffffffffffff, Hello=wwwwwwwwww}
<2>屬性代理
getter方法代理
class PersonNow(var sex: Boolean) {
    val firstName: String by lazy {
        if (sex)
            "nan"
        else
            "nv"
    }
}

源碼分析

--lazy方法

public actual fun <T> lazy(initializer: () -> T): Lazy<T> = 
SynchronizedLazyImpl(initializer)

--Lazy.kt

@kotlin.internal.InlineOnly
public inline operator fun <T> Lazy<T>.getValue(thisRef: Any?, 
property: KProperty<*>): T = value

可以看到Lazy定義的方法 getValue

getValue(thisRef: Any?, property: KProperty<*>)

要想代理屬性的getter需要重寫該方法

setter方法代理

對(duì)于setter方法,其代理可分為兩步:開始設(shè)置和設(shè)置之后

Delegates.observable代理設(shè)置之后
class Manger {
    var state:Int by Delegates.observable(0){
        property, oldValue, newValue ->
        println("$oldValue,$newValue")
    }
}
Delegates.vetoable代理設(shè)置之前
class Mantou {
    var ss: Int by Delegates.vetoable(0) { property, oldValue, newValue ->
        println("$oldValue,$newValue")
        newValue % 2 == 0
    }
}

調(diào)用

fun main() {
    val mantou = Mantou()
    mantou.ss = 1
    mantou.ss = 2
    mantou.ss = 3
    mantou.ss = 4
}

結(jié)果

0,1
0,2
2,3
2,4

Delegates.vetoable 給定初始化值后其結(jié)果返回值為Boolean,如果返回true表示允許本次對(duì)屬性的設(shè)置,屬性的值為newValue,返回false表示攔截此次設(shè)置值,屬性的值仍然為oldValue

源碼得知
Delegate.observable 返回 ReadWriteProperty

public interface ReadWriteProperty<in R, T> {
    public operator fun getValue(thisRef: R, property: KProperty<*>): T
    public operator fun setValue(thisRef: R, property: KProperty<*>, value: T)
}

對(duì)于var 來說需要實(shí)現(xiàn)下列方法,就可以代理屬性

    public operator fun getValue(thisRef: R, property: KProperty<*>): T
    public operator fun setValue(thisRef: R, property: KProperty<*>, value: T)

對(duì)val來說 實(shí)現(xiàn)下方法即可代理屬性

  public operator fun getValue(thisRef: R, property: KProperty<*>): T

具體例子

class Food {
    var x: Int by X()
}

class X {
    operator fun getValue(thisRef: Any?, property: KProperty<*>): Int {
        println("getValue")
        return 2
    }

    operator fun setValue(thisRef: Any?, property: KProperty<*>, i: Int) {
        println("setValue")
    }
}

fun main() {
    val food = Food()
    food.x=1;
    println(food.x)
}

運(yùn)行結(jié)果

setValue
getValue
2

對(duì)food 的屬性 x 調(diào)用其getter或者setter時(shí)會(huì)調(diào)用的屬性代理

5,單例object

Kotlin中單例

  • 使用object進(jìn)行定義
  • 默認(rèn)生成無參構(gòu)造函數(shù)且不能自定義構(gòu)造器,但是可以通過init{}代碼塊進(jìn)行一些初始化操作
  • 跟普通的Kotlin類一樣可以實(shí)現(xiàn)接口,可接繼承其他類
  • 其本質(zhì)就是Kotlin使用餓漢式內(nèi)部生成了INSTANCE的實(shí)例
public object Sigten {
    var x: Int = 0
    var y: String = ""
    fun mm() {}
}

Kotlin中訪問

fun main() {
    Sigten.x = 3
    Sigten.y = "WWWWWWWW"
    println("${Sigten.x}||${Sigten.y}")
}

Java中訪問

Sigten.INSTANCE.mm();
Sigten.INSTANCE.setX(1);
Sigten.INSTANCE.getX();

由于Kotlin是一門跨平臺(tái)語言,不能因?yàn)镴vm上有靜態(tài)變量就定義出相應(yīng)的變量類型,這對(duì)于C語言和JavaScript行不通

@JvmStatic 模擬JVM平臺(tái)的靜態(tài)變量
public object Sigten {
    @JvmStatic var x: Int = 0
    @JvmStatic fun mm() {
    }
}

Java調(diào)用

Sigten.mm();
Sigten.setX(1);
Sigten.getX();
@JvmField 不讓Kotlin屬性生成getter和setter,直接訪問屬性
public object Sigten {
    @JvmStatic var x: Int = 0
    @JvmField var y:Int=0
    @JvmStatic fun mm() {
    }
}

Java調(diào)用

Sigten.mm();
Sigten.setX(1);
Sigten.getX();
Sigten.y=1;
伴生對(duì)象
  • 是某個(gè)類的另一半
  • 其名稱和所在類相同
  • 伴生對(duì)象也是單例的
class FoodX {
    companion object {
        @JvmStatic var x: Int = 0
        @JvmStatic fun mm() {
        }
    }
}

想當(dāng)于Java中

public class FoodX {
    public static int x = 0;
    public static void mm(){}
}

6,內(nèi)部類

  • 內(nèi)部類分為靜態(tài)內(nèi)部類和非靜態(tài)內(nèi)部類
  • 靜態(tài)內(nèi)部類不需要引用外部對(duì)象,可直接創(chuàng)建對(duì)象
  • 非靜態(tài)內(nèi)部類需要引用外部對(duì)象,容易引起內(nèi)存泄露
class Outer{
    //內(nèi)部類
    inner class Inner(){}
    //靜態(tài)內(nèi)部類
    class StaticInner(){}
}

使用

fun main() {
    //創(chuàng)建非靜態(tài)內(nèi)部類
    var inner = Outer().Inner()
    //創(chuàng)建靜態(tài)內(nèi)部類
    var staticInner = Outer.StaticInner()
}
<1>內(nèi)部object
  • 內(nèi)部object 不存在非靜態(tài),都是靜態(tài)
object OuterObject {
    object InnerStaticObject {
        var x: Int = 0
    }
}

使用

OuterObject.InnerStaticObject.x=3
<2>匿名內(nèi)部類
object :Runnable{
        override fun run() {
        }
    }
和Java中不同的是,Kotlin中匿名內(nèi)部類支持多實(shí)現(xiàn)或繼承父類

例如

object :Runnable,Cloneable{
        override fun run() {
        }
    }
Java中也可以實(shí)現(xiàn)方法中多繼承 使用LocalClass
public class TestObjeck {
    public static void main(String[] args) {
        class LocalClass implements Cloneable,Runnable{
            @Override
            public void run() {
            }
        }
    }
}
Kotlin中不僅支持LocalClass 還支持localMethod(方法中定義方法)
  object :Runnable,Cloneable{
        override fun run() {
        }
    }

    class LocalClass:Runnable,Cloneable{
        override fun run() {
        }
    }

    fun localMethod(){}

7,數(shù)據(jù)類 data class

component: 定義在主構(gòu)造器中的屬性又被稱為component

  • 數(shù)據(jù)類和一般類最大的區(qū)別就在于component
  • Kotlin中的data class 不等價(jià)與Java bean
  • 編譯器會(huì)基于component 自動(dòng)生成 equals/hashCode/toString/copy
data class TT(val name: String, val age: Int) {}
fun main() {
    var tt = TT("", 4)
}
如何合理的使用data class
  • 單純的把data class 當(dāng)成數(shù)據(jù)結(jié)構(gòu)使用既是純數(shù)據(jù),大多數(shù)情況下不需要額外的實(shí)現(xiàn)
  • 主構(gòu)造函數(shù)的變量類型 最好為基本類型\String 或者其他data class 保證數(shù)據(jù)類為純數(shù)據(jù)
  • component 不能定義getter和setter 為了防止通過getter或者setter 進(jìn)行數(shù)據(jù)篡改
  • 定義構(gòu)造函數(shù)的變量 最好定義為 val ,如果可變會(huì)導(dǎo)致其hashCode等值的改變 如果該對(duì)象在hashset中 則無法移除該元素

為了實(shí)現(xiàn)一些特殊的需求,需要data class 有無參構(gòu)造和可以被繼承,官方提供了 noArg 和allOpen 插件進(jìn)行支持

id 'org.jetbrains.kotlin.plugin.noarg' version '1.3.60'
id 'org.jetbrains.kotlin.plugin.allopen' version '1.3.60'

8, 枚舉類 enum class

  • 和 Java中枚舉相似 區(qū)別是通過 enum class 定義

無參構(gòu)造枚舉

enum class CC {
    Idle, Busy
}

有參構(gòu)造枚舉

enum class DD(arg: Int) {
    Idle(0), Busy(1)
}

枚舉實(shí)現(xiàn)接口--統(tǒng)一實(shí)現(xiàn)方式

enum class FF : Runnable {
    Idle, Busy;

    override fun run() {
    }
}

枚舉實(shí)現(xiàn)接口--單獨(dú)實(shí)現(xiàn)方式

enum class EE : Runnable {
    Idle {
        override fun run() {
        }
    },
    Busy {
        override fun run() {
        }
    };
}
<1>因?yàn)閑num 枚舉本身是個(gè)類 所以可以為其定義擴(kuò)展方法
<2>枚舉本事是可數(shù)的所在when 條件語句中可以不加else
<3> 因?yàn)槊杜e本身有順序的概念所以可以對(duì)其進(jìn)行比較大小
<4> 枚舉有順序所以也有區(qū)間概念
enum class Color {
    White, Red, Black, Pink, Ori, Yellow
}
fun main() {
    val ran = Color.Black..Color.Yellow
    val color = Color.White
    color in ran
}

9,密封類 sealed class

  • 密封類是一種特殊的抽象類
  • 密封類的子類必須定義在與自身相同的文件中
  • 因?yàn)槊芊忸惖淖宇惗x范圍有限,所以密封類的子類有限,一旦定義好密封類的子類后,外部不可能出現(xiàn)其他子類
  • 密封類首先是個(gè)抽象類,其次是個(gè)密封類

例子

sealed class PlayState

object Idle : PlayState()

object Playing : PlayState() {
    fun start() {}
    fun stop() {}
}

object Error : PlayState() {
    fun recover() {}
}

使用上面定義的幾個(gè)類型做個(gè)小案例

class Player {
    var state: PlayState = Idle

    fun play() {
        this.state = when (val state = this.state) {
           is Idle -> {
                Playing.also {
                    it.start()
                }
            }
            is Playing -> {
                state.stop()
                state.also {
                    it.start()
                }
            }
            is Error -> {
                state.recover()
                Playing.also {
                    it.start()
                }
            }
        }
    }
}
如何區(qū)分使用密封類還是枚舉呢
  1. 如果需要進(jìn)行類型區(qū)分則是使用密封類,如果要進(jìn)行值的區(qū)分 則用枚舉
  2. 枚舉類不能創(chuàng)建對(duì)象,而密封類可以創(chuàng)建對(duì)象

枚舉不能創(chuàng)建對(duì)象這點(diǎn)個(gè)人理解起來比較難一點(diǎn),為什么不能枚舉就不能創(chuàng)建對(duì)象呢?
因?yàn)槊杜e就是實(shí)例對(duì)象的存在<O(∩_∩)O哈哈~>
而密封類則不同,他的分支是類型,只要是子類的對(duì)象就行,因此可以創(chuàng)建多個(gè)對(duì)象

10,內(nèi)聯(lián)類 inline class

  • 內(nèi)聯(lián)類是對(duì)某一個(gè)類型的包裝
  • 類似于Java中裝箱類型的一種類型
  • 編譯器會(huì)盡可能使用被包裝的類型進(jìn)行優(yōu)化
  • 內(nèi)聯(lián)類目前在1.3版本中處于公測(cè)階段,謹(jǐn)慎使用
使用注意
  1. 內(nèi)聯(lián)類不能有backingfiled 只能有方法
  2. 內(nèi)聯(lián)類可以實(shí)現(xiàn)接口,但不能繼承父類也不能被繼承

例子

inline class BoxInt(private val value: Int) {
    operator fun inc(): BoxInt {
        return BoxInt(value + 1)
    }
}
內(nèi)聯(lián)類的使用場(chǎng)景
  • 官方 使用內(nèi)聯(lián)類 實(shí)現(xiàn)無符號(hào)類型
  • 內(nèi)聯(lián)類模擬枚舉,因?yàn)槊杜e內(nèi)存開銷比較大,和dex文件大小
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末留荔,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子摸航,更是在濱河造成了極大的恐慌,老刑警劉巖宾抓,帶你破解...
    沈念sama閱讀 219,490評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件肠牲,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡阿弃,警方通過查閱死者的電腦和手機(jī)诊霹,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,581評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來渣淳,“玉大人脾还,你說我怎么就攤上這事∪肜ⅲ” “怎么了鄙漏?”我有些...
    開封第一講書人閱讀 165,830評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)棺蛛。 經(jīng)常有香客問我怔蚌,道長(zhǎng),這世上最難降的妖魔是什么鞠值? 我笑而不...
    開封第一講書人閱讀 58,957評(píng)論 1 295
  • 正文 為了忘掉前任媚创,我火速辦了婚禮,結(jié)果婚禮上彤恶,老公的妹妹穿的比我還像新娘钞钙。我一直安慰自己鳄橘,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,974評(píng)論 6 393
  • 文/花漫 我一把揭開白布芒炼。 她就那樣靜靜地躺著瘫怜,像睡著了一般。 火紅的嫁衣襯著肌膚如雪本刽。 梳的紋絲不亂的頭發(fā)上鲸湃,一...
    開封第一講書人閱讀 51,754評(píng)論 1 307
  • 那天,我揣著相機(jī)與錄音子寓,去河邊找鬼暗挑。 笑死,一個(gè)胖子當(dāng)著我的面吹牛斜友,可吹牛的內(nèi)容都是我干的炸裆。 我是一名探鬼主播,決...
    沈念sama閱讀 40,464評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼鲜屏,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼烹看!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起洛史,我...
    開封第一講書人閱讀 39,357評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤惯殊,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后也殖,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體土思,經(jīng)...
    沈念sama閱讀 45,847評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,995評(píng)論 3 338
  • 正文 我和宋清朗相戀三年毕源,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了浪漠。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,137評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡霎褐,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出该镣,到底是詐尸還是另有隱情冻璃,我是刑警寧澤,帶...
    沈念sama閱讀 35,819評(píng)論 5 346
  • 正文 年R本政府宣布损合,位于F島的核電站省艳,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏嫁审。R本人自食惡果不足惜跋炕,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,482評(píng)論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望律适。 院中可真熱鬧辐烂,春花似錦遏插、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,023評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至扣草,卻和暖如春了牛,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背辰妙。 一陣腳步聲響...
    開封第一講書人閱讀 33,149評(píng)論 1 272
  • 我被黑心中介騙來泰國(guó)打工鹰祸, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人密浑。 一個(gè)月前我還...
    沈念sama閱讀 48,409評(píng)論 3 373
  • 正文 我出身青樓蛙婴,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親肴掷。 傳聞我的和親對(duì)象是個(gè)殘疾皇子敬锐,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,086評(píng)論 2 355