JDK1.8新特性總結(jié) Day37 2018-12-27

JDK1.8新特性總結(jié)

一、十大特性

  • 1.default關(guān)鍵字
  • 2.Lambda表達(dá)式
  • 3.接口新增:默認(rèn)方法與靜態(tài)方法
  • 4.方法引用,與Lambda表達(dá)式聯(lián)合使用
  • 5.引入重復(fù)注解
  • 6.類型注解
  • 7.Stream函數(shù)式操作流元素集合
  • 8.最新的Date/Time API (JSR 310)
  • 9.新增base64加解密API
  • 10.數(shù)組并行(parallel)操作

  • 1.JVMPermGen空間被移除:取代它的是Metaspace(JEP 122)元空間

二、新特性

1、default關(guān)鍵字

在java里面猴抹,我們通常都是認(rèn)為接口里面是只能有抽象方法整陌,不能有任何方法的實(shí)現(xiàn)的划纽,那么在jdk1.8里面打破了這個(gè)規(guī)定脆侮,引入了新的關(guān)鍵字default,通過(guò)使用default修飾方法勇劣,可以讓我們?cè)诮涌诶锩娑x具體的方法實(shí)現(xiàn)靖避,如下。

public interface NewCharacter {
    public void test1();
    public default void test2(){
        System.out.println("我是新特性1");
    }

}

那這么定義一個(gè)方法的作用是什么呢比默?為什么不在接口的實(shí)現(xiàn)類里面再去實(shí)現(xiàn)方法呢幻捏?

其實(shí)這么定義一個(gè)方法的主要意義是定義一個(gè)默認(rèn)方法,也就是說(shuō)這個(gè)接口的實(shí)現(xiàn)類實(shí)現(xiàn)了這個(gè)接口之后命咐,不用管這個(gè)default修飾的方法篡九,也可以直接調(diào)用,如下醋奠。

public class NewCharacterImpl implements NewCharacter{

    @Override
    public void test1() {
        
    }
    public static void main(String[] args) {
        NewCharacter nca = new NewCharacterImpl();
        nca.test2();
    }

}

所以說(shuō)這個(gè)default方法是所有的實(shí)現(xiàn)類都不需要去實(shí)現(xiàn)的就可以直接調(diào)用榛臼,那么比如說(shuō)jdk的集合List里面增加了一個(gè)sort方法,那么如果定義為一個(gè)抽象方法钝域,其所有的實(shí)現(xiàn)類如arrayList,LinkedList等都需要對(duì)其添加實(shí)現(xiàn)讽坏,那么現(xiàn)在用default定義一個(gè)默認(rèn)的方法之后,其實(shí)現(xiàn)類可以直接使用這個(gè)方法了例证,這樣不管是開發(fā)還是維護(hù)項(xiàng)目,都會(huì)大大簡(jiǎn)化代碼量迷捧。

2织咧、Lambda 表達(dá)式

2.1、 Lambda表達(dá)式的寫法

Lambda表達(dá)式是jdk1.8里面的一個(gè)重要的更新漠秋,這意味著java也開始承認(rèn)了函數(shù)式編程笙蒙,并且嘗試引入其中。

  • Lambda 表達(dá)式junit測(cè)試代碼
 public List<Integer> list = Lists.newArrayList(1,2,3,4,5,6,7,8,9,10);
    
    /**
     * 1.Lambda表達(dá)式
     */
    @Test
    public void testLambda(){
        list.forEach(System.out::println);
        list.forEach(e -> System.out.println("方式二:"+e));
    }

首先庆锦,什么是函數(shù)式編程捅位,引用廖雪峰先生的教程里面的解釋就是說(shuō):

函數(shù)式編程就是一種抽象程度很高的編程范式,純粹的函數(shù)式編程語(yǔ)言編寫的函數(shù)沒有變量搂抒,因此艇搀,任意一個(gè)函數(shù),只要輸入是確定的求晶,輸出就是確定的焰雕,這種純函數(shù)我們稱之為沒有副作用。而允許使用變量的程序設(shè)計(jì)語(yǔ)言芳杏,由于函數(shù)內(nèi)部的變量狀態(tài)不確定矩屁,同樣的輸入辟宗,可能得到不同的輸出,因此吝秕,這種函數(shù)是有副作用的泊脐。函數(shù)式編程的一個(gè)特點(diǎn)就是,允許把函數(shù)本身作為參數(shù)傳入另一個(gè)函數(shù)烁峭,還允許返回一個(gè)函數(shù)容客!

簡(jiǎn)單的來(lái)說(shuō)就是,函數(shù)式編程語(yǔ)言里面函數(shù)也可以跟變量则剃,對(duì)象一樣使用了耘柱,也就是說(shuō)函數(shù)既可以作為參數(shù),也可以作為返回值了棍现,看一下下面這個(gè)例子调煎。

//這是常規(guī)的Collections的排序的寫法,需要對(duì)接口方法重寫
        public void test1(){
        List<String> list =Arrays.asList("aaa","fsa","ser","eere");
        Collections.sort(list, new Comparator<String>() {
            @Override
            public int compare(String o1, String o2) {
                return o2.compareTo(o1);
            }
        });
        for (String string : list) {
            System.out.println(string);
        }
    }
//這是帶參數(shù)類型的Lambda的寫法
        public void testLamda1(){
        List<String> list =Arrays.asList("aaa","fsa","ser","eere");
        Collections.sort(list, (Comparator<? super String>) (String a,String b)->{
            return b.compareTo(a);
        }
        );
        for (String string : list) {
            System.out.println(string);
        }
    }
//這是不帶參數(shù)的lambda的寫法
        public void testLamda2(){
        List<String> list =Arrays.asList("aaa","fsa","ser","eere");
        Collections.sort(list, (a,b)->b.compareTo(a)
        );
        for (String string : list) {
            System.out.println(string);
        }

可以看到不帶參數(shù)的寫法一句話就搞定了排序的問題己肮,所以引入lambda表達(dá)式的一個(gè)最直觀的作用就是大大的簡(jiǎn)化了代碼的開發(fā)士袄,像其他一些編程語(yǔ)言Scala,Python等都是支持函數(shù)式的寫法的谎僻。當(dāng)然娄柳,不是所有的接口都可以通過(guò)這種方法來(lái)調(diào)用,只有函數(shù)式接口才行艘绍,jdk1.8里面定義了好多個(gè)函數(shù)式接口赤拒,我們也可以自己定義一個(gè)來(lái)調(diào)用,下面說(shuō)一下什么是函數(shù)式接口诱鞠。

2.2挎挖、函數(shù)式接口

定義:“函數(shù)式接口”是指僅僅只包含一個(gè)抽象方法的接口,每一個(gè)該類型的lambda表達(dá)式都會(huì)被匹配到這個(gè)抽象方法航夺。jdk1.8提供了一個(gè)@FunctionalInterface注解來(lái)定義函數(shù)式接口蕉朵,如果我們定義的接口不符合函數(shù)式的規(guī)范便會(huì)報(bào)錯(cuò)。

@FunctionalInterface
public interface MyLamda {
   
   public void test1(String y);

//這里如果繼續(xù)加一個(gè)抽象方法便會(huì)報(bào)錯(cuò)
//    public void test1();
   
//default方法可以任意定義
   default String test2(){
       return "123";
   }
   
   default String test3(){
       return "123";
   }

//static方法也可以定義
   static void test4(){
       System.out.println("234");
   }

}

看一下這個(gè)接口的調(diào)用阳掐,符合lambda表達(dá)式的調(diào)用方法始衅。

MyLamda m = y -> System.out.println("ss"+y);

2.3、方法與構(gòu)造函數(shù)引用

jdk1.8提供了另外一種調(diào)用方式::缭保,當(dāng) 你 需 要使用 方 法 引用時(shí) 汛闸, 目 標(biāo)引用 放 在 分隔符::前 ,方法 的 名 稱放在 后 面 涮俄,即ClassName :: methodName 蛉拙。例如 ,Apple::getWeight就是引用了Apple類中定義的方法getWeight彻亲。請(qǐng)記住孕锄,不需要括號(hào)吮廉,因?yàn)槟銢]有實(shí)際調(diào)用這個(gè)方法。方法引用就是Lambda表達(dá)式(Apple a) -> a.getWeight()的快捷寫法畸肆,如下示例宦芦。

//先定義一個(gè)函數(shù)式接口
@FunctionalInterface
public interface TestConverT<T, F> {
    F convert(T t);
}

測(cè)試如下,可以以::形式調(diào)用轴脐。

public void test(){
    TestConverT<String, Integer> t = Integer::valueOf;
    Integer i = t.convert("111");
    System.out.println(i);
}

此外调卑,對(duì)于構(gòu)造方法也可以這么調(diào)用。

//實(shí)體類User和它的構(gòu)造方法
public class User {    
  private String name;
  
  private String sex;

  public User(String name, String sex) {
      super();
      this.name = name;
      this.sex = sex;
  }
}
//User工廠
public interface UserFactory {
  User get(String name, String sex);
}
//測(cè)試類
  UserFactory uf = User::new;
  User u = uf.get("ww", "man");

這里的User::new就是調(diào)用了User的構(gòu)造方法大咱,Java編譯器會(huì)自動(dòng)根據(jù)UserFactory.get方法的簽名來(lái)選擇合適的構(gòu)造函數(shù)恬涧。

  • 方法引用,與Lambda表達(dá)式聯(lián)合使用junit測(cè)試代碼
 /**
     * 4.方法引用,與Lambda表達(dá)式聯(lián)合使用
     */
    @Test
    public void testMethodReference(){
        //構(gòu)造器引用。語(yǔ)法是Class::new碴巾,或者更一般的Class< T >::new溯捆,要求構(gòu)造器方法是沒有參數(shù);
        final Car car = Car.create( Car::new );
        final List< Car > cars = Arrays.asList( car );
        //靜態(tài)方法引用厦瓢。語(yǔ)法是Class::static_method提揍,要求接受一個(gè)Class類型的參數(shù);
        cars.forEach( Car::collide );
        //任意對(duì)象的方法引用煮仇。它的語(yǔ)法是Class::method劳跃。無(wú)參,所有元素調(diào)用浙垫;
        cars.forEach( Car::repair );
        //特定對(duì)象的方法引用刨仑,它的語(yǔ)法是instance::method。有參夹姥,在某個(gè)對(duì)象上調(diào)用方法贸人,將列表元素作為參數(shù)傳入;
        final Car police = Car.create( Car::new );
        cars.forEach( police::follow );
    }
    
    public static class Car {
        public static Car create( final Supplier< Car > supplier ) {
            return supplier.get();
        }              
             
        public static void collide( final Car car ) {
            System.out.println( "靜態(tài)方法引用 " + car.toString() );
        }
             
        public void repair() {   
            System.out.println( "任意對(duì)象的方法引用 " + this.toString() );
        }
        
        public void follow( final Car car ) {
            System.out.println( "特定對(duì)象的方法引用 " + car.toString() );
        }
    }

2.4佃声、局部變量限制

Lambda表達(dá)式也允許使用自由變量(不是參數(shù),而是在外層作用域中定義的變量)倘要,就像匿名類一樣圾亏。 它們被稱作捕獲LambdaLambda可以沒有限制地捕獲(也就是在其主體中引用)實(shí)例變量和靜態(tài)變量封拧。但局部變量必須顯式聲明為final志鹃,或事實(shí)上是final
  為什么局部變量有這些限制泽西?
 〔芰濉(1)實(shí)例變量和局部變量背后的實(shí)現(xiàn)有一個(gè)關(guān)鍵不同。實(shí)例變量都存儲(chǔ)在堆中捧杉,而局部變量則保存在棧上陕见。如果Lambda可以直接訪問局部變量秘血,而且Lambda是在一個(gè)線程中使用的,則使用Lambda的線程评甜,可能會(huì)在分配該變量的線程將這個(gè)變量收回之后灰粮,去訪問該變量。因此忍坷, Java在訪問自由局部變量時(shí)粘舟,實(shí)際上是在訪問它的副本,而不是訪問原始變量佩研。如果局部變量?jī)H僅賦值一次那就沒有什么區(qū)別了——因此就有了這個(gè)限制柑肴。
  (2)這一限制不鼓勵(lì)你使用改變外部變量的典型命令式編程模式旬薯。

final int num = 1;
Converter<Integer, String> stringConverter =
       (from) -> String.valueOf(from + num);
stringConverter.convert(2); 

3.接口新增:默認(rèn)方法與靜態(tài)方法

 /**
     * 3.接口新增:默認(rèn)方法與靜態(tài)方法
     *  default 接口默認(rèn)實(shí)現(xiàn)方法是為了讓集合類默認(rèn)實(shí)現(xiàn)這些函數(shù)式處理晰骑,而不用修改現(xiàn)有代碼
     *  (List繼承于Iterable<T>,接口默認(rèn)方法不必須實(shí)現(xiàn)default forEach方法)
     */
    @Test
    public void testDefaultFunctionInterface(){
        //可以直接使用接口名.靜態(tài)方法來(lái)訪問接口中的靜態(tài)方法
        JDK8Interface1.staticMethod();
        //接口中的默認(rèn)方法必須通過(guò)它的實(shí)現(xiàn)類來(lái)調(diào)用
        new JDK8InterfaceImpl1().defaultMethod();
        //多實(shí)現(xiàn)類袍暴,默認(rèn)方法重名時(shí)必須復(fù)寫
        new JDK8InterfaceImpl2().defaultMethod();
    }
    
    public class JDK8InterfaceImpl1 implements JDK8Interface1 {
        //實(shí)現(xiàn)接口后些侍,因?yàn)槟J(rèn)方法不是抽象方法,重寫/不重寫都成政模!
//        @Override
//        public void defaultMethod(){
//            System.out.println("接口中的默認(rèn)方法");
//        }
    }
    
    public class JDK8InterfaceImpl2 implements JDK8Interface1,JDK8Interface2 {
        //實(shí)現(xiàn)接口后岗宣,默認(rèn)方法名相同,必須復(fù)寫默認(rèn)方法
        @Override
        public void defaultMethod() {
            //接口的
            JDK8Interface1.super.defaultMethod();
            System.out.println("實(shí)現(xiàn)類復(fù)寫重名默認(rèn)方法A苎:氖健!趁猴!");
        }
    }
    public interface JDK8Interface1 {
        //1.接口中可以定義靜態(tài)方法了
        public static void staticMethod(){
            System.out.println("接口中的靜態(tài)方法");
        }
        
        //2.使用default之后就可以定義普通方法的方法體了
        public default void defaultMethod(){
            System.out.println("接口中的默認(rèn)方法");
        }
    }
    public interface  JDK8Interface2 {
        //1.接口中可以定義靜態(tài)方法了
        public static void staticMethod(){
            System.out.println("接口中的靜態(tài)方法");
        }
        
        //2.使用default之后就可以定義普通方法的方法體了
        public default void defaultMethod(){
            System.out.println("接口中的默認(rèn)方法");
        }
    }

4.方法引用,與Lambda表達(dá)式聯(lián)合使用

/**
     * 4.方法引用,與Lambda表達(dá)式聯(lián)合使用
     */
    @Test
    public void testMethodReference(){
        //構(gòu)造器引用刊咳。語(yǔ)法是Class::new,或者更一般的Class< T >::new儡司,要求構(gòu)造器方法是沒有參數(shù)娱挨;
        final Car car = Car.create( Car::new );
        final List< Car > cars = Arrays.asList( car );
        //靜態(tài)方法引用。語(yǔ)法是Class::static_method捕犬,要求接受一個(gè)Class類型的參數(shù)跷坝;
        cars.forEach( Car::collide );
        //任意對(duì)象的方法引用。它的語(yǔ)法是Class::method碉碉。無(wú)參柴钻,所有元素調(diào)用;
        cars.forEach( Car::repair );
        //特定對(duì)象的方法引用垢粮,它的語(yǔ)法是instance::method贴届。有參,在某個(gè)對(duì)象上調(diào)用方法,將列表元素作為參數(shù)傳入毫蚓;
        final Car police = Car.create( Car::new );
        cars.forEach( police::follow );
    }
    
    public static class Car {
        public static Car create( final Supplier< Car > supplier ) {
            return supplier.get();
        }              
             
        public static void collide( final Car car ) {
            System.out.println( "靜態(tài)方法引用 " + car.toString() );
        }
             
        public void repair() {   
            System.out.println( "任意對(duì)象的方法引用 " + this.toString() );
        }
        
        public void follow( final Car car ) {
            System.out.println( "特定對(duì)象的方法引用 " + car.toString() );
        }
    }

5.引入重復(fù)注解

 /**
     * 5.引入重復(fù)注解
     * 1.@Repeatable 
     * 2.可以不用以前的“注解容器”寫法占键,直接寫2次相同注解即可
     * 
     * Java 8在編譯器層做了優(yōu)化,相同注解會(huì)以集合的方式保存绍些,因此底層的原理并沒有變化捞慌。
     */
    @Test
    public void RepeatingAnnotations(){
        RepeatingAnnotations.main(null);
    }
package com.zgldoing.base.jdk8Features;

import java.lang.annotation.ElementType;
import java.lang.annotation.Repeatable;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

import com.zgldoing.base.jdk8Features.RepeatingAnnotations.Filter;
import com.zgldoing.base.jdk8Features.RepeatingAnnotations.Filterable;
import com.zgldoing.base.jdk8Features.RepeatingAnnotations.Filters;
/**
 * @ClassName:RepeatingAnnotations
 * @Description:重復(fù)注解@Repeatable
 * @author zgldo
 *
 */
public class RepeatingAnnotations {
    @Target( ElementType.TYPE )
    @Retention( RetentionPolicy.RUNTIME )
    public @interface Filters {
        Filter[] value();
    }
     
    @Target( ElementType.TYPE )
    @Retention( RetentionPolicy.RUNTIME )
    @Repeatable( Filters.class )
    public @interface Filter {
        String value();
        String value2();
    };
     
    @Filter( value="filter1",value2="111" )
    @Filter( value="filter2", value2="222")
    //@Filters({@Filter(  value="filter1",value2="111" ),@Filter(  value="filter2", value2="222")}).注意:JDK8之前:1.沒有@Repeatable2.采用本行“注解容器”寫法
    public interface Filterable {        
    }
         
    public static void main(String[] args) {
        //獲取注解后遍歷打印值
        for( Filter filter: Filterable.class.getAnnotationsByType( Filter.class ) ) {
            System.out.println( filter.value() +filter.value2());
        }
    }
}

6.類型注解

/**
     * 6.類型注解
     * 新增類型注解:ElementType.TYPE_USE 和ElementType.TYPE_PARAMETER(在Target上)
     * 
     */
    @Test
    public void ElementType(){
        Annotations.main(null);
    }
package com.zgldoing.base.jdk8Features;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.util.ArrayList;
import java.util.Collection;

import com.zgldoing.base.jdk8Features.Annotations.Holder;
import com.zgldoing.base.jdk8Features.Annotations.NonEmpty;
/**
 * @ClassName:Annotations
 * @Description:新增類型注解:ElementType.TYPE_USE 和ElementType.TYPE_PARAMETER(在Target上)
 * @author zgldo
 *
 */
public class Annotations {
      @Retention( RetentionPolicy.RUNTIME )
        @Target( { ElementType.TYPE_USE, ElementType.TYPE_PARAMETER } )
        public @interface NonEmpty {        
        }
             
        public static class Holder< @NonEmpty T > extends @NonEmpty Object {
            public void method() throws @NonEmpty Exception {           
            }
        }
             
        public static void main(String[] args) {
            final Holder< String > holder = new @NonEmpty Holder< String >();       
            @NonEmpty Collection< @NonEmpty String > strings = new ArrayList<>();       
        }
}

7、Stream函數(shù)式操作流元素

定義:流是Java API的新成員柬批,它允許我們以聲明性方式處理數(shù)據(jù)集合(通過(guò)查詢語(yǔ)句來(lái)表達(dá)啸澡,而不是臨時(shí)編寫一個(gè)實(shí)現(xiàn))。就現(xiàn)在來(lái)說(shuō)氮帐,我們可以把它們看成遍歷數(shù)據(jù)集的高級(jí)迭代器嗅虏。此外,流還可以透明地并行處理上沐,也就是說(shuō)我們不用寫多線程代碼了皮服。

Stream 不是集合元素,它不是數(shù)據(jù)結(jié)構(gòu)并不保存數(shù)據(jù)参咙,它是有關(guān)算法和計(jì)算的龄广,它更像一個(gè)高級(jí)版本的Iterator。原始版本的 Iterator蕴侧,用戶只能顯式地一個(gè)一個(gè)遍歷元素并對(duì)其執(zhí)行某些操作择同;高級(jí)版本的 Stream,用戶只要給出需要對(duì)其包含的元素執(zhí)行什么操作净宵,比如 “過(guò)濾掉長(zhǎng)度大于 10 的字符串”敲才、“獲取每個(gè)字符串的首字母”等,Stream 會(huì)隱式地在內(nèi)部進(jìn)行遍歷择葡,做出相應(yīng)的數(shù)據(jù)轉(zhuǎn)換紧武。

Stream 就如同一個(gè)迭代器(Iterator),單向敏储,不可往復(fù)阻星,數(shù)據(jù)只能遍歷一次,遍歷過(guò)一次后即用盡了已添,就好比流水從面前流過(guò)迫横,一去不復(fù)返。而和迭代器又不同的是酝碳,Stream 可以并行化操作,迭代器只能命令式地恨狈、串行化操作疏哗。顧名思義,當(dāng)使用串行方式去遍歷時(shí)禾怠,每個(gè) item 讀完后再讀下一個(gè)item返奉。而使用并行去遍歷時(shí)贝搁,數(shù)據(jù)會(huì)被分成多個(gè)段,其中每一個(gè)都在不同的線程中處理芽偏,然后將結(jié)果一起輸出雷逆。Stream 的并行操作依賴于 Java7 中引入的 Fork/Join 框架(JSR166y)來(lái)拆分任務(wù)和加速處理過(guò)程。

流的操作類型分為兩種:

  • Intermediate:一個(gè)流可以后面跟隨零個(gè)或多個(gè) intermediate 操作污尉。其目的主要是打開流膀哲,做出某種程度的數(shù)據(jù)映射/過(guò)濾,然后返回一個(gè)新的流被碗,交給下一個(gè)操作使用某宪。這類操作都是惰性化的(lazy),就是說(shuō)锐朴,僅僅調(diào)用到這類方法兴喂,并沒有真正開始流的遍歷。
  • Terminal:一個(gè)流只能有一個(gè) terminal操作焚志,當(dāng)這個(gè)操作執(zhí)行后衣迷,流就被使用“光”了,無(wú)法再被操作酱酬。所以這必定是流的最后一個(gè)操作壶谒。Terminal操作的執(zhí)行,才會(huì)真正開始流的遍歷岳悟,并且會(huì)生成一個(gè)結(jié)果佃迄,或者一個(gè) side effect

在對(duì)于一個(gè)Stream 進(jìn)行多次轉(zhuǎn)換操作 (Intermediate 操作)贵少,每次都對(duì) Stream的每個(gè)元素進(jìn)行轉(zhuǎn)換呵俏,而且是執(zhí)行多次,這樣時(shí)間復(fù)雜度就是 N(轉(zhuǎn)換次數(shù))個(gè) for 循環(huán)里把所有操作都做掉的總和嗎滔灶?其實(shí)不是這樣的普碎,轉(zhuǎn)換操作都是 lazy 的,多個(gè)轉(zhuǎn)換操作只會(huì)在 Terminal 操作的時(shí)候融合起來(lái)录平,一次循環(huán)完成麻车。我們可以這樣簡(jiǎn)單的理解,Stream 里有個(gè)操作函數(shù)的集合斗这,每次轉(zhuǎn)換操作就是把轉(zhuǎn)換函數(shù)放入這個(gè)集合中动猬,在 Terminal 操作的時(shí)候循環(huán) Stream 對(duì)應(yīng)的集合,然后對(duì)每個(gè)元素執(zhí)行所有的函數(shù)表箭。

構(gòu)造流的幾種方式

// 1. Individual values
Stream stream = Stream.of("a", "b", "c");
// 2. Arrays
String [] strArray = new String[] {"a", "b", "c"};
stream = Stream.of(strArray);
stream = Arrays.stream(strArray);
// 3. Collections
List<String> list = Arrays.asList(strArray);
stream = list.stream();
  • Stream函數(shù)式操作流元素集合
/**
     * 2.Stream函數(shù)式操作流元素集合
     */
    @Test
    public void testStream(){
        List<Integer> nums = Lists.newArrayList(1,1,null,2,3,4,null,5,6,7,8,9,10);
        System.out.println("求和:"+nums
                .stream()//轉(zhuǎn)成Stream
                .filter(team -> team!=null)//過(guò)濾
                .distinct()//去重
                .mapToInt(num->num*2)//map操作
                .skip(2)//跳過(guò)前2個(gè)元素
                .limit(4)//限制取前4個(gè)元素
                .peek(System.out::println)//流式處理對(duì)象函數(shù)
                .sum());//
    }
    

8赁咙、Date API更新

1.8之前JDK自帶的日期處理類非常不方便,我們處理的時(shí)候經(jīng)常是使用的第三方工具包,比如commons-lang包等彼水。不過(guò)1.8出現(xiàn)之后這個(gè)改觀了很多崔拥,比如日期時(shí)間的創(chuàng)建、比較凤覆、調(diào)整链瓦、格式化、時(shí)間間隔等盯桦。這些類都在java.time包下慈俯。比原來(lái)實(shí)用了很多。

8.1 LocalDate/LocalTime/LocalDateTime

LocalDate為日期處理類俺附、LocalTime為時(shí)間處理類肥卡、LocalDateTime為日期時(shí)間處理類,方法都類似事镣,具體可以看API文檔或源碼步鉴,選取幾個(gè)代表性的方法做下介紹。

now相關(guān)的方法可以獲取當(dāng)前日期或時(shí)間璃哟,of方法可以創(chuàng)建對(duì)應(yīng)的日期或時(shí)間氛琢,parse方法可以解析日期或時(shí)間,get方法可以獲取日期或時(shí)間信息随闪,with方法可以設(shè)置日期或時(shí)間信息阳似,plusminus方法可以增減日期或時(shí)間信息;

8.2 TemporalAdjusters

這個(gè)類在日期調(diào)整時(shí)非常有用铐伴,比如得到當(dāng)月的第一天撮奏、最后一天,當(dāng)年的第一天当宴、最后一天畜吊,下一周或前一周的某天等。

8.3 DateTimeFormatter

以前日期格式化一般用SimpleDateFormat類户矢,但是不怎么好用玲献,現(xiàn)在1.8引入了DateTimeFormatter類,默認(rèn)定義了很多常量格式(ISO打頭的)梯浪,在使用的時(shí)候一般配合LocalDate/LocalTime/LocalDateTime使用捌年,比如想把當(dāng)前日期格式化成yyyy-MM-dd hh:mm:ss的形式:

LocalDateTime dt = LocalDateTime.now();  
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd hh:mm:ss");         
System.out.println(dtf.format(dt));
  • Date/Time API junit測(cè)試代碼
/**
     * 7.最新的Date/Time API (JSR 310)
     * UTC即為世界標(biāo)準(zhǔn)時(shí)間,世界統(tǒng)一時(shí)間挂洛,國(guó)際協(xié)調(diào)時(shí)間礼预,字母T是時(shí)間和日期的分隔符,T后面表示的即為時(shí)間虏劲,末尾的z表示UTC統(tǒng)一時(shí)間逆瑞。
     */
    @Test
    public void DateTime(){
        //1.Clock
        final Clock clock = Clock.systemUTC();
        System.out.println( clock.instant() );//2018-12-27T13:25:18.636Z
        System.out.println( clock.millis() );//1545917118662
        
        //2. ISO-8601格式且無(wú)時(shí)區(qū)信息的日期部分
        final LocalDate date = LocalDate.now();
        final LocalDate dateFromClock = LocalDate.now( clock );
                 
        System.out.println( date );//2018-12-27
        System.out.println( dateFromClock );//2018-12-27
                 
        // ISO-8601格式且無(wú)時(shí)區(qū)信息的時(shí)間部分
        final LocalTime time = LocalTime.now();
        final LocalTime timeFromClock = LocalTime.now( clock );
                 
        System.out.println( time );         //21:25:18.692
        System.out.println( timeFromClock );//13:25:18.692
        
        // 3.ISO-8601格式無(wú)時(shí)區(qū)信息的日期與時(shí)間
        final LocalDateTime datetime = LocalDateTime.now();
        final LocalDateTime datetimeFromClock = LocalDateTime.now( clock );
                 
        System.out.println( datetime );         //2018-12-27T21:25:18.692
        System.out.println( datetimeFromClock );//2018-12-27T13:25:18.692
        
        // 4.特定時(shí)區(qū)的日期/時(shí)間荠藤,
        final ZonedDateTime zonedDatetime = ZonedDateTime.now();
        final ZonedDateTime zonedDatetimeFromClock = ZonedDateTime.now( clock );
        final ZonedDateTime zonedDatetimeFromZone = ZonedDateTime.now( ZoneId.of( "America/Los_Angeles" ) );
                 
        System.out.println( zonedDatetime );         //2018-12-27T21:25:18.694+08:00[Asia/Shanghai]
        System.out.println( zonedDatetimeFromClock );//2018-12-27T13:25:18.694Z
        System.out.println( zonedDatetimeFromZone ); //2018-12-27T05:25:18.706-08:00[America/Los_Angeles]
        
        //5.在秒與納秒級(jí)別上的一段時(shí)間
        final LocalDateTime from = LocalDateTime.of( 2014, Month.APRIL, 16, 0, 0, 0 );
        final LocalDateTime to = LocalDateTime.of( 2015, Month.APRIL, 16, 23, 59, 59 );
         
        final Duration duration = Duration.between( from, to );
        System.out.println( "Duration in days: " + duration.toDays() );  //Duration in days: 365
        System.out.println( "Duration in hours: " + duration.toHours() );//Duration in hours: 8783
    }

9.新增base64加解密API

/**
     * 8.新增base64加解密API
     */
    @Test
    public void testBase64(){
        final String text = "就是要測(cè)試加解密!获高!abjdkhdkuasu!!@@@@";
        String encoded = Base64.getEncoder()
            .encodeToString( text.getBytes( StandardCharsets.UTF_8 ) );
        System.out.println("加密后="+ encoded );
         
        final String decoded = new String( 
            Base64.getDecoder().decode( encoded ),
            StandardCharsets.UTF_8 );
        System.out.println( "解密后="+decoded );
    }

10.數(shù)組并行(parallel)操作

  /**
     * 9.數(shù)組并行(parallel)操作
     */
    @Test
    public void testParallel(){
        long[] arrayOfLong = new long [ 20000 ];        
        //1.給數(shù)組隨機(jī)賦值
        Arrays.parallelSetAll( arrayOfLong, 
            index -> ThreadLocalRandom.current().nextInt( 1000000 ) );
        //2.打印出前10個(gè)元素
        Arrays.stream( arrayOfLong ).limit( 10 ).forEach( 
            i -> System.out.print( i + " " ) );
        System.out.println();
        //3.數(shù)組排序
        Arrays.parallelSort( arrayOfLong );     
        //4.打印排序后的前10個(gè)元素
        Arrays.stream( arrayOfLong ).limit( 10 ).forEach( 
            i -> System.out.print( i + " " ) );
        System.out.println();
    }

11.JVM的PermGen空間被移除:取代它的是Metaspace(JEP 122)元空間

 /**
     * 10.JVM的PermGen空間被移除:取代它的是Metaspace(JEP 122)元空間
     */
    @Test
    public void testMetaspace(){
        //-XX:MetaspaceSize初始空間大小,達(dá)到該值就會(huì)觸發(fā)垃圾收集進(jìn)行類型卸載吻育,同時(shí)GC會(huì)對(duì)該值進(jìn)行調(diào)整
        //-XX:MaxMetaspaceSize最大空間念秧,默認(rèn)是沒有限制
        //-XX:MinMetaspaceFreeRatio在GC之后,最小的Metaspace剩余空間容量的百分比布疼,減少為分配空間所導(dǎo)致的垃圾收集
        //-XX:MaxMetaspaceFreeRatio在GC之后摊趾,最大的Metaspace剩余空間容量的百分比,減少為釋放空間所導(dǎo)致的垃圾收集
    }

三游两、總結(jié)

總的來(lái)說(shuō)砾层,jdk1.8的一些新特性主要還是簡(jiǎn)化了代碼的寫法,減少了部分開發(fā)量贱案,但是需要一些時(shí)間來(lái)熟悉肛炮。很慚愧,1.8的新特性還不是很熟悉宝踪,所以還是要繼續(xù)努力侨糟,還需要多看些源碼。

四瘩燥、附錄 junit測(cè)試代碼

1秕重、 JDK8_features.java

package com.zgldoing.base.jdk8Features;

import static org.junit.jupiter.api.Assertions.*;

import java.nio.charset.StandardCharsets;
import java.time.Clock;
import java.time.Duration;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.Month;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Base64;
import java.util.List;
import java.util.concurrent.ThreadLocalRandom;
import java.util.function.Supplier;

import org.junit.jupiter.api.Test;

import com.google.common.collect.Lists;

/**
 * 
 * @ClassName:JDK8_features
 * @Description:JDK8新特性
 * 
 */
public class JDK8_features {
    
    public List<Integer> list = Lists.newArrayList(1,2,3,4,5,6,7,8,9,10);
    
    /**
     * 1.Lambda表達(dá)式
     */
    @Test
    public void testLambda(){
        list.forEach(System.out::println);
        list.forEach(e -> System.out.println("方式二:"+e));
    }
    
    /**
     * 2.Stream函數(shù)式操作流元素集合
     */
    @Test
    public void testStream(){
        List<Integer> nums = Lists.newArrayList(1,1,null,2,3,4,null,5,6,7,8,9,10);
        System.out.println("求和:"+nums
                .stream()//轉(zhuǎn)成Stream
                .filter(team -> team!=null)//過(guò)濾
                .distinct()//去重
                .mapToInt(num->num*2)//map操作
                .skip(2)//跳過(guò)前2個(gè)元素
                .limit(4)//限制取前4個(gè)元素
                .peek(System.out::println)//流式處理對(duì)象函數(shù)
                .sum());//
    }
    
    /**
     * 3.接口新增:默認(rèn)方法與靜態(tài)方法
     *  default 接口默認(rèn)實(shí)現(xiàn)方法是為了讓集合類默認(rèn)實(shí)現(xiàn)這些函數(shù)式處理,而不用修改現(xiàn)有代碼
     *  (List繼承于Iterable<T>厉膀,接口默認(rèn)方法不必須實(shí)現(xiàn)default forEach方法)
     */
    @Test
    public void testDefaultFunctionInterface(){
        //可以直接使用接口名.靜態(tài)方法來(lái)訪問接口中的靜態(tài)方法
        JDK8Interface1.staticMethod();
        //接口中的默認(rèn)方法必須通過(guò)它的實(shí)現(xiàn)類來(lái)調(diào)用
        new JDK8InterfaceImpl1().defaultMethod();
        //多實(shí)現(xiàn)類溶耘,默認(rèn)方法重名時(shí)必須復(fù)寫
        new JDK8InterfaceImpl2().defaultMethod();
    }
    
    public class JDK8InterfaceImpl1 implements JDK8Interface1 {
        //實(shí)現(xiàn)接口后,因?yàn)槟J(rèn)方法不是抽象方法服鹅,重寫/不重寫都成凳兵!
//        @Override
//        public void defaultMethod(){
//            System.out.println("接口中的默認(rèn)方法");
//        }
    }
    
    public class JDK8InterfaceImpl2 implements JDK8Interface1,JDK8Interface2 {
        //實(shí)現(xiàn)接口后,默認(rèn)方法名相同菱魔,必須復(fù)寫默認(rèn)方法
        @Override
        public void defaultMethod() {
            //接口的
            JDK8Interface1.super.defaultMethod();
            System.out.println("實(shí)現(xiàn)類復(fù)寫重名默認(rèn)方法A衾蟆!@骄搿聚蝶!");
        }
    }
    public interface JDK8Interface1 {
        //1.接口中可以定義靜態(tài)方法了
        public static void staticMethod(){
            System.out.println("接口中的靜態(tài)方法");
        }
        
        //2.使用default之后就可以定義普通方法的方法體了
        public default void defaultMethod(){
            System.out.println("接口中的默認(rèn)方法");
        }
    }
    public interface  JDK8Interface2 {
        //1.接口中可以定義靜態(tài)方法了
        public static void staticMethod(){
            System.out.println("接口中的靜態(tài)方法");
        }
        
        //2.使用default之后就可以定義普通方法的方法體了
        public default void defaultMethod(){
            System.out.println("接口中的默認(rèn)方法");
        }
    }
    /**
     * 4.方法引用,與Lambda表達(dá)式聯(lián)合使用
     */
    @Test
    public void testMethodReference(){
        //構(gòu)造器引用。語(yǔ)法是Class::new藻治,或者更一般的Class< T >::new碘勉,要求構(gòu)造器方法是沒有參數(shù);
        final Car car = Car.create( Car::new );
        final List< Car > cars = Arrays.asList( car );
        //靜態(tài)方法引用桩卵。語(yǔ)法是Class::static_method验靡,要求接受一個(gè)Class類型的參數(shù)倍宾;
        cars.forEach( Car::collide );
        //任意對(duì)象的方法引用。它的語(yǔ)法是Class::method胜嗓。無(wú)參高职,所有元素調(diào)用;
        cars.forEach( Car::repair );
        //特定對(duì)象的方法引用辞州,它的語(yǔ)法是instance::method怔锌。有參,在某個(gè)對(duì)象上調(diào)用方法变过,將列表元素作為參數(shù)傳入埃元;
        final Car police = Car.create( Car::new );
        cars.forEach( police::follow );
    }
    
    public static class Car {
        public static Car create( final Supplier< Car > supplier ) {
            return supplier.get();
        }              
             
        public static void collide( final Car car ) {
            System.out.println( "靜態(tài)方法引用 " + car.toString() );
        }
             
        public void repair() {   
            System.out.println( "任意對(duì)象的方法引用 " + this.toString() );
        }
        
        public void follow( final Car car ) {
            System.out.println( "特定對(duì)象的方法引用 " + car.toString() );
        }
    }
    
    /**
     * 5.引入重復(fù)注解
     * 1.@Repeatable 
     * 2.可以不用以前的“注解容器”寫法,直接寫2次相同注解即可
     * 
     * Java 8在編譯器層做了優(yōu)化媚狰,相同注解會(huì)以集合的方式保存岛杀,因此底層的原理并沒有變化。
     */
    @Test
    public void RepeatingAnnotations(){
        RepeatingAnnotations.main(null);
    }
    
    /**
     * 6.類型注解
     * 新增類型注解:ElementType.TYPE_USE 和ElementType.TYPE_PARAMETER(在Target上)
     * 
     */
    @Test
    public void ElementType(){
        Annotations.main(null);
    }
    
    /**
     * 7.最新的Date/Time API (JSR 310)
     * UTC即為世界標(biāo)準(zhǔn)時(shí)間崭孤,世界統(tǒng)一時(shí)間类嗤,國(guó)際協(xié)調(diào)時(shí)間,字母T是時(shí)間和日期的分隔符裳瘪,T后面表示的即為時(shí)間土浸,末尾的z表示UTC統(tǒng)一時(shí)間。
     */
    @Test
    public void DateTime(){
        //1.Clock
        final Clock clock = Clock.systemUTC();
        System.out.println( clock.instant() );//2018-12-27T13:25:18.636Z
        System.out.println( clock.millis() );//1545917118662
        
        //2. ISO-8601格式且無(wú)時(shí)區(qū)信息的日期部分
        final LocalDate date = LocalDate.now();
        final LocalDate dateFromClock = LocalDate.now( clock );
                 
        System.out.println( date );//2018-12-27
        System.out.println( dateFromClock );//2018-12-27
                 
        // ISO-8601格式且無(wú)時(shí)區(qū)信息的時(shí)間部分
        final LocalTime time = LocalTime.now();
        final LocalTime timeFromClock = LocalTime.now( clock );
                 
        System.out.println( time );         //21:25:18.692
        System.out.println( timeFromClock );//13:25:18.692
        
        // 3.ISO-8601格式無(wú)時(shí)區(qū)信息的日期與時(shí)間
        final LocalDateTime datetime = LocalDateTime.now();
        final LocalDateTime datetimeFromClock = LocalDateTime.now( clock );
                 
        System.out.println( datetime );         //2018-12-27T21:25:18.692
        System.out.println( datetimeFromClock );//2018-12-27T13:25:18.692
        
        // 4.特定時(shí)區(qū)的日期/時(shí)間彭羹,
        final ZonedDateTime zonedDatetime = ZonedDateTime.now();
        final ZonedDateTime zonedDatetimeFromClock = ZonedDateTime.now( clock );
        final ZonedDateTime zonedDatetimeFromZone = ZonedDateTime.now( ZoneId.of( "America/Los_Angeles" ) );
                 
        System.out.println( zonedDatetime );         //2018-12-27T21:25:18.694+08:00[Asia/Shanghai]
        System.out.println( zonedDatetimeFromClock );//2018-12-27T13:25:18.694Z
        System.out.println( zonedDatetimeFromZone ); //2018-12-27T05:25:18.706-08:00[America/Los_Angeles]
        
        //5.在秒與納秒級(jí)別上的一段時(shí)間
        final LocalDateTime from = LocalDateTime.of( 2014, Month.APRIL, 16, 0, 0, 0 );
        final LocalDateTime to = LocalDateTime.of( 2015, Month.APRIL, 16, 23, 59, 59 );
         
        final Duration duration = Duration.between( from, to );
        System.out.println( "Duration in days: " + duration.toDays() );  //Duration in days: 365
        System.out.println( "Duration in hours: " + duration.toHours() );//Duration in hours: 8783
    }
    
    /**
     * 8.新增base64加解密API
     */
    @Test
    public void testBase64(){
        final String text = "就是要測(cè)試加解密;埔痢!abjdkhdkuasu!!@@@@";
        String encoded = Base64.getEncoder()
            .encodeToString( text.getBytes( StandardCharsets.UTF_8 ) );
        System.out.println("加密后="+ encoded );
         
        final String decoded = new String( 
            Base64.getDecoder().decode( encoded ),
            StandardCharsets.UTF_8 );
        System.out.println( "解密后="+decoded );
    }
    
    /**
     * 9.數(shù)組并行(parallel)操作
     */
    @Test
    public void testParallel(){
        long[] arrayOfLong = new long [ 20000 ];        
        //1.給數(shù)組隨機(jī)賦值
        Arrays.parallelSetAll( arrayOfLong, 
            index -> ThreadLocalRandom.current().nextInt( 1000000 ) );
        //2.打印出前10個(gè)元素
        Arrays.stream( arrayOfLong ).limit( 10 ).forEach( 
            i -> System.out.print( i + " " ) );
        System.out.println();
        //3.數(shù)組排序
        Arrays.parallelSort( arrayOfLong );     
        //4.打印排序后的前10個(gè)元素
        Arrays.stream( arrayOfLong ).limit( 10 ).forEach( 
            i -> System.out.print( i + " " ) );
        System.out.println();
    }
    
    /**
     * 10.JVM的PermGen空間被移除:取代它的是Metaspace(JEP 122)元空間
     */
    @Test
    public void testMetaspace(){
        //-XX:MetaspaceSize初始空間大小派殷,達(dá)到該值就會(huì)觸發(fā)垃圾收集進(jìn)行類型卸載还最,同時(shí)GC會(huì)對(duì)該值進(jìn)行調(diào)整
        //-XX:MaxMetaspaceSize最大空間,默認(rèn)是沒有限制
        //-XX:MinMetaspaceFreeRatio在GC之后毡惜,最小的Metaspace剩余空間容量的百分比拓轻,減少為分配空間所導(dǎo)致的垃圾收集
        //-XX:MaxMetaspaceFreeRatio在GC之后,最大的Metaspace剩余空間容量的百分比经伙,減少為釋放空間所導(dǎo)致的垃圾收集
    }
    
}

2扶叉、重復(fù)注解@Repeatable

package com.zgldoing.base.jdk8Features;

import java.lang.annotation.ElementType;
import java.lang.annotation.Repeatable;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

import com.zgldoing.base.jdk8Features.RepeatingAnnotations.Filter;
import com.zgldoing.base.jdk8Features.RepeatingAnnotations.Filterable;
import com.zgldoing.base.jdk8Features.RepeatingAnnotations.Filters;
/**
 * @ClassName:RepeatingAnnotations
 * @Description:重復(fù)注解@Repeatable
 * @author zgldo
 *
 */
public class RepeatingAnnotations {
    @Target( ElementType.TYPE )
    @Retention( RetentionPolicy.RUNTIME )
    public @interface Filters {
        Filter[] value();
    }
     
    @Target( ElementType.TYPE )
    @Retention( RetentionPolicy.RUNTIME )
    @Repeatable( Filters.class )
    public @interface Filter {
        String value();
        String value2();
    };
     
    @Filter( value="filter1",value2="111" )
    @Filter( value="filter2", value2="222")
    //@Filters({@Filter(  value="filter1",value2="111" ),@Filter(  value="filter2", value2="222")}).注意:JDK8之前:1.沒有@Repeatable2.采用本行“注解容器”寫法
    public interface Filterable {        
    }
         
    public static void main(String[] args) {
        //獲取注解后遍歷打印值
        for( Filter filter: Filterable.class.getAnnotationsByType( Filter.class ) ) {
            System.out.println( filter.value() +filter.value2());
        }
    }
}

3、新增類型注解:ElementType.TYPE_USE 和ElementType.TYPE_PARAMETER(在Target上)

package com.zgldoing.base.jdk8Features;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.util.ArrayList;
import java.util.Collection;

import com.zgldoing.base.jdk8Features.Annotations.Holder;
import com.zgldoing.base.jdk8Features.Annotations.NonEmpty;
/**
 * @ClassName:Annotations
 * @Description:新增類型注解:ElementType.TYPE_USE 和ElementType.TYPE_PARAMETER(在Target上)
 * @author zgldo
 *
 */
public class Annotations {
      @Retention( RetentionPolicy.RUNTIME )
        @Target( { ElementType.TYPE_USE, ElementType.TYPE_PARAMETER } )
        public @interface NonEmpty {        
        }
             
        public static class Holder< @NonEmpty T > extends @NonEmpty Object {
            public void method() throws @NonEmpty Exception {           
            }
        }
             
        public static void main(String[] args) {
            final Holder< String > holder = new @NonEmpty Holder< String >();       
            @NonEmpty Collection< @NonEmpty String > strings = new ArrayList<>();       
        }
}

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末帕膜,一起剝皮案震驚了整個(gè)濱河市枣氧,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌垮刹,老刑警劉巖达吞,帶你破解...
    沈念sama閱讀 211,042評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異荒典,居然都是意外死亡酪劫,警方通過(guò)查閱死者的電腦和手機(jī)吞鸭,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,996評(píng)論 2 384
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)覆糟,“玉大人刻剥,你說(shuō)我怎么就攤上這事√沧郑” “怎么了透敌?”我有些...
    開封第一講書人閱讀 156,674評(píng)論 0 345
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)踢械。 經(jīng)常有香客問我,道長(zhǎng)魄藕,這世上最難降的妖魔是什么内列? 我笑而不...
    開封第一講書人閱讀 56,340評(píng)論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮背率,結(jié)果婚禮上话瞧,老公的妹妹穿的比我還像新娘。我一直安慰自己寝姿,他們只是感情好交排,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,404評(píng)論 5 384
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著饵筑,像睡著了一般埃篓。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上根资,一...
    開封第一講書人閱讀 49,749評(píng)論 1 289
  • 那天架专,我揣著相機(jī)與錄音,去河邊找鬼玄帕。 笑死部脚,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的裤纹。 我是一名探鬼主播委刘,決...
    沈念sama閱讀 38,902評(píng)論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼鹰椒!你這毒婦竟也來(lái)了锡移?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,662評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤吹零,失蹤者是張志新(化名)和其女友劉穎罩抗,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體灿椅,經(jīng)...
    沈念sama閱讀 44,110評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡套蒂,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,451評(píng)論 2 325
  • 正文 我和宋清朗相戀三年钞支,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片操刀。...
    茶點(diǎn)故事閱讀 38,577評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡烁挟,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出骨坑,到底是詐尸還是另有隱情撼嗓,我是刑警寧澤,帶...
    沈念sama閱讀 34,258評(píng)論 4 328
  • 正文 年R本政府宣布欢唾,位于F島的核電站且警,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏礁遣。R本人自食惡果不足惜斑芜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,848評(píng)論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望祟霍。 院中可真熱鬧杏头,春花似錦、人聲如沸沸呐。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,726評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)崭添。三九已至寓娩,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,952評(píng)論 1 264
  • 我被黑心中介騙來(lái)泰國(guó)打工魂拦, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人排嫌。 一個(gè)月前我還...
    沈念sama閱讀 46,271評(píng)論 2 360
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像缰犁,于是被迫代替她去往敵國(guó)和親淳地。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,452評(píng)論 2 348

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