android

1.什么是面向对象?

其本质是以建立模型体现出来的抽象思维过程和面向对象的方法,是一种编程思维,也是一种思考问题的方式。面向对象的三大特性:封装,继承,多态。

2.基本数据类型

byte: 属于Java中的整型,长度为1字节8bit,取值10000000(-128)到 01111111(127),变量初始化默认值为0,包装类Byte;
short: 属于Java中的整型,长度为2字节16bit,取值10000000 00000000(-32768)到 01111111 11111111(32767),变量初始化默认值为0,包装类Short;
int: 属于Java中的整型,长度为4字节32bit,取值-2^31 (-2,147,483,648)到 2^31-1(2,147,483,647),变量初始化默认值为0,包装类Integer;
long: 属于Java中的整型,长度为8字节64bit,取值-2^63 (-9,223,372,036,854,775,808)到 2^63-1(9,223,372,036,854,775,8087),变量初始化默认值为0或0L,包装类Long;
float: 属于Java中的浮点型,也叫单精度浮点型,长度为4字节32bit,变量初始化默认值0.0f,包装类Float;小数类型默认的double类型;
double: 属于Java中的浮点型,也叫双精度浮点型,长度为8字节64bit,变量初始化默认值0.0d,包装类Double;float 和 double 都是表示浮点型的数据类型,它们之间的区别在于精确度的不同。
boolean: 属于java中的布尔型,占1bit,1/8字节,仅有两个值true, false,变量初始化默认值false,包装类Boolean;
char:属于java中的字符型,占2字节16bit,可以赋值单字符以及整型数值, 变量初始化无默认值,包装类Character;

String、StringBuilder与StringBuffer

String是内容不可变的,而StringBuffer、StringBuilder都是内容可变的。StringBuffer是同步的,数据安全的,但是效率低; StringBuilder是不同步的,数据不安全,相比于来说,效率高。

3.final finally finalize

final类不能被继承,因此final类的成员方法没有机会被覆盖,默认都是final的。在设计类时候,如果这个类不需要子类,类的实现细节不运行改变,并且确定这个类不会被扩展,那么可以把这个类设计为final类。
finally关键字一般在异常中使用,配合try catch 一起使用,表示不管是否发生异常,finally中的内容一定会被执行。
finalize方法名,Object类的方法,java技术运行使用finalize()方法在垃圾收集器将对象从内存中清除出去之前做必要的清理工作。这个方法是在垃圾收集器在确定这个对象没有引用指向它时调用。finalize()方法是在垃圾收集器删除对象之前对这个对象调用的子类覆盖finalize()方法以整理系统资源或执行其他清理操作。

4.==与equals区别

“==”常用来比较基本数据类型,8种基本数据类型有byte、short、long、double、char、int、float、boolean,因为变量直接存储的就是他们的值,所以用"=="去比较,比较的就是他们的值。
但是复合数据类型用“==”比较的是他的堆内存地址。
“equals”对于复合数据类型比较的也是它的堆内存地址(不能作用于基本数据类型的变量)。

5.内部类、静态内部类、匿名内部类、局部内部类

内部类:内部类是一个编译的概念,一旦编译成功,就会成为完全不同的两个类,分别为outer.class和outer$inner.class类。内部类的成员变量/方法名可以和外部类的相同。可以很好的实现隐藏,可实现多重继承,可以避免修改接口而实现同一个类中两种同名方法的调用。
静态内部类:静态内部类与非静态内部类的区别在于:静态内部类没有x 指向外部的引用。在静态内部类new一个外部类的对象,可以访问外部的非公开的(private 修饰的)成员变量与方法(jdk1.8测试),静态内部类中可以定义静态或者非静态的成员。在外部类中,创建的静态内部类对象可以直接访问对象中的所有成员变量和方法,无论是否是私有的。
匿名内部类:为了免去给内部类命名,或者只想使用一次,就可以选择使用匿名内部类。
于匿名内部类没有自己的名字,所以其在实例化时,必须继承一个父类(可以是一个抽象类)或者实现一个接口,但是也只能是二者选其一,而不能即继承父类,又实现接口。而且其继承和实现都是隐式的,不是显式的使用extends和implement关键字来继承和实现的。由于匿名内部类不能是抽象类,所以它必须要实现它的抽象父类或者接口里面所有的抽象方法。匿名内部类不能定义任何静态成员、方法。局部内部类的所有限制同样对匿名内部类生效。匿名内部类访问的外部类成员变量或成员方法必须用final修饰;jdk1.8可以不需要显式的声明
局部内部类:指内部类定义在方法体内,在局部内部类前不加修饰符public或private。局部内部类不能被public、private、static修饰;局部内部类中不可定义静态变量或方法,当访问外部方法的局部变量(即方法内的变量)时,变量必须是final修饰的的(jdk1.8环境下可以不显式的加final,但是我们不能对变量进行修改操作,因为它是默认final型的)。

6.java反射

反射是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都 能够调用它的任意一个方法和属性;优点:可以动态执行,在运行期间根据业务功能动态执行方法、访问属性,最大限度发挥了java的灵活性。缺点:对性能有影响,这类操作总是慢于直接执行java代码。

8.数据结构

常见的数据结构有:线性链表,数组,栈,队列,树和二叉树
线性链表:采用动态分配内存的形式实现,用一组任意的存储单元存放数据元素链表的,一般为每个元素增设指针域,用来指向后继元素。
数组必须事先定义固定的长度(元素个数),不能适应数据动态地增减的情况。当数据增加时,可能超出原先定义的元素个数;当数据减少时,造成内存浪费;数组可以根据下标直接存取。
栈:先进后出的数据结构。
队列:先进先出 FIFO(first in first out),新元素(等待进入队列的元素)总是被插入到链表的尾部,而读取的时候总是从链表的头部开始读取。
树: 是一种数据结构,它是由n(n>=1)个有限结点组成一个具有层次关系的集合。
二叉树:是每个结点最多有两个子树的树结构。

9.HashMap

Hashmap是有数组+链表+红黑树组成的数据结构。HashMap采用Entry数组来存储key-value对,每一个键值对组成了一个Entry实体,Entry类实际上是一个单向的链表结构,它具有Next指针,可以连接下一个Entry实体。 只是在JDK1.8中,链表长度大于8的时候,链表会转成红黑树。数组是用来确定桶的位置,利用元素的key的hash值对数组长度取模得到. 链表是用来解决hash冲突问题,当出现hash值一样的情形,就在数组上的对应位置形成一条链表。在hashmap插入数据的时候通过计算key的hash值,如果hash值没有碰撞就直接放到数组对应的链表中。如果hash值碰撞了,就以链表形式存放。如果碰撞导致链表过长,就会把链表转换成红黑树。从hashmap获取数据,根据key计算出hash值,如果链表中第一个节点就命中直接返回。如果有冲突,通过key.equals去查找对应的元素。Hashmap默认长度16,在插入数据的时候,通过load factor因子判断是否需要扩容,默认0.75。

10.Hashmap与hashtable的区别:

两者最主要的区别在于Hashtable是线程安全,而HashMap则非线程安全。
Hashtable的实现方法里面都添加了synchronized关键字来确保线程同步,因此相对而言HashMap性能会高一些,我们平时使用时若无特殊需求建议使用HashMap,在多线程环境下若使用HashMap需要使用Collections.synchronizedMap()方法来获取一个线程安全的集合(Collections.synchronizedMap()实现原理是Collections定义了一个SynchronizedMap的内部类,这个类实现了Map接口,在调用方法时使用synchronized来保证线程同步,当然了实际上操作的还是我们传入的HashMap实例,简单的说就是Collections.synchronizedMap()方法帮我们在操作HashMap时自动添加了synchronized来实现线程同步,类似的其它Collections.synchronizedXX方法也是类似原理)。
HashMap可以使用null作为key,而Hashtable则不允许null作为key。
虽说HashMap支持null值作为key,不过建议还是尽量避免这样使用,因为一旦不小心使用了,若因此引发一些问题,排查起来很是费事。
HashMap以null作为key时,总是存储在table数组的第一个节点上。
HashMap是对Map接口的实现,HashTable实现了Map接口和Dictionary抽象类。
HashMap的初始容量为16,Hashtable初始容量为11,两者的填充因子默认都是0.75。
HashMap扩容时是当前容量翻倍即:capacity2,Hashtable扩容时是容量翻倍+1。即:capacity2+1
两者计算hash的方法不同,Hashtable计算hash是直接使用key的hashcode对table数组的长度直接进行取模。

11.gc垃圾回收

什么时候触发GC?
手动触发:当前程序去调用System.gc()的时候触发。注意:GC回收的时候程序会停止运行,同时回收的过程中,会消耗大量的系统性能,所以,一般情况下我们不会主动的去调用gc回收方法。
自动触发:根据Eden区和From Space区的内存大小来决定。当内存大小不足时,则会启动GC线程并停止应用线程
程序再申请内存的时候,系统(jvm)发现内存不足,这个时候就会触发GC。
GC回收的算法?
标记清除
分为两个步骤,第一个步骤就是标记,也就是标记处所有需要回收的对象,标记完成后就统一回收掉带有标记的对象。这种算法优点是简单,缺点是效率问题,还有一个最大的缺点是空间问题,标记清除之后会产生大量不连续的内存碎片,当程序在以后的运行过程中需要分配较大对象时无法找到足够的连续内存而造成内存空间浪费。
标记复制
复制将可用内存按容量划分为大小相等的两块,每次只使用其中的一块。当这一块的内存用完了,就将还存活着的对象复制到另外一块上面,然后再把已使用过的内存空间一次清理掉。这样使得每次都是对其中的一块进行内存回收,内存分配时也就不用考虑内存碎片等复杂情况。只是这种算法的代价是将内存缩小为原来的一半。
标记整理
标记整理算法与标记清除算法很相似,但最显著的区别是:标记清除算法仅对不存活的对象进行处理,剩余存活对象不做任何处理,造成内存碎片;而标记整理算法不仅对不存活对象进行处理清除,还对剩余的存活对象进行整理,重新整理,因此其不会产生内存碎片。
分代收集
新生代->老年代->永久代
新生代:尽可能快速收集回收掉生命周期短的对象,一般情况下新创建的对象都放入到新生代中。
老年代:老年代中对象的生命周期比较长。新生代经过N次回收以后,任然存活的对象。
永久代:主要用于存放静态文件,如:java类,方法。
在新生代中,每次垃圾收集时都发现有大批对象死去,只有少量存活,那就选用复制算法。只需要付出少量存活对象的复制成本就可以完成收集。
新生代中的对象如何向老年代过度?
新生代分三个区域:eden,survivor0,survivor1三个区域,大量的对象都在eden区域,在gc的时候,先将eden区存活的对象复制到survivor0区域,然后清空了eden。当survivor0区域满了以后,则将eden和survivor0区域中存活的对象复制到survivor1区域。然后清空eden和survivor0区域。把survivor1中的数据全部复制到survivor0区域中。经过反复的gc,当survivor1区域不足以放下eden和survivor0区域中的存活对象,就直接将存活的对象放入到老年代。
2、老年代中因为对象存活率高、没有额外空间对他进行分配担保,就必须用标记-清除或者标记-整理。
注意:在jdk8的时候java废弃了永久代,但是并不意味着我们以上的结论失效,因为java提供了与永久代类似的叫做“元空间”的技术。

12.类加载ClassLoader

类的加载包含了加载、验证、准备、解析和初始化这 5 个阶段。

13.双亲委派

类的加载器分为:
启动类加载器(Bootstrap ClassLoader)此类加载器负责将存放在 <JAVA_HOME>\lib 目录中的,或者被 -Xbootclasspath 参数所指定的路径中的,并且是虚拟机识别的(仅按照文件名识别,如 rt.jar,名字不符合的类库即使放在 lib 目录中也不会被加载)类库加载到虚拟机内存中。启动类加载器无法被 Java 程序直接引用,用户在编写自定义类加载器时,如果需要把加载请求委派给启动类加载器,直接使用 null 代替即可。
扩展类加载器(Extension ClassLoader)这个类加载器是由ExtClassLoader(sun.misc.LauncherExtClassLoader)实现的。 它负责将 <JAVA_HOME>/lib/ext 或者被 java.ext.dir 系统变量所指定路径中的所有类库加载到内存中,开发者可以直接使用扩展类加载器。 应用程序类加载器(Application ClassLoader)这个类加载器是由 AppClassLoader(sun.misc.LauncherAppClassLoader)实现的。由于这个类加载器是 ClassLoader 中的 getSystemClassLoader() 方法的返回值,因此一般称为系统类加载器。它负责加载用户类路径(ClassPath)上所指定的类库,开发者可以直接使用这个类加载器,如果应用程序中没有自定义过自己的类加载器,一般情况下这个就是程序中默认的类加载器。

14.线程

线程的创建方式
集成thread,重写run方法
实现runnable接口,重写run方法
实现callable接口,重写call方法,相对runnable,可以声明返回类型
区别:
thread方式,最为简单,可以通过this获取当前线程,但是因为继承了thread类,不能在继承其他类了
runnable方式,子类实现这个接口,可以继承其他的类,多个线程可以共享同一个target对象,没有返回值
callable方式,子类实现这个接口,可以继承其他的类,多个线程可以共享同一个target对象,有返回值

线程状态


xc.png

wait(),yield和sleep()的区别
sleep:属于thread类,指定休眠时间,不会释放锁,到时间后会自动执行
yield:不指定时间,礼让优先级高的线程执行,也不会释放锁,当别的线程执行完毕后,如果没有优先级更高的线程需要执行,继续执行当前线程,否则继续抢占CPU资源。
Wait:属于object类,一般不指定时间,释放锁,需要通过调用notify或notifyall方法唤醒,才能继续执行(如果给wait设置了等待时间,如果到时间还没有唤醒,则会自动唤醒)

15.线程池

线程池的创建:ExecutorService service = new ThreadPoolExecutor(....)。
参数说明:corePoolSize:核心线程数,默认情况下,核心线程一直存活在线程池中,即便他们在线程池中处于闲置状态。除非我们将ThreadPoolExecutor的allowCoreThreadTimeOut属性设为true的时候,这时候处于闲置的核心线程在等待新任务到来时会有超时策略,这个超时时间由keepAliveTime来指定。一旦超过所设置的超时时间,闲置的核心线程就会被终止
maximumPoolSize:线程池中所容纳的最大线程数,如果活动的线程达到这个数值以后,后续的新任务将会被阻塞。包含核心线程数+非核心线程数。
keepAliveTime:非核心线程闲置时的超时时长,对于非核心线程,闲置时间超过这个时间,非核心线程就会被回收。只有对ThreadPoolExecutor的allowCoreThreadTimeOut属性设为true的时候,这个超时时间才会对核心线程产生效果
unit:时间单位
workQueue:线程池中保存等待执行的任务的阻塞队列
threadFactory:为线程池提供新线程的创建
handler:无法处理新任务的时候抛出异常
开启线程池的两个方法:execute,没有返回值,不能监听执行结果;submit,会返回一个future,我们可以通过get方法来回去返回值,用于监听线程是否执行完毕。
关闭线程池的两个方法:sutdown,将线程池的状态设置为SHUTDWON状态,中断的是闲置线程。Sutdownnow:将线程池的状态设置为stop,中断所有任务(包括正在执行任务的线程和闲置线程)
线程池执行原理:
①如果在线程池中的线程数量没有达到核心的线程数量,这时候就回启动一个核心线程来执行任务。
②如果线程池中的线程数量已经超过核心线程数,这时候任务就会被插入到任务队列中排队等待执行。
③由于任务队列已满,会立即启动一个非核心线程来执行任务(当然线程池里边目前的线程数量不能超过最大线程数)。
④如果线程池中的数量达到了所规定的最大值,那么就会拒绝执行此任务,这时候就会调用RejectedExecutionHandler中的rejectedExecution方法来通知调用者。

四种线程池
1)newFixedThreadPool:所有的任务都在核心线程中执行,且核心线程一旦创建,即使任务执行完成,后期一直处于闲置状态,也不会销毁,线程池会一直对这个线程进行维护,直到线程池关闭。如果所有的核心线程都处于活动状态,新加入的任务会被放到linkedblockingqueue这个队列当中,且这个队列没有大小限制。因为核心线程创建后不会被销毁,当新的任务加入时,不需要重新创建线程来执行新的任务,所以相应速度非常快,但是因为核心线程不会销毁,如果长时间处于闲置状态,消耗资源,所以这种线程池一般用于不会有太多任务执行的场景下。
2)newCachedThreadPool:相当于对threadpoolexcutor的一个封装,他的核心线程数量为0,最大线程数量是Integer.MAX_VALUE,线程池对于线程的维护时间是60秒,如果有新的任务,线程池会去内部寻找是否有闲置线程,如果有将任务分发给该线程,如果没有,创建一个非核心线程去执行,当任务执行完成后,线程会等待60秒,如果没有新的任务,将销毁线程。因为最大线程数是一个非常庞大的值,且对于长时间未接受新任务的线程,会回收,所以基本不会达到最大线程的数量,所以内部传入的队列相当于一个空集合,不会使用到。
3)newScheduledThreadPool:是一个可定时执行或周期执行任务的线程池,对于非核心线程,执行完毕后会立马回收(scheduleWithFixedDelay当上一个任务执行完成,然后延时时间到后开始执行第二个任务,因为任务具体的执行时间不能确定,所以除第一个任务外,其他任务的触发时间不可预知;scheduleAtFixedRate当上一个任务开始执行,延时时间到后开始执行第二个任务,因为延时是一个固定时间,所以所有任务的触发时间可推断)
4)newSingleThreadPool:这个线程池当中只有一个核心线程,且最大线程也是1个,同时只能执行一个任务,其他所有任务都放在阻塞队列中,且这个队列没有大小限制(因为没有非核心线程,所以维护时间虽然为0,如果核心线程不设置allowCoreThreadTimeOut为true,维护时间和核心线程没有关系,所以核心线程并不会销毁);

16.进程

系统进行资源分配和调度的一个独立单位、
线程进程的区别

  1. 线程是程序执行的最小单位,而进程是操作系统分配资源的最小单位;
  2. 一个进程由一个或多个线程组成,线程是一个进程中代码的不同执行路线
  3. 进程之间相互独立,但同一进程下的各个线程之间共享程序的内存空间(包括代码段,数据集,堆等)及一些进程级的资源(如打开文件和信
    号等),某进程内的线程在其他进程不可见;
  4. 调度和切换:线程上下文切换比进程上下文切换要快得多

17.网络分层

wlfc.png

18.http与https协议区别

HTTP协议传输的数据都是未加密的,也就是明文的,因此使用HTTP协议传输隐私信息非常不安全,为了保证这些隐私数据能加密传输,于是网景公司设计了SSL(Secure Sockets Layer)协议用于对HTTP协议传输的数据进行加密,从而就诞生了HTTPS。简单来说,HTTPS协议是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议,要比http协议安全。
1、https协议需要到ca申请证书,一般免费证书较少,因而需要一定费用。
2、http是超文本传输协议,信息是明文传输,https则是具有安全性的ssl加密传输协议。
3、http和https使用的是完全不同的连接方式,用的端口也不一样,前者是80,后者是443。这个只是默认端口不一样,实际上端口是可以改的)
4、http的连接很简单,是无状态的;HTTPS协议是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议,比http协议安全。

http请求报文与响应报文格式
请求报文包含三部分:
a、请求行:包含请求方法、URI、HTTP版本信息
b、请求头部(headers)字段
c、请求内容实体(body)
响应报文包含三部分:
a、状态行:包含HTTP版本、状态码、状态码的原因短语
b、响应头部(headers)字段
c、响应内容(body)实体

19.tcp与udp区别

TCP是一种面向连接的、可靠的、基于字节流的传输层通信协议,是专门为了在不可靠的网络中提供一个可靠的端对端字节流而设计的,面向字节流。
UDP(用户数据报协议)是iso参考模型中一种无连接的传输层协议,提供简单不可靠的非连接传输层服务,面向报文
1) TCP是面向连接的,可靠性高;UDP是基于非连接的,可靠性低。
2) 由于TCP是连接的通信,需要有三次握手、重新确认等连接过程,会有延时,实时性差,同时过程复杂,也使其易于攻击;UDP没有建立连接的过程,因而实时性较强,也稍安全。
3) 在传输相同大小的数据时,TCP首部开销20字节;UDP首部开销8字节,TCP报头比UDP复杂,故实际包含的用户数据较少。TCP在IP协议的基础上添加了序号机制、确认机制、超时重传机制等,保证了传输的可靠性,不会出现丢包或乱序,而UDP有丢包,故TCP开销大,UDP开销较小。
4) 每条TCP连接只能时点到点的;UDP支持一对一、一对多、多对一、多对多的交互通信。

Udp协议
udp: 位于传输层的无连接协议,也称透明协议。如:广播
udp:
a)提供无连接的传输,通信前不需要建立连接
b)提供不可靠的传输
c)是面向数据报的传输,没有分组开销
d)不提供拥塞控制和流量控制机制
e)数据可以不完整
场景:
流媒体服务(直播,视频,音频,语音电话,视频电话)

20.三次握手

1603199881(1).png

第一次握手:建立连接时,客户端发送syn包(syn=j)到服务器,并进入SYN_SENT状态,等待服务器确认;SYN:同步序列编号(Synchronize Sequence Numbers)。

第二次握手服务器收到syn包,必须确认客户的SYN(ack=j+1),同时自己也发送一个SYN包(syn=k),即SYN+ACK包,此时服务器进入SYN_RECV状态;

第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=k+1),此包发送完毕,客户端和服务器进入ESTABLISHED(TCP连接成功)状态,完成三次握手。

完成三次握手,客户端与服务器开始传送数据

21.四次挥手

1603199979(2).png

第一步,当主机A的应用程序通知TCP数据已经发送完毕时,TCP向主机B发送一个带有FIN附加标记的报文段(FIN表示英文finish)。
第二步,主机B收到这个FIN报文段之后,并不立即用FIN报文段回复主机A,而是先向主机A发送一个确认序号ACK,同时通知自己相应的应用程序:对方要求关闭连接(先发送ACK的目的是为了防止在这段时间内,对方重传FIN报文段)。
第三步,主机B的应用程序告诉TCP:我要彻底的关闭连接,TCP向主机A送一个FIN报文段。
第四步,主机A收到这个FIN报文段后,向主机B发送一个ACK表示

22.Socket

Socket:又称”套接字”,应用程序通过”套接字”向网络发送请求或应答,它是
一个针对TCP和UDP编程的接口,借助它建立TCP/UDP连接。理论上客户端和服务器端一旦建立起连接将不会主动断掉。依靠心跳包来维护网络链接。

23.WebSocket

Websocket是web服务用前后端的即时通信的一种机制,使用简单方便。可以实现后端主动给前端发消息。
前端断开
在使用websocket过程中,可能会出现网络断开的情况,比如信号不好,或者网络临时关闭,这时候websocket的连接已经断开,而不同浏览器有不同的机制,触发onclose的时机也不同,并不会理想执行websocket的onclose方法,我们无法知道是否断开连接,也就无法进行重连操作。

后端断开
如果后端因为一些情况需要断开ws,在可控情况下,会下发一个断连的消息通知,之后才会断开,我们便会重连。
如果因为一些异常断开了连接,我们是不会感应到的,所以如果我们发送了心跳一定时间之后,后端既没有返回心跳响应消息,前端又没有收到任何其他消息的话,我们就能断定后端主动断开了。

因此需要一种机制来检测客户端和服务端是否处于正常连接的状态。通过在指定时间间隔发送心跳包来保证连接正常,如果连接出现问题,就需要手动触发onclose事件,这时候便可进行重连操作。因此websocket心跳重连就应运而生。

24.常见的其他协议

FTP:文件传输协议
SMTP:邮件传输协议
NFS:网络文件系统

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,294评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,780评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,001评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,593评论 1 289
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,687评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,679评论 1 294
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,667评论 3 415
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,426评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,872评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,180评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,346评论 1 345
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,019评论 5 340
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,658评论 3 323
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,268评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,495评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,275评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,207评论 2 352