Java & Groovy & Scala & Kotlin - 16.方法鹏往,Lambda 與閉包

Overview

本章主要介紹各語言中的方法定義以及與方法有很大聯(lián)系的 Lambda 表達式,閉包等概念缭保。

基本概念

為了更好的進行闡述,序章部分會簡單介紹一下本章會涉及到的各種名詞蝙茶,在接下來各語言中會再進一步解說艺骂。

方法,函數(shù)與過程

這三種名詞在編程中非常常見隆夯,其概念非常相近钳恕。一般來說函數(shù) (Function) 是可重復調(diào)用帶有有輸出和輸入的代碼塊。方法 (Method) 是定義在類中蹄衷,作為類的成員的函數(shù)忧额。過程(Subroutine)即沒有返回值的函數(shù)。也就是說函數(shù)是基礎形式愧口,方法與過程只是函數(shù)的特例睦番。

由于這些名詞容易混淆,在 Java 中一般都統(tǒng)一使用方法這個名詞。而在 Kotlin 中使用關(guān)鍵字 fun 即表示 Kotlin 中使用的其實是函數(shù)這個名詞托嚣。不過為了方便起見巩检,本系列主要都使用方法這個不一定精確的名字。

Lambda 表達式

Java 8 中引入了 Lambda 表達式示启,實際接觸時發(fā)現(xiàn)有不少同學把這和函數(shù)式算子混到了一起理解兢哭,覺得 Lambda 表達式遍歷效率不行,這是一個非常大的誤解夫嗓。實際上 Lambda 表達式不是什么新東西迟螺,就是一個匿名函數(shù)的語法糖,簡單理解就是繁體字=匿名函數(shù)舍咖,簡體字=Lambda煮仇,Java 8 無非就是在原來只能用繁字體的地方也允許使用簡體字罷了。

函數(shù)式接口

只包含一個抽象方法的接口谎仲,是 Java 8 中用于實現(xiàn) Lambda 表達式的根本機制浙垫,函數(shù)接口就是一種 SAM 類型。

SAM 類型

SAM (Single Abstract Method)是有且僅有一個抽象方法的類型郑诺,該類型可以是抽象類也可以是接口夹姥。

閉包

閉包是一種帶有自由變量的代碼塊,其最顯著的特性就是能夠擴大局部變量的生命周期辙诞。

閉包與方法

閉包和方法的最大區(qū)別是方法執(zhí)行完畢后其內(nèi)部的變量便會被釋放辙售,而閉包不會。閉包可以進行嵌套飞涂,而方法不行旦部。

Java 篇

方法

定義方法

語法為

[訪問控制符] [static] [返回值類型] 方法名(參數(shù)列表)

Java 中方法必須聲明在類的內(nèi)部,且被分為成員方法和靜態(tài)方法较店。

成員方法表示類的對象的一種行為士八,聲明時沒有關(guān)鍵字 static

public int add(int x, int y) {
    return x + y;
}

靜態(tài)方法使用關(guān)鍵字 static 聲明梁呈,屬于類的行為婚度,或稱作類對象的行為,因此調(diào)用時無需創(chuàng)建任何對象官卡。main() 方法就是最常見的靜態(tài)方法蝗茁。

public static void main(String[] args) {
}

Varargs

Varargs 即參數(shù)長度不確定,簡稱變長參數(shù)寻咒。Java 使用符號 ... 表示變參哮翘,但是變參只能出現(xiàn)在參數(shù)列表的最后一個,即 sum(int x, int y, int...n) 是合法的毛秘,但 sum(int x, int...n, int y)sum(int...n, int x, int y) 都是非法的饭寺。

聲明一個變參方法

例:

class Calculator {
    public void sum(int... n) {
        int result = 0;
        for (int i : n) {
            result += i;
        }
        System.out.println(result);
    }
}

調(diào)用該方法

Calculator calculator = new Calculator();
calculator.sum(1, 2, 3);

參數(shù)默認值

Java 不支持參數(shù)默認值,所以調(diào)用時必須為每一個參數(shù)賦值

例:

private static void say(String name, String word) {
    if (word == null) {
        System.out.println(word + " " + name);
    }
}

say("Peter", null);

返回值

Java 中方法除非返回值類型聲明為 void 表示沒有返回值,否則必須在方法中調(diào)用 return 語句返回到調(diào)用處佩研。

例:

public int add(int x, int y) {
    return x + y;
}

Lambda 表達式

序章已經(jīng)說過了,Lambda 只是匿名方法的語法糖

例:

Java 8 以前實現(xiàn)匿名內(nèi)部類的方式

  button.addActionListener(new ActionListener() {
    @Override
    public void actionPerformed(final ActionEvent e) {
        System.out.println("Perform Click");
    }
});

Java 1.8 使用 Lambda 表達式簡化原來的調(diào)用方式

button.addActionListener(e -> System.out.println("Perform Click"));

函數(shù)接口

定義一個函數(shù)接口

@FunctionalInterface
interface Excite {
    String accept(String from);
}

以上使用了注解 @FunctionalInterface霞揉,在 Java 1.8 的初期版本這個注解用于標示一個接口為函數(shù)接口旬薯,但在現(xiàn)在的版本這個注解已經(jīng)僅僅是個標識符了,可以進行省略适秩。

使用 Lambda 表達式

Lambda 表達式的基本語法為

(參數(shù)列表) -> {執(zhí)行語句}

如果執(zhí)行語句只有一句的話可以省略包裹其的花括號

例:

Excite excite = (word) -> word + "!!";

然后我們可以很方便的調(diào)用這個接口

excite.accept("Java")

如果 Lambda 語句只有一個語句且只有一個參數(shù)绊序,且該語句調(diào)用的是一個靜態(tài)方法,則可以使用符號 :: 進一步縮減代碼

Excite hello = (w) -> String.valueOf(w);

以上等同于

Excite hello = String::valueOf;

如果 Lambda 語句只有一個語句秽荞,且該語句為使用類的無參構(gòu)造方法創(chuàng)建類的實例骤公,則也可以使用符號 :: 進一步縮減代碼

Excite hello = (w) -> new Word();

以上等同于

Excite hello = Word::new;

多個參數(shù)

函數(shù)接口也可以接收多個參數(shù),這些參數(shù)可以為泛型而不是具體類型扬跋,實際上使用泛型的函數(shù)接口更為常見

以下定義了一個接收兩個參數(shù) F1F2阶捆,返回 T 類型的接口

interface Convert<F1, F2, T> {
    T convert(F1 from1, F2 from2);
}

使用該接口

Convert<Integer, Integer, String> convert = (x, y) -> {
    int result = x + y;
    return x + " plus " + y + " is " + result;
};
System.out.println(convert.convert(1, 2));  //  1 plus 2 is 3

變參

在 Lambda 表達式中也一樣可以使用變參

例:

定義一個含有變參的接口

interface Contact<F, T> {
    T accept(F... from);
}

使用該接口

Contact<String, String> contact = (args) -> String.join(",", args);
contact.accept("Java", "Groovy", "Scala", "Kotlin");

內(nèi)置函數(shù)接口

通過以上例子我們可以看到要想使用 Lambda 表達式我們必須先定義一個函數(shù)接口,這樣用法太過麻煩钦听。所以 Java 提供了一些內(nèi)置的函數(shù)接口供我們調(diào)用.

Predicate

Predicate 接口用于接收一個參數(shù)并返回 Boolean 值洒试,主要用于處理邏輯動詞。該接口還有一個默認方法 negate() 用于進行邏輯取反朴上。

Predicate<String> predicate = (s) -> s.length() > 0;
assert predicate.test("foo");
assert !predicate.negate().test("foo");
Function

Function 接口接收一個參數(shù)并返回單一結(jié)果垒棋,主要用于進行類型轉(zhuǎn)換等功能。該接口也提供了一個 andThen() 方法用于執(zhí)行鏈式操作痪宰。

Function<String, Integer> toInteger = Integer::valueOf;
Function<String, String> backToString = toInteger.andThen(String::valueOf);
assert toInteger.apply("123") == 123;
assert backToString.apply("123").equals("123");
Supplier

Supplier 接口沒有參數(shù)叼架,但是會返回單一結(jié)果,可以用于實現(xiàn)工廠方法衣撬。

Supplier<Calculator> calculatorSupplier = Calculator::new;
assert calculatorSupplier.get().add(1, 2) == 3;
Consumer

Consumer 接口接收一個參數(shù)乖订,沒有返回值,用于對傳入的參數(shù)進行某些處理具练。該接口也提供了 andThen() 方法垢粮。

Consumer<Person> calculatorConsumer = (p) ->
        System.out.println("The name is " + p.getName());
calculatorConsumer.accept(new Person("Peter"));
Comparator

Comparator 接口接收兩個參數(shù),返回 int 值靠粪,用于進行排序操作蜡吧。該接口提供了 reversed() 方法進行反序排列。

Comparator<Person> comparator = (p1, p2) ->
        p1.getAge().compareTo(p2.getAge());
Person john = new Person("John", 20);
Person alice = new Person("Alice", 18);

assert comparator.compare(john, alice) > 0;
assert comparator.reversed().compare(john, alice) < 0;

函數(shù)接口作為參數(shù)

函數(shù)接口也可以作為參數(shù)來使用

private static int max(int[] arr, Function<int[], Integer> integerFunction) {
    return integerFunction.apply(arr);
}

使用該接口

int maxValue = max(new int[]{3, 10, 2, 40}, (s) -> {
    int max = -1;
    for (int n : s) {
        if (max < n) max = n;
    }
    return max;
});
assert maxValue == 40;

閉包

Java 中的閉包

Java 中和閉包相近的概念就是匿名類以及本章所說的 Lambda 表達式占键。但是這兩種都不是真正意義上的閉包昔善。

先看一個例子:

interface Excite {
    String accept(String from);
}
private static Excite excite(String s) {
  Excite e = from -> {
    from = "from=" + from;
    return from + "," + s;
  };
  return e;
}
Excite excite = excite("hello");
System.out.println(excite.accept("world")); //  from=world,hello

以上例子中 e 為 Lambda 表達式,其定義在 excite() 方法中并且訪問了該方法的參數(shù)列表畔乙。按照生命周期君仆,excite() 的參數(shù) s 應該在方法被調(diào)用后就自動釋放,即 Excite excite = excite("hello") 調(diào)用后就不存在參數(shù) hello 了,但實際打印語句還是打印出來了返咱。

這一表現(xiàn)形式非常像閉包钥庇,因為參數(shù)明顯在其生命周期外還存活。但是如果我們在 Lambda 表達式內(nèi)試圖修改參數(shù) s 的值后編譯器會報 s 必須為 final 咖摹,這就是說該變量實際并不是自由變量评姨,所以并不是真正的閉包。

如果查看 Groovy 的閉包形式你可以發(fā)現(xiàn) Groovy 實際也是通過實現(xiàn)繼承自 Closure 類的匿名內(nèi)部類來實現(xiàn)閉包形式的萤晴,這一點與 Java 一致吐句。所以理論上 Java 也能實現(xiàn)真正的閉包,至于 1.8 為什么沒有這么做就不得而知了店读。

Groovy 篇

方法

定義方法

完整的 Groovy 方法定義語法為

[訪問控制符] [static] def 方法名(參數(shù)列表)

Groovy 也和 Java 一樣有成員方法和靜態(tài)方法之分嗦枢。

成員方法表示類的對象的一種行為,聲明時沒有關(guān)鍵字 static屯断。

def add(x, y) {
    x + y
}

靜態(tài)方法使用關(guān)鍵字 static 聲明文虏,屬于類的行為,或稱作類對象的行為殖演,因此調(diào)用時無需創(chuàng)建任何對象择葡。main() 方法就是最常見的靜態(tài)方法。

static def main(String[] args) {
}

Varargs

Groovy 表示變參的方式與 Java 一樣剃氧,且變參也只能出現(xiàn)在參數(shù)列表的最后一個敏储。

聲明一個變參方法

class Calculator {
    def sum(int ... n) {
        print(n.sum())
    }
}

調(diào)用該方法

def calculator = new Calculator()
calculator.sum(1, 2, 3)

參數(shù)默認值

Groovy 支持參數(shù)默認值,但是一旦使用參數(shù)默認值時朋鞍,參數(shù)列表的最后一個或最后幾個參數(shù)都必須有默認值已添,即 def foo(x, y, z ="bar")def foo(x, y = "bar", z = "bar") 都是合法的,但是 def foo(x, y = "bar", z) 則是非法的滥酥。

例:

static def say(name, word = "Hello") {
    println("$word $name")
}

say("Peter")

返回值

Groovy 中由動態(tài)類型的存在更舞,所以可以不聲明返回值類型。并且在 Groovy 中方法的最后一個語句的執(zhí)行結(jié)果總是回被返回(也適用于無返回值的時候)坎吻,所以也無需 return 語句缆蝉。

例:

def add(x, y) {
    x + y
}

Lambda 表達式

Groovy 目前還不支持 Java 1.8 的特性,所以 Java 中的 Lambda 表達式和對應的函數(shù)式接口無法在 Groovy 中直接使用瘦真。但是 Groovy 本身支持閉包刊头,且閉包就是以 Lambda 表達式的形式存在的,所以閉包和 Lambda 合在一節(jié)講诸尽。

閉包

概念

閉包是一種帶有自由變量的代碼塊原杂,其最顯著的特性就是能夠擴大局部變量的生命周期。與 Java 不同您机,Groovy 支持真正的閉包穿肄。

創(chuàng)建一個閉包

由于閉包是個代碼塊年局,所以一般意義上最簡單的閉包形式如下

{ println("foo") }

不過由于 Java 的普通代碼塊也是這樣的形式,所以為了避免混淆咸产,以上閉包必須寫成如下形式

{ -> println("foo") }

綜上所述矢否,閉包的語法為

{ 參數(shù)列表 -> 執(zhí)行語句 }

例:

{ x, y ->
    println "$x plus $y is ${x + y}"
}

Groovy 中定義閉包實際是定義了一個繼承自 Closure 類的匿名內(nèi)部類,執(zhí)行閉包實際是執(zhí)行該類的實例的方法脑溢。這一點與 Java 非常相似僵朗。

字面量

閉包可以存儲在一個變量中,這一點是實現(xiàn)函數(shù)是一等公民的重要手段焚志。

例:

def excite = { word ->
    "$word!!"
}

調(diào)用閉包

excite("Java")

excite.call("Groovy")

多參數(shù)

閉包的參數(shù)可以和方法的參數(shù)一樣擁有多個參數(shù)及默認值

例:

def plus = { int x, int y = 1 ->
    println "$x plus $y is ${x + y}"
}

it

it 是個隱式參數(shù)衣迷,當閉包只有一個參數(shù)時畏鼓,使用 it 可以直接指代該參數(shù)而不用預先聲明參數(shù)列表酱酬。

例:

def greeting = { "Hello, $it!" }
println(greeting("Peter"))

Varargs

閉包也支持變參

例:

def contact = { String... args -> args.join(',') }
println(contact("Java", "Groovy", "Scala", "Kotlin"))

閉包作為參數(shù)

由于閉包本質(zhì)是 Closure 的子類,所以可以使用 Closure 作為參數(shù)的類型接收一個閉包

static def max(numbers, Closure<Integer> closure) {}

進一步簡化后

static def max(numbers, cls) {
    cls(numbers)
}

傳入閉包

def maxValue = max([3, 10, 2, 1, 40]) {
    def list = it as List<Integer>
    list.max()
}
assert maxValue == 40

自執(zhí)行閉包

自執(zhí)行閉包即定義閉包的同時直接執(zhí)行閉包云矫,一般用于初始化上下文環(huán)境膳沽,Javascript 中常使用這種方法來初始化文檔。

定義一個自執(zhí)行的閉包

{ int x, int y ->
    println "$x plus $y is ${x + y}"
}(1, 3) //  1 plus 3 is 4

Scala 篇

方法

定義方法

完整的 Scala 方法定義語法為

[訪問控制符] def 方法名(參數(shù)列表) [:返回值類型] [=] {}

Scala 可以省略變量定義的類型聲明和返回值類型让禀,但是在定義參數(shù)列表時則必須明確指定類型挑社。

例:

def add(x: Int, y: Int): Int = {
  x + y
}

Scala 只有成員方法,沒有靜態(tài)方法巡揍,但是可以通過單例來實現(xiàn)靜態(tài)方法的功能痛阻,具體內(nèi)容見 Object 章節(jié)。

參數(shù)列表

Scala 中參數(shù)列表必須明確指定參數(shù)類型腮敌。如果一個方法沒有參數(shù)列表時阱当,可以省略小括號,但是調(diào)用時也不能加上小括號糜工。

例:

//  沒有小括號
def info(): Unit = {
  println("This is a class called Calculator.")
}
println(info())

//  有小括號
def info2: Unit = {
  println("This is a class called Calculator.")
}
println(info)

Varargs

Scala 使用 參數(shù)類型* 表示變參弊添。

聲明一個變參方法

class Calculator {
  def sum(n: Int*) {
    println(n.sum)
  }
}

調(diào)用該方法

val calculator = new Calculator
calculator.sum(1, 2, 3)

_*

如果希望將一個 Sequence 作為參數(shù)傳入上一節(jié)的 sum() 方法的話編輯器會報參數(shù)不匹配。此時可以使用 _* 操作符捌木,_* 可以將一個 Sequence 展開為多個參數(shù)進行傳遞油坝。

例:

calculator.sum(1 to 3: _*)

參數(shù)默認值

Scala 同 Groovy 一樣支持參數(shù)默認值,但是一旦使用參數(shù)默認值時刨裆,參數(shù)列表的最后一個或最后幾個參數(shù)都必須有默認值澈圈。

def say(name: String, word: String = "Hello"): Unit = {
  println(s"$word $name")
}

say("Peter")

返回值

Scala 中總是會返回方法內(nèi)部的最后一個語句的執(zhí)行結(jié)果,所以無需 return 語句帆啃。如果沒有返回值的話需要聲明返回值類型為 Unit极舔,并此時可以省略 :Unit=。如果方法沒有遞歸的話返回值類型也可以省略链瓦,但是必須使用 =拆魏。

默認返回最后一行的執(zhí)行結(jié)果

def add(x: Int, y: Int): Int = {
  x + y
}

無返回值的情況

def echo(): Unit = {}

無返回值時可以簡寫為以下形式

def echo() = {}

方法嵌套

Scala 支持方法嵌套盯桦,即一個方法可以定義在另一個方法中,且內(nèi)層方法可以訪問外層方法的成員渤刃。

例:

def testMethod(): Unit = {
  var x = 1
  def add(y: Int): Int = {
    x + y
  }
  println(add(100))
}

Lambda 表達式

同 Groovy 一樣拥峦,閉包和 Lambda 也合在一節(jié)講。

閉包

同 Groovy 一樣卖子,Scala 也支持閉包略号,但是寫法有些不同。

創(chuàng)建一個閉包

由于閉包是個代碼塊洋闽,所以最簡單的閉包形式如下

例:

() => println("foo")

字面量

閉包可以存儲在一個變量中玄柠,這一點是實現(xiàn)函數(shù)是一等公民的重要手段。

例:

val excite = (word: String) =>
  s"$word!!"

調(diào)用閉包

excite("Java")

excite.apply("Scala")

多參數(shù)

閉包的參數(shù)可以和方法的參數(shù)一樣擁有多個參數(shù)诫舅,但是同 Groovy 不一樣羽利,Scala 中閉包的參數(shù)不能有默認值,且參數(shù)列表為多個時必須將參數(shù)包裹在小括號內(nèi)刊懈。

例:

val plus =  (x: Int, y: Int) =>
  println(s"$x plus $y is ${x + y}")

_

_ 是個占位符这弧,當閉包只有一個參數(shù)時,使用 _ 可以直接指代該參數(shù)而不用預先聲明參數(shù)列表虚汛。

例:

val greeting = "Hello,  " + _
println(greeting("Peter"))

Varargs

Scala 中閉包不支持變參

閉包作為參數(shù)

def max(numbers: Array[Int], s: (Array[Int]) => Int): Unit = {
  s.apply(numbers)
}

傳入閉包

val maxValue = max(Array(3, 10, 2, 1, 40), (numbers) => {
  numbers.max
})

也可以使用如下方式進行簡化

def max2(numbers: Array[Int])(s: (Array[Int]) => Int): Unit = {
  s.apply(numbers)
}

maxValue = max2(Array(3, 10, 2, 1, 40)) { numbers =>
  numbers.max
}

自執(zhí)行閉包

自執(zhí)行閉包即定義閉包的同時直接執(zhí)行閉包匾浪,一般用于初始化上下文環(huán)境,Javascript 中常使用這種方法來初始化文檔卷哩。

定義一個自執(zhí)行的閉包

例:

((x: Int, y: Int) => {
  println(s"$x plus $y is ${x + y}")
})(1, 3)    //  1 plus 3 is 4

Kotlin 篇

方法

定義方法

完整的 Kotlin 方法定義語法為

[訪問控制符] fun 方法名(參數(shù)列表) [:返回值類型] {}

Kotlin 可以省略變量定義的類型聲明蛋辈,但是在定義參數(shù)列表和定義返回值類型時則必須明確指定類型。

例:

fun add(x: Int, y: Int): Int {
    return x + y
}

Kotlin 只有成員方法将谊,沒有靜態(tài)方法冷溶,但是可以通過單例來實現(xiàn)靜態(tài)方法的功能,具體內(nèi)容見 Object 章節(jié)瓢娜。

Varargs

Kotlin 使用 vararg 修飾參數(shù)來表示變參挂洛。

聲明一個變參方法

class Calculator {
    fun sum(vararg n: Int) {
        println(n.sum())
    }
}

調(diào)用該方法

val calculator = Calculator()
calculator.sum(1, 2, 3)

參數(shù)默認值

Kotlin 同 Scala 一樣支持參數(shù)默認值,但是一旦使用參數(shù)默認值時眠砾,參數(shù)列表的最后一個或最后幾個參數(shù)都必須有默認值虏劲。

fun say(name: String, word: String = "Hello") {
    println("$word $name")
}

say("Peter")

返回值

Kotlin 同 Java 一樣不會必須使用 return 語句來返回執(zhí)行結(jié)果。

例:

fun add(x: Int, y: Int): Int {
    return x + y
}

方法嵌套

Kotlin 支持方法嵌套褒颈,即一個方法可以定義在另一個方法中柒巫,且內(nèi)層方法可以訪問外層方法的成員。

例:

fun testMethod() {
    var x = 1
    fun add(y: Int): Int {
        return x + y
    }
    println(add(100))
}

Lambda 表達式

同 Scala 一樣谷丸,閉包和 Lambda 也合在一節(jié)講堡掏。

閉包

同 Scala 一樣,Kotlin 也支持閉包刨疼,但是寫法有些不同泉唁。

創(chuàng)建一個閉包

由于閉包是個代碼塊鹅龄,所以最簡單的閉包形式如下

例:

{ -> println("foo") }

字面量

閉包可以存儲在一個變量中,這一點是實現(xiàn)函數(shù)是一等公民的重要手段亭畜。

例:

val excite = { word: String ->
    "$word!!"
}

調(diào)用閉包

excite("Java")

excite.invoke("Kotlin")

多參數(shù)

同 Scala 一樣扮休,Kotlin 中閉包的參數(shù)不能有默認值。

例:

val plus = { x: Int, y: Int ->
    println("$x plus $y is ${x + y}")
}

it

同 Groovy 一樣閉包只有一個參數(shù)時可以使用 it 直接指代該參數(shù)而不用預先聲明參數(shù)列表拴鸵。但是不像 Groovy 那么方便析既,Kotlin 中這一特性僅能用作傳遞作為參數(shù)的閉包中而不能用在定義閉包時正驻。

以下閉包作為參數(shù)傳遞給方法 filter

val ints = arrayOf(1, 2, 3)
ints.filter {
    it > 3
}

以下定義閉包時指定 it 是非法的

val greeting = { -> println(it) }

Varargs

Kotlin 中閉包不支持變參

閉包作為參數(shù)

fun max(numbers: Array<Int>, s: (Array<Int>) -> Int): Int {
    return s.invoke(numbers)
}

傳入閉包

val maxValue = max(arrayOf(3, 10, 2, 1, 40)) {
    it.max()!!
}

自執(zhí)行閉包

自執(zhí)行閉包即定義閉包的同時直接執(zhí)行閉包豫柬,一般用于初始化上下文環(huán)境陨闹,Javascript 中常使用這種方法來初始化文檔。

定義一個自執(zhí)行的閉包

{ x: Int, y: Int ->
    println("$x plus $y is ${x + y}")
}(1, 3)    //  1 plus 3 is 4

Summary

  • ?除 Java 外聘芜,其它語言都支持參數(shù)默認值

文章源碼見 https://github.com/SidneyXu/JGSK 倉庫的 _16_method 小節(jié)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末兄渺,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子厉膀,更是在濱河造成了極大的恐慌溶耘,老刑警劉巖二拐,帶你破解...
    沈念sama閱讀 216,402評論 6 499
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件服鹅,死亡現(xiàn)場離奇詭異,居然都是意外死亡百新,警方通過查閱死者的電腦和手機企软,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,377評論 3 392
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來饭望,“玉大人仗哨,你說我怎么就攤上這事∏Υ牵” “怎么了厌漂?”我有些...
    開封第一講書人閱讀 162,483評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長斟珊。 經(jīng)常有香客問我苇倡,道長,這世上最難降的妖魔是什么囤踩? 我笑而不...
    開封第一講書人閱讀 58,165評論 1 292
  • 正文 為了忘掉前任旨椒,我火速辦了婚禮,結(jié)果婚禮上堵漱,老公的妹妹穿的比我還像新娘综慎。我一直安慰自己,他們只是感情好勤庐,可當我...
    茶點故事閱讀 67,176評論 6 388
  • 文/花漫 我一把揭開白布示惊。 她就那樣靜靜地躺著好港,像睡著了一般。 火紅的嫁衣襯著肌膚如雪米罚。 梳的紋絲不亂的頭發(fā)上媚狰,一...
    開封第一講書人閱讀 51,146評論 1 297
  • 那天,我揣著相機與錄音阔拳,去河邊找鬼崭孤。 笑死,一個胖子當著我的面吹牛糊肠,可吹牛的內(nèi)容都是我干的辨宠。 我是一名探鬼主播,決...
    沈念sama閱讀 40,032評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼货裹,長吁一口氣:“原來是場噩夢啊……” “哼嗤形!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起弧圆,我...
    開封第一講書人閱讀 38,896評論 0 274
  • 序言:老撾萬榮一對情侶失蹤赋兵,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后搔预,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體霹期,經(jīng)...
    沈念sama閱讀 45,311評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,536評論 2 332
  • 正文 我和宋清朗相戀三年拯田,在試婚紗的時候發(fā)現(xiàn)自己被綠了历造。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,696評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡船庇,死狀恐怖吭产,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情鸭轮,我是刑警寧澤臣淤,帶...
    沈念sama閱讀 35,413評論 5 343
  • 正文 年R本政府宣布,位于F島的核電站窃爷,受9級特大地震影響邑蒋,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜吞鸭,卻給世界環(huán)境...
    茶點故事閱讀 41,008評論 3 325
  • 文/蒙蒙 一寺董、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧刻剥,春花似錦遮咖、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽麦箍。三九已至,卻和暖如春陶珠,著一層夾襖步出監(jiān)牢的瞬間挟裂,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,815評論 1 269
  • 我被黑心中介騙來泰國打工揍诽, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留诀蓉,地道東北人。 一個月前我還...
    沈念sama閱讀 47,698評論 2 368
  • 正文 我出身青樓暑脆,卻偏偏與公主長得像渠啤,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子添吗,可洞房花燭夜當晚...
    茶點故事閱讀 44,592評論 2 353

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