Scala学习

1. 特点:

  • Scala是一门多范式编程语言,集成了面向对象编程和函数式编程等多种特性。
  • Scala运行在虚拟机上,并兼容现有的Java程序。
  • Scala源代码被编译成java字节码,所以运行在JVM上,并可以调用现有的Java类库。
  • Scala和Java最大的区别是:Scala语句末尾的分号(;)是可选的!
  • Scala编译运行:
    先编译:scalac HelloScala.scala 将会生成两个文件:HelloScala$.class和HelloScala.class
    再运行:scala HelloScala
    输出结果:hello scala!!!

2. Scala基本语法

  • 区分大小写
  • 类名首字母大写驼峰形式(MyFirstScalaClass)
  • 方法名称首字母小写驼峰形式(myMethodName())
  • 程序文件名应该与对象名称完全匹配
  • def main(args:Array[String]):scala程序从main方法开始处理,程序的入口。
  • Scala注释:分为多行/**/和单行//
  • 换行符:Scala是面向行的语言,语句可以用分号(;)结束或换行符(println())
  • 定义包有两种方法:
  1、package com.ahu
     class HelloScala
  2、package com.ahu{
       class HelloScala
     }
  • 引用:import java.awt.Color
    如果想要引入包中的几个成员,可以用selector(选取器):
    import java.awt.{Color,Font}
    // 重命名成员
    import java.util.{HashMap => JavaHashMap}
    // 隐藏成员 默认情况下,Scala 总会引入 java.lang._ 、 scala._ 和 Predef._,所以在使用时都是省去scala.的
    import java.util.{HashMap => _, _} //引入了util包所有成员,但HashMap被隐藏了

3. 数据类型

Scala与Java有着相同的数据类型,下面列出一些Scala有的数据类型。

  • Unit:表示无值,和其他语言的void一样。
  • Null:null或空引用。
  • Nothing:是Scala的类层级的最低端,是任何其他类型的子类型。
  • Any:是所有其他类的超类。
  • AnyRef:是Scala所有引用类的基类。
  • 多行字符串的表示方法:
val foo ="""第一行
          第二行
          第三行"""

4. 变量

  • 在Scala中,使用关键字“var”声明变量,使用关键字“val”声明常量。
var myVar1 : String = "foo"
var myVar2 : Int
val myVal = "Hello,Scala!"
  • Scala多个变量声明:
 val xmax, ymax = 100  // xmax,ymax都声明为100

5. 访问修饰符

Scala访问修饰符和Java基本一样,分别有private、protected、public。
默认情况下,Scala对象的访问级别是public。

  • 私有成员:用private关键字修饰的成员仅在包含了成员定义的类或对象内部可见。
    class Outer{
      class Inner{
         private def f(){println("f")}
         class InnerMost{
           f() // 正确
         }
        (new Inner).f() // 错误
       }
    }
  • 保护成员:Scala比Java中更严格。只允许保护成员在定义了该成员的类的子类中被访问。
    package p{
       class Super{
         protected def f() {println("f")}
       }
       class Sub extends Super{
           f()
       }
       class Other{
           (new Super).f()  // 错误
       }
    }
  • 公共成员:默认public,这样的成员在任何地方都可以被访问。
  class Outer{
     class Inner{
       def f(){println("f")}
       class InnerMost{
         f() // 正确
       }
     }
     (new Inner).f() // 正确
  }
  • 作用域保护:Scala中,访问修饰符可以通过使用限定词强调。
  • private[x] 或者 protected[x]
  • private[x]:这个成员除了对[...]中的类或[...]中的包中的类及他们的伴生对象可见外,对其他的类都是private。

5. 运算符

Scala运算符:和Java一样,这里就不再浪费时间一一介绍了。
算术运算符、关系运算符、逻辑运算符、位运算符、赋值运算符。

  • Scala if...else语句:和Java一样
  • Scala循环:和Java一样。while循环、do...while循环、for循环

6. Scala方法与函数

  • Scala 有方法与函数,二者在语义上的区别很小。
  • Scala 方法是类的一部分,而函数是一个对象可以赋值给一个变量。换句话来说在类中定义的函数即是方法。
  • Scala 中的方法跟 Java 的类似,方法是组成类的一部分。
  • Scala 中的函数则是一个完整的对象,Scala 中的函数其实就是继承了 Trait 的类的对象。
  • Scala 中使用 val 语句可以定义函数,def 语句定义方法。
    用一个例子来说明函数的定义和函数调用。
class Test{
  def m(x: Int) = x + 3
  val f = (x: Int) => x + 3
}

注意:有些翻译上函数(function)与方法(method)是没有区别的。

  1. 方法的声明
    Scala 方法声明格式如下:

def functionName ([参数列表]) : [return type]

如果你不写等于号和方法主体,那么方法会被隐式声明为抽象(abstract),包含它的类型于是也是一个抽象类型。

  1. 方法的定义
    方法定义由一个 def 关键字开始,紧接着是可选的参数列表,一个冒号 : 和方法的返回类型,一个等于号 = ,最后是方法的主体。
    Scala 方法定义格式如下:

def functionName ([参数列表]) : [return type] = {
function body
return [expr]
}

以上代码中 return type 可以是任意合法的 Scala 数据类型。参数列表中的参数可以使用逗号分隔。
以下方法的功能是将两个传入的参数相加并求和:

object add{
   def addInt( a:Int, b:Int ) : Int = {
      var sum:Int = 0
      sum = a + b
      return sum
   }
}

如果方法没有返回值,可以返回为 Unit,这个类似于 Java 的 void, 实例如下:

object Hello{
   def printMe( ) : Unit = {
      println("Hello, Scala!")
   }
}
  1. 方法调用
    Scala 提供了多种不同的方法调用方式:
    以下是调用方法的标准格式:

functionName( 参数列表 )

如果方法使用了实例的对象来调用,我们可以使用类似java的格式 (使用 . 号):

[instance.]functionName( 参数列表 )

以下实例演示了定义与调用方法的实例:

object Test {
   def main(args: Array[String]) {
        println( "Returned Value : " + addInt(5,7) );
   }
   def addInt( a:Int, b:Int ) : Int = {
      var sum:Int = 0
      sum = a + b
      return sum
   }
}

7. Scala闭包:

闭包是一个函数,返回值依赖于声明在函数外部的一个或多个变量。
例子:

  object Test{
   def main(args: Array[String]){
     println("muliplier(1) value = " + muliplier(1))
     println("muliplier(2) value = " + muliplier(2))
   }
   var factor = 3  // 定义在函数外的自由变量
   val muliplier = (i:Int) => i * factor  // muliplier函数变量就是一个闭包
  }
  输出结果:
  muliplier(1) value = 3
  muliplier(2) value = 6

在 multiplier 中有两个变量:i 和 factor。其中的一个 i 是函数的形式参数,在 multiplier 函数被调用时,i 被赋予一个新的值。然而,factor不是形式参数,而是自由变量,
这里我们引入一个自由变量 factor,这个变量定义在函数外面。
这样定义的函数变量 multiplier 成为一个"闭包",因为它引用到函数外面定义的变量,定义这个函数的过程是将这个自由变量捕获而构成一个封闭的函数。

8. Scala字符串

Scala中可以创建两中字符串:一种是不可修改的,一种是可以修改的。

  • 创建不可修改的字符串
 val greeting:String = "Hello World!";
  • 创建可以修改的字符串
object Test{
   def main(args: Array[String]){
     val buf = new StringBuilder;
     buf += 'a'  // 添加一个字符
     buf ++= "bcdef" // 添加一个字符串
     println(buf.toString);  // 输出:abcdef
   }
 }
  • 字符串长度:xxx.length()
  • 字符串连接:可以用concat()方法或者用加号
object Test {
       def main(args: Array[String]) {
         var str1 = "字符串1:";
         var str2 =  "字符串2";
         var str3 =  "字符串3:";
         var str4 =  "字符串4";
         println( str1 + str2 ); //  字符串1:字符串2
         println( str3.concat(str4) ); // 字符串3:字符串4
       }
 }
  • 创建格式化字符串:
    String类中可以使用printf()方法来格式化字符串并输出。
object Test{
   def main(args:Array[String]){
     var floatVar = 12.456
     var intVar = 2000
     var stringVar = "字符串变量"
     var fs = printf("浮点型变量为 " +
                     "%f,整形变量为 %d, 字符串为 " +
                     "%s", floatVar, intVar, stringVar)
     println(fs) // 浮点型变量为 12.456000, 整型变量为 2000, 字符串为 字符串变量
   }
}

9. Scala数组

  1. 声明数组
//第一种
var z:Array[String] = new Array[String](3);
//第二种
var z = new Array[String](3);
//赋值
z(0)= "value1";
z(1) = "value2";
z(2) = "value3";
//第三种
var z = Array("value1","value2","value3");
  1. 处理数组
object Test {
  def main(args: Array[String]): Unit = {
    var myList = Array(1.1,2.2,3.3,4.4);
    //输出所有元素
    for(x <- myList){
      println(x);
    }
    //计算数组所有元素的总和
    var total = 0.0;
    for(i <- 0 to (myList.length-1)){
      total += myList(i);
    }
    println("total: "+total)
    //查找数组中的最大值
    var max = myList(0);
    for(i <- 0 to (myList.length-1)){
      if(myList(i) > max){
        max = myList(i);
      }
    }
    println("max: " + max)
  }
}
  1. 多维数组
import Array._
object Test {
  def main(args: Array[String]): Unit = {
    //定义数组
    val myMatrix = ofDim[Int](3,3);
    //创建矩阵
    for(i <- 0 to 2){
      for(j <- 0 to 2){
        myMatrix(i)(j) = j;
      }
    }
    //打印矩阵
    for(i <- 0 to 2){
      for(j <- 0 to 2){
        print(" " + myMatrix(i)(j));
      }
      println();
    }

  }
}

结果:
  1. 合并数组
import Array._
object Test {
  def main(args: Array[String]): Unit = {
    var myList1 = Array(1.1, 2.2, 3.3, 4.4)
    var myList2 = Array(5.5, 6.6, 7.7, 8.8)
    // 使用concat()合并
    var myList3 = concat(myList1, myList2)
    // 输出所有数组元素
    for (x <- myList3) {
      println(x)
    }
  }
}

结果:
  1. 创建区间数组:使用range(x,y,z)创建区间数组,数值范围大于等于x,小于y。z表示步长,默认为1。
import Array._
object Test {
  def main(args: Array[String]): Unit = {
    var myList1 = range(10,20,2);
    var myList2 = range(10,20);
    for (x <- myList1) {
      print(" " + x)
    }
    println(); //输出:10 12 14 16 18

    for(x <- myList2){
      print(" " + x); //输出:10 11 12 13 14 15 16 17 18 19
    }
  }
}

10. Scala集合

Scala集合分为可变集合和不可变集合
可变集合:可以在适当的时候扩展或更新,也就是可以修改、添加、移除集合元素。
不可变集合:永远不可改变。但可以模拟添加、移除、更新操作,但是这些操作将在每一种情况下都返回一个新的集合, 同时使原来的集合不发生改变。

  • Scala List:List的特征是其元素以线性方式存储,集合中可以存放重复对象。
  • Scala Set:Set是最简单的一种集合。集合中的对象不按特定的方式排序,并且没有重复对象。
  • Scala Map:Map 是一种把键对象和值对象映射的集合,它的每一个元素都包含一对键对象和值对象。
  • Scala 元组:元组是不同类型的值的集合
  • Scala Option:Option[T] 表示有可能包含值的容器,也可能不包含值。
  • Scala Iterator:迭代器不是一个容器,更确切的说是逐一访问容器内元素的方法。
object Test {
  def main(args: Array[String]): Unit = {
    //定义整型List
    val list = List(1, 2, 3, 4);
    //定义Set
    val set = Set(1, 3, 5, 7);
    //定义Map
    val map = Map("one" -> 1, "two" -> 2, "three" -> 3);
    //创建两个不同类型的元组
    val x = (10, "tom");
    //定义Option
    val option: Option[Int] = Some(5);

    //迭代器示例
    val it = Iterator("one", "two", "three", "four")
    while (it.hasNext) { // 检测集合中是否还有元素
      println(it.next()) // 返回迭代器的下一个元素,并更新迭代器的状态
    }
    val ita = Iterator(1, 2, 3, 4, 5)
    val itb = Iterator(11, 22, 33, 44, 55)
    //println(ita.max)  // 查找最大元素
    // println(itb.min)  // 查找最小元素
    println(ita.size) // 获取迭代器的长度
    println(itb.length) // 获取迭代器的长度
  }
}

11. Scala类和对象

类是对象的抽象,而对象是类的具体实例。
类是抽象的,不占用内存,而对象是具体的,占用存储空间。
类是用于创建对象的蓝图,它是一个定义包括在特定类型的对象中的方法和变量的软件模板。

class Point(xc:Int, yc:Int) {
  var x:Int = xc;
  var y:Int = yc;
  def move(dx:Int,dy:Int): Unit ={
    x = x + dx;
    y = y + dy;
    println("x的坐标是:" + x);
    println("y的坐标是:" + y);
  }
}

object Test {
  def main(args: Array[String]): Unit = {
    val pt = new Point(10,20);
    pt.move(10,20);
  }
}

12. Scala继承

Scala继承一个基类跟Java很相似, 但我们需要注意以下几点:
1、重写一个非抽象方法必须使用override修饰符。
2、只有主构造函数才可以往基类的构造函数里写参数。
3、在子类中重写超类的抽象方法时,你不需要使用override关键字。

class Point(xc:Int, yc:Int) {
  var x:Int = xc;
  var y:Int = yc;
  def move(dx:Int,dy:Int): Unit ={
    x = x + dx;
    y = y + dy;
    println("x的坐标是:" + x);
    println("y的坐标是:" + y);
  }

  var name = "";
  override def toString: String = getClass.getName + "[name=" + name + "]";
}

class Location(val xc: Int, val yc: Int, val zc: Int)
  extends Point(xc, yc) {
  
  var z: Int = zc;
  def move(dx: Int, dy: Int, dz: Int) = {
    x = x + dx;
    y = y + dy;
    z = z + dz;
  }
  var salary = 0.0;
  override def toString: String = super.toString + "[salary="+ salary+ "]";
}

object Test {
  def main(args: Array[String]): Unit = {
    val lo = new Location(10,20,30);
    lo.move(10,10,5);
    lo.name = "location";
    lo.salary = 35000.0;
    println(lo);
  }
}

13. Scala单例对象

  • 在 Scala 中,是没有 static 这个东西的,但是它也为我们提供了单例模式的实现方法,那就是使用关键字 object。
  • Scala 中使用单例模式时,除了定义的类之外,还要定义一个同名的 object 对象,它和类的区别是,object对象不能带参数。
  • 当单例对象与某个类共享同一个名称时,他被称作是这个类的伴生对象:companion object。你必须在同一个源文件里定义类和它的伴生对象。类被称为是这个单例对象的伴生类:companion class。
  • 类和它的伴生对象可以互相访问其私有成员
//私有构造方法
class Marker private(val color:String){
  println("创建:" + this);
  override def toString(): String = "颜色标记:"+ color  //4:颜色标记:red

}

//伴生对象,能访问类的私有属性和方法
object Marker {
  private val markers : Map[String, Marker] = Map(
    "red" -> new Marker("red"), //1.创建颜色标记:red
    "blue" -> new Marker("blue"), //2.创建颜色标记;blue
    "green" -> new Marker("green")  //3.创建颜色标记:green
  )

  def apply(color:String)  = {
    if(markers.contains(color)) markers(color) else null;
  }

  def getMarker(color:String) = {
    if(markers.contains(color)) markers(color) else null; //5:颜色标记:blue
  }

  def main(args: Array[String]): Unit = {
    println(Marker("red"));
    //单例函数调用,省略了.(点)符号
    println(Marker getMarker "blue");
  }
}

运行结果:

14. Scala Trait(特征)

Scala Trait(特征) 相当于 Java 的接口,实际上它比接口还功能强大。
与接口不同的是,它还可以定义属性和方法的实现。
一般情况下Scala的类只能够继承单一父类,但是如果是 Trait(特征) 的话就可以继承多个,从结果来看就是实现了多重继承。

  1. Trait(特征) 定义的方式与类类似,但它使用的关键字是 trait,如下所示:
trait Equal {
  def isEqual(x:Any) : Boolean;
  def isNotEqual(x:Any) : Boolean = !isEqual(x);
}

以上Trait(特征)由两个方法组成:isEqual 和 isNotEqual。isEqual 方法没有定义方法的实现,isNotEqual定义了方法的实现。子类继承特征可以实现未被实现的方法。所以其实 Scala Trait(特征)更像 Java 的抽象类。
以下演示了特征的完整实例:

trait Equal {
  def isEqual(x:Any) : Boolean;
  def isNotEqual(x:Any) : Boolean = !isEqual(x);
}

class Point(xc:Int,yc:Int) extends Equal{
  var x:Int = xc;
  var y:Int = yc;
  override def isEqual(obj: Any) = obj.isInstanceOf[Point] && obj.asInstanceOf[Point].x == x
}

object Test{
  def main(args: Array[String]): Unit = {
    val p1 = new Point(2,3);
    val p2 = new Point(2,4);
    val p3 = new Point(3,3);

    println(p1.isNotEqual(p2))  //false
    println(p1.isNotEqual(p3))  //true
    println(p1.isNotEqual(2))  //true
  }
}
  1. 特征构造顺序
    特征也可以有构造器,由字段的初始化和其他特征体中的语句构成。这些语句在任何混入该特征的对象在构造时都会被执行。
    构造器的执行顺序:
  • 调用超类的构造器;
  • 特征构造器在超类构造器之后、类构造器之前执行;
  • 特征由左到右被构造;
  • 每个特征当中,父特征先被构造;
  • 如果多个特征共有一个父特征,父特征不会被重复构造
    *所有特征被构造完毕,子类被构造。

15. Scala模式匹配

Scala 提供了强大的模式匹配机制,应用也非常广泛。
一个模式匹配包含了一系列备选项,每个都开始于关键字 case。每个备选项都包含了一个模式及一到多个表达式。箭头符号 => 隔开了模式和表达式。
示例:

object Test{
  def main(args: Array[String]): Unit = {
    println(matchText(3)); //many
  }

  def matchText(x : Int) : String = x match {
    case 1 => "one";
    case 2 => "two";
    case _ => "many";
  }
}

match 对应 Java 里的 switch,但是写在选择器表达式之后。即: 选择器 match {备选项}。
match 表达式通过以代码编写的先后次序尝试每个模式来完成计算,只要发现有一个匹配的case,剩下的case不会继续匹配。
接下来我们来看一个不同数据类型的模式匹配:

object Test {
   def main(args: Array[String]) {
      println(matchTest("two"))
      println(matchTest("test"))
      println(matchTest(1))
      println(matchTest(6))

   }
   def matchTest(x: Any): Any = x match {
      case 1 => "one"
      case "two" => 2
      case y: Int => "scala.Int"
      case _ => "many"
   }
}

使用样例类
使用了case关键字的类定义就是就是样例类(case classes),样例类是种特殊的类,经过优化以用于模式匹配。

object Test {
   def main(args: Array[String]) {
       val alice = new Person("Alice", 25)
    val bob = new Person("Bob", 32)
       val charlie = new Person("Charlie", 32)
   
    for (person <- List(alice, bob, charlie)) {
        person match {
            case Person("Alice", 25) => println("Hi Alice!")
            case Person("Bob", 32) => println("Hi Bob!")
            case Person(name, age) =>
               println("Age: " + age + " year, name: " + name + "?")
         }
      }
   }
   // 样例类
   case class Person(name: String, age: Int)
}

在声明样例类时,下面的过程自动发生了:

  • 构造器的每个参数都成为val,除非显式被声明为var,但是并不推荐这么做;
  • 在伴生对象中提供了apply方法,所以可以不使用new关键字就可构建对象;
  • 提供unapply方法使模式匹配可以工作;
  • 生成toString、equals、hashCode和copy方法,除非显示给出这些方法的定义。

16. Scala正则表达式

Scala 的正则表达式继承了 Java 的语法规则
示例:

import scala.util.matching.Regex

object Test {
   def main(args: Array[String]) {
      val pattern = new Regex("(S|s)cala")  // 首字母可以是大写 S 或小写 s
      val str = "Scala is scalable and cool"
      
      println((pattern findAllIn str).mkString(","))   // 使用逗号 , 连接返回结果
   }
}

17. Scala异常处理

Scala 的异常处理和其它语言比如 Java 类似。
Scala 的方法可以通过抛出异常的方法的方式来终止相关代码的运行,不必通过返回值。

  1. 抛出异常
    Scala 抛出异常的方法和 Java一样,使用 throw 方法,例如,抛出一个新的参数异常:
    throw new IllegalArgumentException
  2. 捕获异常
    异常捕捉的机制与其他语言中一样,如果有异常发生,catch字句是按次序捕捉的。因此,在catch字句中,越具体的异常越要靠前,越普遍的异常越靠后。 如果抛出的异常不在catch字句中,该异常则无法处理,会被升级到调用者处。
    捕捉异常的catch子句,语法与其他语言中不太一样。在Scala里,借用了模式匹配的思想来做异常的匹配,因此,在catch的代码里,是一系列case字句,如下例所示:
import java.io.{FileNotFoundException, FileReader, IOException}

object Test{
  def main(args: Array[String]): Unit = {
    try{
      val f = new FileReader("input.txt");
    }catch{
      case ex : FileNotFoundException =>{
        println("Missing file exception")
      }
      case ex : IOException =>{
        println("IO exception")
      }
    }
  }
}

18. Scala 提取器(Extractor)

apply方法:无需new操作就可创建对象。
unapply方法:是apply方法的反向操作,接受一个对象,然后从对象中提取值,提取的值通常是用来构造对象的值。
以下实例演示了邮件地址的提取器对象:

object Test{
  def main(args: Array[String]): Unit = {
    println("Apply方法:" + apply("Zara","gmail.com"));//Apply 方法 : Zara@gmail.com
    println("unapply方法:" + unapply("Zara@gmail.com"));//Unapply 方法 : Some((Zara,gmail.com))
    println("unapply方法:" + unapply("Zara Ali"));//Unapply 方法 : None
  }
  //注入方法(可选)
  def apply(user:String, domain:String) ={
    user + "@" + domain
  }
  //提取方法(必选)
  def unapply(str: String): Option[(String,String)] = {
    val parts = str split("@")
    if(parts.length == 2){
      Some(parts(0),parts(1))
    }else{
      None
    }
  }
}

以上对象定义了两个方法: apply 和 unapply 方法。通过 apply 方法我们无需使用 new 操作就可以创建对象。所以你可以通过语句 Test("Zara", "gmail.com") 来构造一个字符串 "Zara@gmail.com"。
unapply方法算是apply方法的反向操作:unapply接受一个对象,然后从对象中提取值,提取的值通常是用来构造该对象的值。实例中我们使用 Unapply 方法从对象中提取用户名和邮件地址的后缀。

  1. 提取器使用模式匹配
    在我们实例化一个类的时,可以带上0个或者多个的参数,编译器在实例化的时会调用 apply 方法。我们可以在类和对象中都定义 apply 方法。
    就像我们之前提到过的,unapply 用于提取我们指定查找的值,它与 apply 的操作相反。 当我们在提取器对象中使用 match 语句是,unapply 将自动执行,如下所示:
object Test{
  def main(args: Array[String]): Unit = {
    val x = Test(5);//执行apply
    println(x)
    x match{
        //执行unapply
      case Test(num) => println(x + "是:" + num +"的两倍")
      case _ => println("无法计算")
    }
  }
  //注入方法(可选)
  def apply(x:Int) = x*2;
  //提取方法(必选)
  def unapply(z: Int): Option[Int] = if(z%2 == 0) Some(z/2) else None
}

19. Scala文件I/O

  1. 文件写操作
    Scala 进行文件写操作,直接用的都是 java中 的 I/O 类 (java.io.File)
import java.io._

object Test{
  def main(args: Array[String]): Unit = {
    val writer = new PrintWriter(new File("test.txt"))
    writer.write("Scala教程");
    writer.close();
  }
}
  1. 从屏幕上读取用户操作
import scala.io.StdIn

object Test{
  def main(args: Array[String]): Unit = {
    print("请输入百度地址:")
    val line = StdIn.readLine();
    println("你输入的是: " + line)
  }
}
  1. 从文件上读取内容
    从文件读取内容非常简单。我们可以使用 Scala 的 Source 类及伴生对象来读取文件。以下实例演示了从 "test.txt"(之前已创建过) 文件中读取内容:
import scala.io.Source

object Test{
  def main(args: Array[String]): Unit = {
    println("文件内容是:")
    Source.fromFile("test.txt").foreach{
      print;
    }
  }
}

参考:https://www.cnblogs.com/ahu-lichang/p/7207847.html?utm_source=itdadao&utm_medium=referral

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

推荐阅读更多精彩内容