Java中的注解和反射

文章首發(fā)我的博客怠褐,歡迎訪問:https://blog.itzhouq.cn/annotation-reflection

最近又回顧了一下 Java 中的注解和反射知識點较剃,注解在日常開發(fā)中使用很多,但是反射比較少嚣潜。值得注意的是 Java 的各種框架底層源碼中大量使用了注解和反射,閱讀源碼,這些是基本功赂毯,面試中這部分內(nèi)容也經(jīng)常問到。這里面概念不多,內(nèi)容略微有些枯燥党涕,但是通過一些簡單的例子烦感,能讓我們明白一些基本概念和 API 的使用。所以膛堤,說到底手趣,這篇博客只能算是一個簡單的筆記,希望對你有幫助肥荔。 以前也寫過枚舉類和注解的相關(guān)筆記绿渣,可以看看歷史文章 Java枚舉類和注解梳理

1燕耿、什么是注解

注解 Annotation 是從JDK1.5 開始引入的新技術(shù)中符。

注解的作用:不是程序本身,可以對程序作出解釋誉帅,能被其他程序讀取到淀散。

注解使用的位置:package、class蚜锨、method吧凉、field 等上面,相當(dāng)于給他們添加了額外的輔助信息踏志。我們可以通過反射機制實現(xiàn)對這些元數(shù)據(jù)的訪問阀捅。

2、元注解

元注解的作用就是負(fù)責(zé)注解其他的注解针余,Java 定義了 4 個標(biāo)準(zhǔn)的 meta-Annotation類型饲鄙,他們被用來提供對其他 Annotation 類型做說明。

  • Target:用于描述注解的使用范圍圆雁,注解可以用在什么地方忍级。隨便點擊一個注解,查看源碼可以看到這個位置使用 ElementType枚舉類表示伪朽,主要可以放在類上轴咱,方法上,屬性上等烈涮,我這就不細(xì)說了朴肺。
  • Retention:表示在什么級別保存該注解的信息,用于描述注解的生命周期坚洽。SOURCE < CLASS <RUNTIME戈稿。同樣看源碼,使用 RetentionPolicy枚舉類表示讶舰,有 SOURCE鞍盗,CLASS需了, RUNTIME“慵祝基本見名知意肋乍。
  • Document:說明該注解會被包含在 Javadoc中。
  • Inherited:說明子類可以繼承父類的該注解敷存。

3住拭、自定義注解

使用 @interface 自定義注解時,自動繼承了 java.lang.annotation.Annotation 接口历帚。

分析:

  • @interface:用來聲明一個注解滔岳,格式:public @interface 注解名{定義內(nèi)容}
  • 其中的每一個方法實際上就是一個配置參數(shù)挽牢;
  • 方法的名稱就是參數(shù)的名稱谱煤;
  • 返回的類型就是參數(shù)的類型(返回值只能是基本類型、Class禽拔、String刘离、enum);
  • 可以通過 default 來聲明參數(shù)的默認(rèn)值睹栖;
  • 如果只有一個參數(shù)成員硫惕,一般參數(shù)名為 value;
  • 注解元素必須要有值野来,我們定義注解元素時恼除,經(jīng)常使用空字符串,0作為默認(rèn)值曼氛。
// 自定義注解
public class Test {
    @MyAnnotation(age = 18, name = "Hello")
    public void test() {}

}

@interface MyAnnotation {
    // 注解的參數(shù):參數(shù)類型 + 參數(shù)名();
    String name() default "";
    int age();
    int id() default -1;
    String[] schools() default {"清華大學(xué)", "北京大學(xué)"};
}

4豁辉、什么是反射

反射(Reflection):是 Java 被視為動態(tài)語言的關(guān)鍵,反射機制允許程序在執(zhí)行期借助于 Reflection API 取得任何類的內(nèi)部信息舀患,并能直接操作任意對象的內(nèi)部屬性及方法徽级。

加載完類后,在堆內(nèi)存的方法區(qū)中就產(chǎn)生了一個 Class 類型的對象(一個類只有一個 Class 對象)聊浅,這個對象包含了完整的類的結(jié)構(gòu)信息餐抢。我們可以通過這個對象看到類的結(jié)構(gòu)。這個對象就像一面鏡子低匙,透過和鏡子看到類的結(jié)構(gòu)旷痕。所以我們形象地稱之為反射。

反射

Java發(fā)射的優(yōu)缺點:

優(yōu)點:可以實現(xiàn)動態(tài)創(chuàng)建對象和編譯努咐,體現(xiàn)很大的靈活性苦蒿;

缺點:對性能有影響殴胧,使用反射基本上是一種解釋操作渗稍,這類操作總是慢于直接執(zhí)行相同的操作佩迟。

public class Test01 {
    public static void main(String[] args) throws ClassNotFoundException {
        // 通過反射獲取類的Class對象
        Class c1 = Class.forName("Test01");
        Class c2 = Class.forName("Test01");
        System.out.println(c1); // class Test01

        // 一個類在內(nèi)存中只有一個Class對象
        // 一個類被加載后,類的整個結(jié)構(gòu)都會被封裝在Class對象中竿屹。
        System.out.println(c1.hashCode()); // 685325104
        System.out.println(c2.hashCode()); // 685325104
    }
}

class User{
    private String name;
    private int age;
    public User() {}
    public User(String name, int age) {
        this.name = name;
        this.age = age;
    }
    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
}

5报强、Class 類及其創(chuàng)建方式

在Object類中定義了一下方法,此方法將被所有子類繼承拱燃。

public final Class getClass()

此方法的返回值類型是一個Class類秉溉,此類是Java反射的源頭,實際上所謂反射從程序的運行結(jié)果來看也很好理解:即:可以通過對象反射求出類的名稱碗誉。

Class 類的特點:

  • Class本身也是一個類
  • Class對象只能由系統(tǒng)建立對象
  • 一個加載的類在 JVM 中只會有一個Class實例
  • 一個Class對象對應(yīng)的是一個加載到JVM中的一個.class文件
  • 每個類的實例都會記得自己是由哪一個Class實例所生成的
  • 通過Class可以完整的得到一個類中所有被加載的結(jié)構(gòu)
  • Class類是Reflection的根源針對任何你想要動態(tài)加載召嘶、運行的類,唯有先獲取相依的Class對象哮缺。
/**
 * 測試Class類的創(chuàng)建方式有哪些
 */
public class Test02 {
    public static void main(String[] args) throws ClassNotFoundException {
        Person person = new Student();
        System.out.println("這個人是:" + person.name); // 這個人是:學(xué)生

        // 方式一:通過對象獲得
        Class c1 = person.getClass();
        System.out.println(c1.hashCode()); // 460141958

        // 方式二:forName獲取
        Class c2 = Class.forName("Student");
        System.out.println(c2.hashCode()); // 460141958

        // 方式三:通過類名.class獲取【最為安全可靠弄跌,性能最高】
        Class c3 = Student.class;
        System.out.println(c3.hashCode()); // 460141958

        // 方式四:基本內(nèi)置類型的包裝類都有一個Type屬性
        Class c4 = Integer.TYPE;
        System.out.println(c4); // int
    }
}

class Person {
    String name;
    public Person() {
    }
    public Person(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                '}';
    }
}

class Student extends Person{
    public Student() {
        this.name = "學(xué)生";
    }
}

class Teacher extends Person{
    public Teacher() {
        this.name = "老師";
    }
}

注意:Class 類創(chuàng)建方式很大概率在面試中會被問到。

6尝苇、類的加載過程和ClassLoader的理解

Java內(nèi)存

當(dāng)程序主動使用某個類時铛只,如果該類還未被加載到內(nèi)存中,則系統(tǒng)會通過如下三個步驟來對該類進行初始化:

類的加載過程
  • 加載:將class文件字節(jié)碼內(nèi)容加載到內(nèi)存中糠溜,并將這些靜態(tài)數(shù)據(jù)轉(zhuǎn)換成方法區(qū)的運行時數(shù)據(jù)結(jié)構(gòu)淳玩,然后生成一個代表這個類的java.lang.Class對象;
  • 鏈接:將類的二進制代碼合并到JVM的運行狀態(tài)之中的過程非竿。
    • 驗證:確保的加載的類信息符合JVM規(guī)范蜕着,沒有安全方面的問題;
    • 準(zhǔn)備:正式為類變量(static)分配內(nèi)存并設(shè)置類變量默認(rèn)值的階段红柱,這些內(nèi)存都將在方法區(qū)中進行分配侮东;
    • 解析:虛擬機常量池內(nèi)的符號引用(常量名)替換為直接引用(地址)的過程;
  • 初始化:
    • 執(zhí)行類構(gòu)造器<clinit>()方法的過程豹芯。類構(gòu)造器<clinit>()方法是由編譯器自動收集類中所有類變量的賦值動作和靜態(tài)代碼塊中的語句合并產(chǎn)生的悄雅;
    • 當(dāng)初始化一個類的時候,如果發(fā)現(xiàn)其父類還沒有進行初始化铁蹈,則需要先觸發(fā)其父類的初始化宽闲;
    • 虛擬機會保證一個類的<clinit>()方法在多線程環(huán)境中被正確加鎖和同步。
public class Test03 {
    public static void main(String[] args) {
        A a = new A();
        System.out.println(a.m);
    }
}

class A {
    static {
        System.out.println("A類靜態(tài)代碼塊初始化");
        m = 300;
    }

    static int m = 100;

    public A () {
        System.out.println("A類的無參構(gòu)造初始化");
    }

//    A類靜態(tài)代碼塊初始化
//    A類的無參構(gòu)造初始化
//    100
    /**
     * 過程分析:
     *      1. 加載到內(nèi)存握牧,會產(chǎn)生一個類對象Class對象
     *      2. 鏈接容诬, 鏈接結(jié)束后 m = 0
     *      3. 初始化
     *      <clinit>(){
     *          System.out.println("A類靜態(tài)代碼塊初始化");
     *          m = 300;
     *          m = 100;
     *      }
     */
}
類加載內(nèi)存分析

7、分析類的初始化

什么時候會發(fā)生類的初始化沿腰?

  • 類的主動引用:一定會發(fā)生類的初始化
    • 當(dāng)虛擬機啟動览徒,先初始化 main 方法所在的類
    • new 一個類的對象
    • 調(diào)用類的靜態(tài)方法(除了 final 常量)和靜態(tài)方法
    • 使用 java.lang.reflection包的方法對類進行反射調(diào)用
    • 當(dāng)初始化一個類,如果其父類沒有被初始化颂龙,則會先初始化其父類
  • 類的被動引用:不會發(fā)生類的初始化
    • 當(dāng)訪問一個靜態(tài)域時习蓬,只有真正聲明這個域的類才會被初始化纽什。如:當(dāng)通過子類引用父類的靜態(tài)變量,不會導(dǎo)致子類被初始化
    • 通過數(shù)組定義類的引用躲叼,不會觸發(fā)類的初始化
    • 引用常量不會觸發(fā)此類的初始化(常量在鏈接階段就存入調(diào)用類的常量池中了)芦缰。
// 測試類什么時候會被初始化
public class Test04 {
    static {
        System.out.println("Main類被加載");
    }

    public static void main(String[] args) throws ClassNotFoundException {
        // 1. 主動引用
        // Son son = new Son();
//        Main類被加載
//        父類被加載
//        子類被加載

        // 2. 反射也會產(chǎn)生主動引用
        // Class.forName("Son");
//        Main類被加載
//        父類被加載
//        子類被加載

        // 3. 不會產(chǎn)生類的引用方法
        // System.out.println(Son.b);
//        Main類被加載
//        父類被加載
//        3

        Son[] array = new Son[5]; // Main類被加載
    }
}

class Father{
    static int b = 3;
    static {
        System.out.println("父類被加載");
    }
}

class Son extends Father{
    static {
        System.out.println("子類被加載");
        m = 300;
    }

    static int m = 100;
    static final int M = 1;
}

8、類加載器的作用

類加載器的作用:將class文件字節(jié)碼內(nèi)容加載到內(nèi)存中枫慷,并將這些靜態(tài)數(shù)據(jù)轉(zhuǎn)換成方法區(qū)的運行時數(shù)據(jù)結(jié)構(gòu)让蕾,然后再堆中生成這個類的java.lang.Class對象,作為方法區(qū)中類數(shù)據(jù)的訪問入口或听。

類緩存:標(biāo)準(zhǔn)的 JavaSE 類加載器可以按要求查找類探孝,但一旦某個類被加載到類加載器中,他將維持加載(緩存)一段時間誉裆。不過 JVM 垃圾回收機制可以回收這些Class對象再姑。

類的加載

類加載器作用:用來把類(class)裝載進內(nèi)存的。JVM 規(guī)范定義了如下類型的類的加載器找御。

類的加載器
public class Test05 {
    public static void main(String[] args) throws ClassNotFoundException {
        // 獲取系統(tǒng)類加載器
        ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();
        System.out.println(systemClassLoader); // sun.misc.Launcher$AppClassLoader@18b4aac2

        // 獲取系統(tǒng)類加載器的父類---> 擴展類加載器
        ClassLoader systemClassLoaderParent = systemClassLoader.getParent();
        System.out.println(systemClassLoaderParent); // sun.misc.Launcher$ExtClassLoader@1b6d3586

        // 測試當(dāng)前類是哪個類加載器加載的
        ClassLoader classLoader = Class.forName("Test05").getClassLoader();
        System.out.println(classLoader); // sun.misc.Launcher$AppClassLoader@18b4aac2

        // 測試 JDK 內(nèi)置的類是哪個加載器加載的
        ClassLoader loader = Class.forName("java.lang.Object").getClassLoader();
        System.out.println(loader); // null 引導(dǎo)類加載器
    }

}

9元镀、獲取運行時類的完整結(jié)構(gòu)

通過反射獲取運行時累的完整結(jié)構(gòu)

Filed、Method霎桅、Constructor栖疑、Superclass、Interface滔驶、Annotation遇革。

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

// 獲得類的信息
public class Test06 {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, NoSuchMethodException {
        Class c1 = Class.forName("pojo.User");

        // 獲得類的名稱
        System.out.println(c1.getName()); // 包名+類名  pojo.User
        System.out.println(c1.getSimpleName()); // 類名   User

        // 獲得類的屬性
        Field[] fields = c1.getFields(); // 只能找到public屬性

        Field[] declaredFields = c1.getDeclaredFields(); // 找到全部屬性 private int pojo.User.id

        // 獲得指定屬性的值
        Field name = c1.getDeclaredField("name");

        Method[] methods = c1.getMethods(); // 獲得本類及其父類的全部 public 方法
        Method[] declaredMethods = c1.getDeclaredMethods(); // 獲得本類的所有方法

        // 獲得指定方法
        Method getName = c1.getMethod("getName", null);
        Method setName = c1.getMethod("setName", String.class);

        // 獲得指定構(gòu)造器
        Constructor[] constructors = c1.getConstructors();
        Constructor[] declaredConstructors = c1.getDeclaredConstructors();

        Constructor declaredConstructor = c1.getDeclaredConstructor(int.class, String.class);
        System.out.println(declaredConstructor); // public pojo.User(int,java.lang.String)

    }
}

10、動態(tài)創(chuàng)建對象執(zhí)行方法

有了 Class 對象之后揭糕,能做什么萝快?

創(chuàng)建類的對象:調(diào)用 Class 對象的 newInstance() 方法。

  • 類必須有一個無參構(gòu)造器
  • 類的構(gòu)造器的訪問權(quán)限需要足夠著角。

思考揪漩?難道沒有無參構(gòu)造器就不能創(chuàng)建對象了嗎?

答:只要操作的時候明確的調(diào)用類中的構(gòu)造器吏口。并將參數(shù)傳遞進去之后奄容,才可以實例化操作。

import pojo.User;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

// 通過反射動態(tài)的創(chuàng)建對象
public class Test07 {
    public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException, NoSuchFieldException {
        // 獲得 Class 對象
        Class c1 = Class.forName("pojo.User");

        // 構(gòu)造一個對象
        User user = (User) c1.newInstance(); // 本質(zhì)調(diào)用了類的無參構(gòu)造器
        System.out.println(user); // User{id=0, name='null'}

        // 通過構(gòu)造器創(chuàng)建對象
        Constructor constructor = c1.getDeclaredConstructor(int.class, String.class);
        User jack = (User) constructor.newInstance(1, "Jack");
        System.out.println(jack); // User{id=1, name='Jack'}

        // 通過反射調(diào)用普通方法
        User user2 = (User) c1.newInstance();
        // 通過反射調(diào)用一個方法
        Method setName = c1.getDeclaredMethod("setName", String.class);
        setName.invoke(user2, "小米");
        System.out.println(user2); // User{id=0, name='小米'}

        // 通過反射操作屬性
        User user3 = (User) c1.newInstance();
        Field name = c1.getDeclaredField("name");
        // 不能直接操作私有屬性产徊,需要取消安全監(jiān)測
        name.setAccessible(true);
        name.set(user3, "小黑");
        System.out.println(user3); // User{id=0, name='小黑'}
    }
}

Method 和 Field昂勒、Constructor 對象都有 setAccessible() 方法。

setAccessible 作用是啟動和禁用訪問安全檢查的開關(guān)舟铜。

參數(shù)值為 true 則指示反射的對象在使用時應(yīng)該取消 Java 語言訪問檢查戈盈。

11、反射操作泛型(generics)

Java 采用泛型擦除的機制來引入泛型谆刨,Java 中的泛型僅僅是給編譯器 javac 使用的塘娶,確保數(shù)據(jù)的安全性和免去強制類型轉(zhuǎn)換問題归斤,但是一旦編譯完成,所有和泛型有關(guān)的類型全部擦除血柳。

為了通過反射操作這些類型官册, Java 新增了 ParameteriedType, GenericArrayType, TypeVariableWildcardType 幾種類型來代表不能被歸一到 Class 類中的類型但是又和原始類型齊名的類型生兆。

  • ParameteriedType:表示一個參數(shù)化類型难捌,比如Collection<String>
  • GenericArrayType:表示一個元素類型是參數(shù)化類型或者類型變量的數(shù)組類型
  • TypeVariable:是各種類型變量的公共父接口
  • WildcardType :代表一種通配符類型的表達(dá)式。
// 獲取泛型(generics)信息
public class Test08 {
    public void test01 (Map<String, User> map, List<User> list) {
        System.out.println("test01");
    }

    public Map<String, User> test02 () {
        System.out.println("test02");
        return null;
    }

    public static void main(String[] args) throws NoSuchMethodException {
        Method method = Test08.class.getMethod("test01", Map.class, List.class);
        Type[] genericParameterTypes = method.getGenericParameterTypes();
        for (Type genericParameterType : genericParameterTypes) {
            System.out.println(genericParameterType);
            // java.util.Map<java.lang.String, pojo.User>
            // java.util.List<pojo.User>
            if (genericParameterType instanceof ParameterizedType) {
                Type[] actualTypeArguments = ((ParameterizedType) genericParameterType).getActualTypeArguments();
                for (Type actualTypeArgument : actualTypeArguments) {
                    System.out.println("##" + actualTypeArgument);
//                    java.util.Map<java.lang.String, pojo.User>
//                    ##class java.lang.String
//                    ##class pojo.User
//                    java.util.List<pojo.User>
//                    ##class pojo.User
                }
            }
        }

        System.out.println("=======================");
        // 獲取返回值泛型
        Method method1 = Test08.class.getMethod("test02", null);
        Type genericReturnType = method1.getGenericReturnType();
        if (genericReturnType instanceof ParameterizedType) {
            Type[] actualTypeArguments = ((ParameterizedType) genericReturnType).getActualTypeArguments();
            for (Type actualTypeArgument : actualTypeArguments) {
                System.out.println("##" + actualTypeArgument);
//                ##class java.lang.String
//                ##class pojo.User
            }
        }
    }
}

12鸦难、反射操作注解

練習(xí):ORM

使用注解和反射完成類和表結(jié)構(gòu)映射根吁。類和表結(jié)構(gòu)對應(yīng),屬性和字段對應(yīng)合蔽、對象和記錄對應(yīng)击敌。

ORM映射
import java.lang.annotation.*;
import java.lang.reflect.Field;

// 練習(xí)反射操作注解
public class Test09 {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException {
        Class c1 = Class.forName("Student");
        // 通過反射獲得注解

        Annotation[] annotations = c1.getAnnotations();
        for (Annotation annotation : annotations) {
            System.out.println(annotation); // @TableMy(value=db_student)
        }

        // 獲得注解的 value 的值
        TableMy tableMy = (TableMy) c1.getAnnotation(TableMy.class);
        String value = tableMy.value();
        System.out.println(value); // db_student

        // 獲得類指定的注解
        Field f = c1.getDeclaredField("id");
        FiledMy annotation = f.getAnnotation(FiledMy.class);
        System.out.println(annotation.columnName()); // db_id
        System.out.println(annotation.type()); // int
        System.out.println(annotation.length()); // 10
    }

}

// 類名的注解
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@interface TableMy{
    String value();
}

// 屬性的注解
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@interface FiledMy {
    String columnName();
    String type();
    int length();
}

@TableMy("db_student")
class Student {
    @FiledMy(columnName = "db_id", type = "int", length = 10)
    private int id;
    @FiledMy(columnName = "db_age", type = "int", length = 10)
    private String name;
    @FiledMy(columnName = "db_name", type = "varchar", length = 3)
    private int age;

    public Student() {
    }

    public Student(int id, String name, int age) {
        this.id = id;
        this.name = name;
        this.age = age;
    }

    @Override
    public String toString() {
        return "Student{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", age=" + age +
                '}';
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市拴事,隨后出現(xiàn)的幾起案子沃斤,更是在濱河造成了極大的恐慌,老刑警劉巖刃宵,帶你破解...
    沈念sama閱讀 221,635評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件衡瓶,死亡現(xiàn)場離奇詭異,居然都是意外死亡牲证,警方通過查閱死者的電腦和手機哮针,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,543評論 3 399
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來坦袍,“玉大人十厢,你說我怎么就攤上這事∥嫫耄” “怎么了蛮放?”我有些...
    開封第一講書人閱讀 168,083評論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長奠宜。 經(jīng)常有香客問我筛武,道長,這世上最難降的妖魔是什么挎塌? 我笑而不...
    開封第一講書人閱讀 59,640評論 1 296
  • 正文 為了忘掉前任徘六,我火速辦了婚禮,結(jié)果婚禮上榴都,老公的妹妹穿的比我還像新娘待锈。我一直安慰自己,他們只是感情好嘴高,可當(dāng)我...
    茶點故事閱讀 68,640評論 6 397
  • 文/花漫 我一把揭開白布竿音。 她就那樣靜靜地躺著和屎,像睡著了一般。 火紅的嫁衣襯著肌膚如雪春瞬。 梳的紋絲不亂的頭發(fā)上柴信,一...
    開封第一講書人閱讀 52,262評論 1 308
  • 那天,我揣著相機與錄音宽气,去河邊找鬼随常。 笑死,一個胖子當(dāng)著我的面吹牛萄涯,可吹牛的內(nèi)容都是我干的绪氛。 我是一名探鬼主播,決...
    沈念sama閱讀 40,833評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼涝影,長吁一口氣:“原來是場噩夢啊……” “哼枣察!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起燃逻,我...
    開封第一講書人閱讀 39,736評論 0 276
  • 序言:老撾萬榮一對情侶失蹤序目,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后伯襟,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體猿涨,經(jīng)...
    沈念sama閱讀 46,280評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,369評論 3 340
  • 正文 我和宋清朗相戀三年逗旁,在試婚紗的時候發(fā)現(xiàn)自己被綠了嘿辟。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,503評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡片效,死狀恐怖红伦,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情淀衣,我是刑警寧澤昙读,帶...
    沈念sama閱讀 36,185評論 5 350
  • 正文 年R本政府宣布,位于F島的核電站膨桥,受9級特大地震影響蛮浑,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜只嚣,卻給世界環(huán)境...
    茶點故事閱讀 41,870評論 3 333
  • 文/蒙蒙 一沮稚、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧册舞,春花似錦蕴掏、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,340評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽挽荡。三九已至,卻和暖如春即供,著一層夾襖步出監(jiān)牢的瞬間定拟,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,460評論 1 272
  • 我被黑心中介騙來泰國打工逗嫡, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留青自,地道東北人。 一個月前我還...
    沈念sama閱讀 48,909評論 3 376
  • 正文 我出身青樓祸穷,卻偏偏與公主長得像性穿,于是被迫代替她去往敵國和親勺三。 傳聞我的和親對象是個殘疾皇子雷滚,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,512評論 2 359

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