Groovy 快速入門

Groovy是一門基于JVM的動態(tài)語言磨澡,很多語法和Java類似懊直。大部分Java代碼也同時是合法的Groovy代碼指巡。本文是快速入門淑履,所以針對語法并不會做非常詳細的介紹。如果需要詳細語法藻雪,請直接查看Groovy官方文檔秘噪。另外為了省事,本文中的大部分代碼例子直接引用了Groovy文檔勉耀。

基本內容

注釋

單行注釋缆娃,以//開頭。

多行注釋瑰排,/* */

GroovyDoc注釋暖侨,和JavaDoc注釋類似椭住。

    /**
     * Creates a greeting method for a certain person.
     *
     * @param otherPerson the person to greet
     * @return a greeting message
     */

Shebang注釋,和Linux其他注釋類似字逗,用于指定腳本解釋器的位置京郑。

#!/usr/bin/env groovy

標識符

大體上,Groovy標識符的命名規(guī)則和Java差不多葫掉。如果某個標識符在Groovy中合法些举,在Java中不合法,我們可以使用單引號或雙引號將標識符包括起來俭厚。

字符串

字符串可以使用單引號'或雙引號"包括起來户魏。

def str="1234"
def str2='1234'

多行字符串可以使用三個連續(xù)的單引號或雙引號包括。不論是單行還是多行字符串, 都可以使用反斜杠轉義字符叼丑。

def multiline="""line1
line2
line3
"""

我們還可以將變量直接插入到字符串中关翎,這叫做內插字符串(String interpolation)。語法和EL表達式類似鸠信。編譯器會把美元和花括號中的內容替換成實際的值纵寝,內插字符串中還可以進行表達式計算。

def name = 'Guillaume' // a plain string
def greeting = "Hello ${name}"

當內插字符串可以由前后的符號區(qū)分出的時候星立,花括號可以省略爽茴。

def person = [name: 'Guillaume', age: 36]
assert "$person.name is $person.age years old" == 'Guillaume is 36 years old'

當使用內插字符串的時候,字符串字面值是Groovy的字符串類型GString绰垂。這一點需要注意室奏。普通的Java字符串是不變的,而GString是可變的辕坝。另外它們的哈希值也不同窍奋。因此在使用Map等數(shù)據(jù)類型的時候需要格外注意,避免使用GString作為Map的鍵酱畅。

字符

Groovy沒有字符字面量琳袄。如果需要向Java方法傳入單個字符的話,可以使用下面的方法進行轉換纺酸。

def c2 = 'B' as char 
assert c2 instanceof Character

def c3 = (char)'C' 
assert c3 instanceof Character

布爾類型

Groovy的布爾類型和Java類似窖逗,也有truefalse兩個值。不過Groovy的布爾語義更豐富餐蔬。未到結尾的迭代器碎紊、非空對象引用、非零數(shù)字都認為是真樊诺;空集合仗考、空字符串等認為是假。詳情參見Groovy文檔 core-semantics#Groovy-Truth

數(shù)字類型

Groovy支持byte词爬、char 秃嗜、shortint 顿膨、longBigInteger等幾種數(shù)字類型锅锨。如果使用普通方式聲明,它們和Java中的變量很相似恋沃。

int   i = 4

BigInteger bi =  6

如果使用def關鍵字聲明必搞,那么這些數(shù)字會自動選擇可以容納它們的類型。

def a = 1
assert a instanceof Integer

// Integer.MAX_VALUE
def b = 2147483647
assert b instanceof Integer

// Integer.MAX_VALUE + 1
def c = 2147483648
assert c instanceof Long

// Long.MAX_VALUE
def d = 9223372036854775807
assert d instanceof Long

// Long.MAX_VALUE + 1
def e = 9223372036854775808
assert e instanceof BigInteger

這些整數(shù)還可以添加0b囊咏、00x前綴恕洲,分別代表8進制數(shù)塔橡,8進制數(shù)和16進制數(shù)。

另外Groovy還支持float研侣、doubleBigDecimal三種浮點數(shù)類型谱邪。原理同上。還可以使用科學計數(shù)法1.123E10這樣的形式代表浮點數(shù)庶诡。

Groovy的數(shù)字常量同樣支持后綴區(qū)分字面值類型惦银,這幾種類型和Java中的類似。唯一不同的是Groovy還支持Gg后綴末誓,代表BigInteger或BigDecimal類型扯俱,根據(jù)字面值是否含有小數(shù)點來區(qū)分。

數(shù)學計算

數(shù)字的計算結果和Java規(guī)則類似:小于int的整數(shù)類型會被提升為int類型喇澡,計算結果也是int類型迅栅;小于long的整數(shù)類型和long計算,結果是long類型晴玖;BigInteger和其它整數(shù)類型計算读存,結果是BigInteger類型;BigDecimal和其它整數(shù)類型計算呕屎,結果是BigDecimal類型让簿;BigDecimal和float、double等類型計算秀睛,結果是double類型尔当。

列表

Groovy中的列表比較靈活,有點像Python中的列表蹂安。使用[....]語法可以聲明列表椭迎,默認情況下列表是ArrayList實現(xiàn)。我們也可以使用as運算符自己選擇合適的列表底層類型田盈。

def arrayList = [1, 2, 3]
assert arrayList instanceof java.util.ArrayList

def linkedList = [2, 3, 4] as LinkedList    
assert linkedList instanceof java.util.LinkedList

有了列表之后畜号,就可以使用它了。使用方法和Python差不多允瞧。我們使用[索引]引用和修改列表元素简软。如果索引是負的,則從后往前計數(shù)瓷式。要在列表末尾添加元素,可以使用左移運算符<<语泽。如果在方括號中指定了多個索引贸典,會返回由這些索引對應元素組成的新列表。使用兩個點加首位索引..可以選擇一個子列表踱卵。

def letters = ['a', 'b', 'c', 'd']

assert letters[0] == 'a'     
assert letters[1] == 'b'

assert letters[-1] == 'd'    
assert letters[-2] == 'c'

letters[2] = 'C'             
assert letters[2] == 'C'

letters << 'e'               
assert letters[ 4] == 'e'
assert letters[-1] == 'e'

assert letters[1, 3] == ['b', 'd']         
assert letters[2..4] == ['C', 'd', 'e']    

列表還可以組合成復合列表廊驼。

def multi = [[0, 1], [2, 3]]     
assert multi[1][0] == 2   

數(shù)組

聲明數(shù)組的方式和列表一樣据过,只不過需要顯示指定數(shù)組類型。數(shù)組的使用方法也和列表類似妒挎,只不過由于數(shù)組是不可變的绳锅,所以不能像數(shù)組末尾添加元素。

int[] intArray = [1, 2, 3, 4, 5]

def intArray2 = [1, 2, 3, 4, 5, 6] as int[]

Map

創(chuàng)建Map同樣使用方括號酝掩,不過這次需要同時指定鍵和值了鳞芙。Map創(chuàng)建好之后,我們可以使用[鍵].鍵來訪問對應的值期虾。默認情況下創(chuàng)建的Map是java.util.LinkedHashMap原朝,我們可以聲明變量類型或者使用as關鍵字改變Map的實際類型。

def colors = [red: '#FF0000', green: '#00FF00', blue: '#0000FF']   

assert colors['red'] == '#FF0000'    
assert colors.green  == '#00FF00' 

關于Map有一點需要注意镶苞。如果將一個變量直接作為Map的鍵的話喳坠,其實Groovy會用該變量的名稱作為鍵,而不是實際的值茂蚓。如果需要講變量的值作為鍵的話壕鹉,需要在變量上添加小括號。

def key = 'name'
def person = [key: 'Guillaume']      //鍵是key而不是name

assert !person.containsKey('name')   
assert person.containsKey('key') 

//這次才正確的將key變量的值作為Map的鍵
person = [(key): 'Guillaume']        

assert person.containsKey('name')    
assert !person.containsKey('key')  

運算符

和Java類似的運算符

Groovy的數(shù)學運算符和Java類似聋涨,只不過多了一個乘方運算**和乘方賦值**=晾浴。

Groovy的關系運算符(大于、小于等于這些)和Java類似牛郑。

Groovy的邏輯運算符(與或非這些)和Java類似怠肋,也支持短路計算。

Groovy的位運算符合Java類似淹朋。

Groovy的三元運算符條件?值1:值2和Java類似笙各。

可空運算符

Groovy支持Elvis操作符,當對象非空的時候結果是值1础芍,為空時結果是值2杈抢。或者更直接仑性,對象非空是使用對象本身惶楼,為空時給另一個值,常用于給定某個可空變量的默認值诊杆。

displayName = user.name ? user.name : 'Anonymous'   
displayName = user.name ?: 'Anonymous'   

安全導航運算符

當調用一個對象上的方法或屬性時歼捐,如果該對象為空,就會拋出空指針異常晨汹。這時候可以使用?.運算符豹储,當對象為空時表達式的值也是空,不會拋出空指針異常淘这。

def person = Person.find { it.id == 123 }    
def name = person?.name                      
assert name == null   

字段訪問運算符

在Groovy中默認情況下使用點運算符.會引用屬性的Getter或Setter剥扣。如果希望直接訪問字段巩剖,需要使用.@運算符。

class User {
    public final String name                 
    User(String name) { this.name = name}
    String getName() { "Name: $name" }       
}
def user = new User('Bob')
assert user.name == 'Name: Bob'   
assert user.@name == 'Bob'   

方法指針運算符

我們可以將方法賦給變量钠怯,這需要使用.&運算符佳魔。然后我們就可以像調用方法那樣使用變量。方法引用的實際類型是Groovy的閉包Closure晦炊。這種運算符可以將方法作為參數(shù)鞠鲜,讓Groovy語言非常靈活。

def str = 'example of method reference'            
def fun = str.&toUpperCase                         
def upper = fun()                                  
assert upper == str.toUpperCase()   

展開運算符

展開運算符*.會調用一個列表上所有元素的相應方法或屬性刽锤,然后將結果再組合成一個列表镊尺。

class Car {
    String make
    String model
}
def cars = [
       new Car(make: 'Peugeot', model: '508'),
       new Car(make: 'Renault', model: 'Clio')]       
def makes = cars*.make                                
assert makes == ['Peugeot', 'Renault'] 

展開運算符是空值安全的,如果遇到了null值并思,不會拋出空指針異常庐氮,而是返回空值。

cars = [
   new Car(make: 'Peugeot', model: '508'),
   null,                                              
   new Car(make: 'Renault', model: 'Clio')]
assert cars*.make == ['Peugeot', null, 'Renault']     
assert null*.make == null  

展開運算符還可以用于展開方法參數(shù)宋彼、列表和Map弄砍。

范圍運算符

使用..創(chuàng)建范圍。默認情況下范圍是閉區(qū)間输涕,如果需要開閉區(qū)間可以在結束范圍上添加<符號音婶。范圍的類型是groovy.lang.Range,它繼承了List接口莱坎,也就是說我們可以將范圍當做List使用衣式。

def range = 0..5                                    
assert (0..5).collect() == [0, 1, 2, 3, 4, 5]       
assert (0..<5).collect() == [0, 1, 2, 3, 4]         
assert (0..5) instanceof List                       
assert (0..5).size() == 6   

比較運算符

<=>運算符相當于調用compareTo方法。

assert (1 <=> 1) == 0

成員運算符

成員運算符in相當于調用contains或isCase方法檐什。

def list = ['Grace','Rob','Emmy']
assert ('Emmy' in list)

相等運算符

==運算符和Java中的不同碴卧。在Groovy中它相當于調用equals方法。如果需要比較引用乃正,使用is住册。

def list1 = ['Groovy 1.8','Groovy 2.0','Groovy 2.3']        
def list2 = ['Groovy 1.8','Groovy 2.0','Groovy 2.3']        
assert list1 == list2    //比較內容相等                                   
assert !list1.is(list2)   //比較引用相等

轉換運算符

我們可以使用Java形式的(String) i來轉換類型。但是假如類型不匹配的話瓮具,就會拋出ClassCastException荧飞。而使用as運算符就會避免這種情況。

Integer x = 123
String s = x as String 

如果希望自己的類也支持as運算符的話名党,需要實現(xiàn)asType方法叹阔。

表達式和語句

聲明變量

Groovy支持以傳統(tǒng)方式使用變量類型 變量名的方式聲明變量,也可以使用def關鍵字聲明變量传睹。使用def關鍵字的時候耳幢,變量類型由編譯器自動推斷,無法推斷時就是Object類型蒋歌。

Groovy可以同時聲明多個變量帅掘。

def (a, b, c) = [10, 20, 'foo']

如果左邊的變量數(shù)比右面的值多,那么剩余的變量就是null堂油。

def (a, b, c) = [1, 2]
assert a == 1 && b == 2 && c == null

如果等號右面比左面多修档,那么多余的值會被忽略。

def (a, b) = [1, 2, 3]
assert a == 1 && b == 2

自定義對象也可以用多重賦值進行對象解構府框。該對象必須有getAt方法吱窝。

class CustomDestruction {
    int a
    int b
    int c
    //解構需要實現(xiàn)getAt方法
    def getAt(int i) {
        switch (i) {
            case 0: a; break
            case 1: b; break
            case 2: c; break
            default: throw new IllegalArgumentException()
        }
    }
    static void main(String[] args) {
        //對象解構
        def obj = new CustomDestruction(a: 3, b: 4, c: 5)
        def (x, y, z) = obj
        println("x=$x,y=$y,z=$z")
    }
}

條件語句

Groovy的if語句和Java的類似。不過在Groovy中布爾值的真假不僅看條件比較的結果迫靖,還可以以其他情況判斷院峡。前面已經(jīng)介紹過了。switch語句同理系宜,真值判斷非常自由照激。詳情可參見Groovy文檔 真值判斷

循環(huán)語句

Groovy支持傳統(tǒng)的Java的for(int i=0;i<N;i++)for(int i :array)兩種形式盹牧。另外還支持for in loop形式俩垃,支持迭代范圍、列表汰寓、Map口柳、數(shù)組等多種形式的集合。

// 迭代范圍
def x = 0
for ( i in 0..9 ) {
    x += i
}
assert x == 45

// 迭代列表
x = 0
for ( i in [0, 1, 2, 3, 4] ) {
    x += i
}

while語句的形式和Java相同有滑。

斷言語句

前面我們看到了很多Groovy斷言的例子跃闹。Groovy斷言語句的功能很強大,以至于文檔中寫的是強力斷言(Power assertion)毛好。

Groovy斷言的形式如下望艺。Groovy斷言和Java斷言完全不同。Groovy斷言是一項語言功能睛榄,一直處于開啟狀態(tài)荣茫,和JVM的斷言功能-ea完全無關。所以它是我們進行單元測試的首選方式场靴。

assert [left expression] == [right expression] : (optional message)

比如我們要斷言1+1=3啡莉。結果應該類似這樣。越復雜的表達式旨剥,斷言效果越清晰咧欣。有興趣的同學可以試試。

Caught: Assertion failed:

assert 1+1 == 3
        |  |
        2  false

面向對象編程

Groovy的面向對象編程和Java類似轨帜,但是提供了一系列功能簡化面向對象開發(fā)魄咕。當然如果你想使用傳統(tǒng)的Java語法來聲明所有成員也可以,Groovy設計目的之一就是讓Java程序員能夠以低成本的方式切換到Groovy上蚌父。

  • 字段默認是私有的哮兰,Groovy會自動實現(xiàn)Getter和Setter方法毛萌。
  • 方法和屬性默認是公有的。
  • 類不必和文件名相同喝滞,
  • 一個文件可以有多個類阁将,如果一個類也沒有,該文件就會被看做是腳本右遭。

構造器

Groovy的構造器非常靈活做盅,我們可以使用傳統(tǒng)的Java方式聲明和使用構造器,也可以完全不聲明構造器窘哈。有時候不聲明反而更簡單吹榴。如果沒有聲明構造器的話,我們可以在構造對象的時候使用命名參數(shù)方式傳遞參數(shù)滚婉,這種方式非常方便图筹,因為我們不需要聲明所有參數(shù),只要聲明所需的參數(shù)即可让腹。

如果希望對構造器進行限制婿斥,可以手動聲明構造器,這樣這種自動構造就不會進行了哨鸭。

class Product {
    String name
    double price

    String toString() {
        return "Product(name:$name,price:$price)"
    }

    static void main(String[] args) {
        def product = new Product(name: 'AMD Ryzen 1700', price: 2499)
        println("隱式構造器:$product")
    }
}

方法

Groovy方法和Java方法基本相同民宿。不過Groovy方法更方便:支持命名參數(shù)和默認參數(shù)。另外Groovy方法可以使用def關鍵字聲明像鸡,這時候方法返回類型是Object活鹰。在Groovy中方法的返回語句可以省略,這時候編譯器會使用方法的最后一個語句的值作為返回值只估。在前面我們還看到了def關鍵字定義變量志群,這時候變量的類型需要從代碼中推斷。

在使用命名參數(shù)的時候需要注意一點蛔钙,方法參數(shù)需要聲明為Map類型(不需要詳細指定鍵和值的類型)锌云,在調用方法的時候使用命名參數(shù)方式傳入?yún)?shù)。

def foo(Map args) { "${args.name}: ${args.age}" }
//調用方法
foo(name: 'Marie', age: 1)

另外方法的括號是可選的吁脱,我們可以省略括號直接像這樣調用方法桑涎。

methodWithDefaultParam '555', 42

字段

Groovy中字段和Java中的概念類似。不過Groovy更加方便:默認情況下字段是私有的兼贡,Groovy自動生成字段的Getter和Setter攻冷。如果需要更精細的控制,把它當成Java字段用就行了遍希。不過如果自定義字段的話等曼,Groovy不會自動生成對應的屬性了。

屬性

如果字段上面沒有聲明訪問修飾符(private、public這些)禁谦,Groovy就會自動生成Gettter和Setter胁黑。如果字段是final的,那么只會生成Getter州泊。這就是Groovy方便的屬性功能别厘。

當然Groovy的方便不止于此,我們的所有類似Java訪問字段的語法拥诡,實際上都會調用字段對應的Getter和Setter。這樣顯著減少了代碼量氮发。如果在類內部的話渴肉,.字段語法會直接訪問字段,這樣做是為了防止無限遞歸調用屬性爽冕。

下面的例子中仇祭,第一次調用p.name = 'Marge'如果在類內部,就直接寫入字段颈畸,如果調用在類外部乌奇,就會使用Setter寫入。第二次調用使用了方法語法眯娱,直接使用Setter寫入礁苗,所以不管在類內還是類外,寫入的值都是"Wonder$name"徙缴。

class Person {
    String name
    void name(String name) {
        this.name = "Wonder$name"       
    }
    String wonder() {
        this.name                       
    }
}
def p = new Person()
p.name = 'Marge'                        
assert p.name == 'Marge'                
p.name('Marge')                         
assert p.wonder() == 'WonderMarge' 

特征類

Groovy和Scala一樣试伙,支持特征類(trait)。特征類就好像自帶實現(xiàn)的接口于样。在Java中只能繼承一個類和多個接口疏叨。在Groovy中,我們可以繼承多個特征類穿剖。特征類和普通的Groovy類一樣蚤蔓,可以包括屬性、字段糊余、方法等秀又,特征類也可以是抽象的。

使用特征類贬芥,我們可以在Groovy中實現(xiàn)類似C++的多重繼承涮坐。另外,特征類支持運行時動態(tài)綁定誓军,在某些情況下非常有用袱讹。

trait Readable {
    void read() {
        println("read...")
    }
}

trait Writable {
    void write(String text) {
        println("write $text")
    }
}

class Notebook implements Readable, Writable {
    static void main(String[] args) {
        //使用特性類
        def notebook = new Notebook()
        notebook.read()
        notebook.write("something")
    }
}

閉包

閉包是Groovy非常重要的一個功能,也是我們介紹的最后一個功能。要了解閉包捷雕,最好先知道Java的Lambda表達式椒丧、匿名內部類等概念。Groovy閉包和Lambda表達式概念相近救巷,但是功能更強大壶熏。

聲明閉包

閉包的形式如下。

{ [closureParameters -> ] statements }

以下都是合法的Groovy閉包浦译。所有閉包都是groovy.lang.Closure類型的實例棒假。閉包的參數(shù)類型是可選的。如果閉包只有單個參數(shù)精盅,參數(shù)名也是可選的帽哑。Groovy會隱式指定it作為參數(shù)名。Kotlin語言也是類似的做法叹俏,有助于我們先出可讀性很好的閉包妻枕。

{ item++ }                                          

{ -> item++ }                                       

{ println it }                                      

{ it -> println it }                                

{ name -> println name }                            

{ String x, int y ->                                
    println "hey ${x} the value is ${y}"
}

{ reader ->                                         
    def line = reader.readLine()
    line.trim()
}

調用閉包

閉包既可以當做方法來調用,也可以顯示調用call方法粘驰。

def code = { 123 }
assert code() == 123
assert code.call() == 123

調用有參數(shù)的閉包也是類似的屡谐。

def isOdd = { int i-> i%2 == 1 }                            
assert isOdd(3) == true                                     
assert isOdd.call(2) == false  

使用閉包

Groovy閉包類似Java的Lambda表達式和匿名內部類,不過使用更方便蝌数,能讓我們減少不少代碼量愕掏。閉包還可以作為方法參數(shù)傳遞到其他地方,這讓閉包更加靈活顶伞。

static void funWithClosure(Closure closure) {
    closure()
}

//在其他地方調用該方法
funWithClosure({ println("Hello yitian") })

//括號還可以省略亭珍,更加簡練
funWithClosure { println("Hello yitian") }

關于閉包,還有幾個精彩的例子枝哄,就是Gradle腳本和Groovy模板引擎肄梨,它們都利用了Groovy強大的閉包功能,構建出簡練而強大的DSL挠锥,讓我們用很少的代碼就可以實現(xiàn)強大的功能(雖然學起來稍微復雜點)众羡。

參考資料

Groovy官方文檔 語法

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市蓖租,隨后出現(xiàn)的幾起案子粱侣,更是在濱河造成了極大的恐慌,老刑警劉巖蓖宦,帶你破解...
    沈念sama閱讀 207,113評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件齐婴,死亡現(xiàn)場離奇詭異,居然都是意外死亡稠茂,警方通過查閱死者的電腦和手機柠偶,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,644評論 2 381
  • 文/潘曉璐 我一進店門情妖,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人诱担,你說我怎么就攤上這事毡证。” “怎么了蔫仙?”我有些...
    開封第一講書人閱讀 153,340評論 0 344
  • 文/不壞的土叔 我叫張陵料睛,是天一觀的道長。 經(jīng)常有香客問我摇邦,道長恤煞,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,449評論 1 279
  • 正文 為了忘掉前任施籍,我火速辦了婚禮居扒,結果婚禮上,老公的妹妹穿的比我還像新娘法梯。我一直安慰自己,他們只是感情好犀概,可當我...
    茶點故事閱讀 64,445評論 5 374
  • 文/花漫 我一把揭開白布立哑。 她就那樣靜靜地躺著,像睡著了一般姻灶。 火紅的嫁衣襯著肌膚如雪铛绰。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,166評論 1 284
  • 那天产喉,我揣著相機與錄音捂掰,去河邊找鬼。 笑死曾沈,一個胖子當著我的面吹牛这嚣,可吹牛的內容都是我干的。 我是一名探鬼主播塞俱,決...
    沈念sama閱讀 38,442評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼姐帚,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了障涯?” 一聲冷哼從身側響起罐旗,我...
    開封第一講書人閱讀 37,105評論 0 261
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎唯蝶,沒想到半個月后九秀,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,601評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡粘我,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 36,066評論 2 325
  • 正文 我和宋清朗相戀三年鼓蜒,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,161評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡友酱,死狀恐怖晴音,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情缔杉,我是刑警寧澤锤躁,帶...
    沈念sama閱讀 33,792評論 4 323
  • 正文 年R本政府宣布队秩,位于F島的核電站盏浙,受9級特大地震影響,放射性物質發(fā)生泄漏政供。R本人自食惡果不足惜霸琴,卻給世界環(huán)境...
    茶點故事閱讀 39,351評論 3 307
  • 文/蒙蒙 一椒振、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧梧乘,春花似錦澎迎、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,352評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至仁堪,卻和暖如春哮洽,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背弦聂。 一陣腳步聲響...
    開封第一講書人閱讀 31,584評論 1 261
  • 我被黑心中介騙來泰國打工鸟辅, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人莺葫。 一個月前我還...
    沈念sama閱讀 45,618評論 2 355
  • 正文 我出身青樓匪凉,卻偏偏與公主長得像,于是被迫代替她去往敵國和親捺檬。 傳聞我的和親對象是個殘疾皇子洒缀,可洞房花燭夜當晚...
    茶點故事閱讀 42,916評論 2 344

推薦閱讀更多精彩內容

  • 前言 人生苦多,快來 Kotlin 欺冀,快速學習Kotlin树绩! 什么是Kotlin? Kotlin 是種靜態(tài)類型編程...
    任半生囂狂閱讀 26,146評論 9 118
  • Groovy簡介 Groovy是基于Java平臺開發(fā)的一門強大的隐轩、具有Optional類型饺饭,多功能性的動態(tài)語言,它...
    Goach閱讀 1,758評論 0 3
  • Spring Cloud為開發(fā)人員提供了快速構建分布式系統(tǒng)中一些常見模式的工具(例如配置管理职车,服務發(fā)現(xiàn)瘫俊,斷路器鹊杖,智...
    卡卡羅2017閱讀 134,601評論 18 139
  • 01 - 胸肌與背肌chest back 熱身之后,只做了8組就汗流不止扛芽,完全提不起上肢骂蓖。 尷尬的停止了。
    張偉_柯里昂閱讀 106評論 0 0
  • 緊鑼密鼓地準備著三天后回家川尖,家里卻有些等不急了登下。早上接到老公電話,得知婆婆眩暈得很厲害叮喳,起不來床了被芳。公公昨天蹲著干...
    綻蕊向陽閱讀 313評論 0 0