jdk8

作者: 北风第一支 | 来源:发表于2017-05-30 12:32 被阅读0次

    Java 8是Java自Java 5(发布于2004年)之后的最重要的版本。这个版本包含语言、编译器、库、工具和JVM等方面的十多个新特性。

    Lambda表达式和函数式接口

    ['læmdə] 朗姆蹬..
    jdk8之前,各种的匿名内部类,大把大把拖沓的代码,程序毫无美感可言!既然java中一切皆为对象,那么,就类似于某些动态语言一样,函数也可以当成是对象,代码块也可以当成是对象啊,随着函数式编程的概念越来越深入人心,java中CODE=OBJECT的这一天终于到来了!
    ambda的语法 包含3个部分:
    (1)括弧包起来的参数 ,参数可以写类型,也可以不写
    (2)一个箭头
    (3)方法体,可以是单个语句,也可以是语句块 , 方法可以有返回,也可以无返回,如果有多个语句,还要返回值,需要加上return

    lambda的定义:
    lambda是方法的实现
    lambda是延迟执行的
    首先看一个用Runable的实现:

    public static void main(String args[]){
             Runnable r = ()->System.out.println("hello,lambda");
             r.run();
    }
    

    为了配合lambda,jdk8引入了一个新的定义叫做:函数式接口(Functional interfaces)。

    函数式接口

    函数式接口的定义:
    是一个接口
    只有一个待实现的方法
    jdk8开始,接口可以有default方法,所以,函数式接口也是可以有default方法的,但是,只能有一个未实现的方法。 与此对应,新引入了一个注解: @FunctionalInterface
    这个注解只是起文档的作用,说明这个接口是函数式接口,编译器并不会使用这个注解来决定一个接口是不是函数式接口。
    不管加不加@FunctionalInterface这个注解,下面的接口都是函数式接口:

    interface Something { 
      public String doit(Integer i); //只有一个未实现的方法
    } 
    

    函数式接口如何与lambda结合使用的呢?,只含有一个接口方法的函数式接口可以隐式转换为Lambda表达式。java.lang.Runnable和java.util.concurrent.Callable是函数式接口的最佳例子。在实践中,函数式接口非常脆弱:只要某个开发者在该接口中添加一个函数,则该接口就不再是函数式接口进而导致编译失败。为了克服这种代码层面的脆弱性,并显式说明某个接口是函数式接口,Java 8 提供了一个特殊的注解@FunctionalInterface(Java 库中的所有相关接口都已经带有这个注解了),举个简单的函数式接口的定义:

    @FunctionalInterfacepublic interface Functional { 
             void method();
    }
    

    不过有一点需要注意,[默认方法和静态方法]是不会破坏函数式接口的定义,因此如下的代码是合法的。

    @FunctionalInterfacepublic interface FunctionalDefaultMethods { 
           void method(); 
           default void defaultMethod() {
           } 
    }
    

    列如:

    public  void test2(){
          HaveArgs notArgs = (String x,Integer xx)->{
                System.out.println(x);
                System.out.println(xx);
          };
          notArgs.doSomething("good",32);
    }
    

    默认方法

    类似抽象类里的公用方法

    为什么不能用默认方法来重载equals,hashCode和toString?
    接口不能提供对Object类的任何方法的默认实现。这意味着从接口里不能提供对equals,hashCode或toString的默认实现。
    这刚看起来挺奇怪的,但考虑到一些接口实际上是在文档里定义他们的equals行为的。List接口就是一个例子了。因此,为什么不允许这样呢?
    Brian Goetz在这个问题上的冗长的回复里给出了4个原因。我这里只说其中一个,因为那个已经足够说服我了:
    它会变得更困难来推导什么时候该调用默认的方法。如果一个类实现了一个方法,那总是优先于默认的实现的。所有接口实例都对equals/hashCode/toString的非默认实现,一个在接口上这些的默认版本都是没用的,它也不会被编译。

    Optional

    Java应用中最常见的bug就是[空值异常]在Java 8之前,[Google Guava]引入了Optionals类来解决NullPointerException,从而避免源码被各种null检查污染,以便开发者写出更加整洁的代码。Java 8也将Optional加入了官方库。
    Optional仅仅是一个容易:存放T类型的值或者null。它提供了一些有用的接口来避免显式的null检查。

    Optional< String > fullName = Optional.ofNullable( null );
    System.out.println( "Full Name is set? " + fullName.isPresent() );        
    System.out.println( "Full Name: " + fullName.orElseGet( () -> "[none]" ) ); 
    System.out.println( fullName.map( s -> "Hey " + s + "!" ).orElse( "Hey Stranger!" ) );
    

    如果Optional实例持有一个非空值,则isPresent()方法返回true,否则返回false;orElseGet()方法,Optional实例持有null,则可以接受一个lambda表达式生成的默认值;map()方法可以将现有的Opetional实例的值转换成新的值;orElse()方法与orElseGet()方法类似,但是在持有null的时候返回传入的默认值。

    Streams

    Stream 的创建需要指定一个数据源,比如 java.util.Collection的子类,List或者Set, Map不支持。Stream的操作可以串行执行或者并行执行。
    过滤age>12的元素,并输出:

    listperson.stream()
          .filter((it) -> it.getAge() >= 21)
          .forEach((it) -> 
            System.out.println("Have a beer, " + it.getFirstName()));
    
    

    Date/Time

    Java 8中新的时间和日期管理API深受Joda-Time影响,并吸收了很多Joda-Time的精华。新的java.time包包含了所有关于日期、时间、时区、Instant(跟日期类似但是精确到纳秒)、duration(持续时间)和时钟操作的类。新设计的API认真考虑了这些类的不变性(从java.util.Calendar吸取的教训),如果某个实例需要修改,则返回一个新的对象。

    Clock 时钟
    Clock类提供了访问当前日期和时间的方法,Clock是时区敏感的,可以用来取代 System.currentTimeMillis() 来获取当前的微秒数。某一个特定的时间点也可以使用Instant类来表示,Instant类也可以用来创建老的java.util.Date对象。

    Clock clock = Clock.systemDefaultZone();
    long millis = clock.millis();
    Instant instant = clock.instant();
    Date legacyDate = Date.from(instant);   // legacy java.util.Date
    

    ...

    Annotation 注解

    在Java 8中支持多重注解

    以上特性可以满足java日常开发了,其他特性个人觉得可以直接引入scala开发包,使用scala.

    相关文章

      网友评论

          本文标题:jdk8

          本文链接:https://www.haomeiwen.com/subject/skxrfxtx.html