Java 8 | 简介

作者: 懒癌正患者 | 来源:发表于2018-04-12 22:12 被阅读22次

    Java 10 都已经出来了,为啥还在学 Java 8 呢?

    首先是我自己没有系统的学习 Java 8 的新特性,只是看博客的时候学到那些是那些。

    其次呢,2017年9月,Oracle 将 Java 大版本周期从原来的 2-3 年,调整成每半年发布一个大的版本。而版本号仍延续原来的序号,即 Java 8、Java 9、Java 10、Java 11.....

    但和之前不一样的是,同时还有一个版本号来表示发布的时间和是否为 LTS(长期支持版本),比如 Java 10 对应 18.3。如下示例:

    /jdk-10/bin$ ./java -version
    
    openjdk version "10" 2018-03-20
    
    OpenJDK Runtime Environment 18.3 (build 10+46)
    
    OpenJDK 64-Bit Server VM 18.3 (build 10+46, mixed mode)
    

    需要注意的是 Java 9 和 Java 10 都不是 LTS 版本。和过去的 Java 大版本升级不同,这两个只有半年左右的开发和维护期。而未来的 Java 11,也就是 18.9 LTS,才是 Java 8 之后第一个 LTS 版本(得到 Oracle 等商业公司的长期支持服务)。

    所以等 Java 11 出来了再去学习新的特征也不迟,不过尝鲜的小伙伴可以了解一下 Java 9 和 Java 10 添加了那些特征。这里我还是老老实实啃一下 Java 8 吧。

    Java 8中我们谈论最多的就是 lambda 表达式了,当然它还有其他的特性,比如 默认方法,stream API 和 新的 Date/Time API 等等。下面我们先用例子来了解一下 Java 8 的一下特性吧。

    Lambda 表达式

    在编程使用上,Lambda 表达式就像是匿名函数一样,我们将Lambda 表达式当做一个参数传递给另一个函数,是不是很神奇。但是这个特性在 Scala 中已经很常见了。

    Lambda 表达式的基本语法

    (parameters) -> expression
    或者
    (parameters) -> { statements; }
    或者
    () -> expression
    

    举个例子

    (x, y) -> x + y // 这个函数接受2个参数,并且返回2个参数的和
    

    书写 Lambda 表达式的规则

    1. 一个 Lambda 表达式可以有 0个,1个或者更多的参数。
    2. 参数的类型可以显示声明出来,也可以通过代码推断出来参数的类型。
    3. 多个参数必须放在 () 中并用 , 分隔 比如这样 (param1, param2, param3),空的() 表示不接受任何参数。
    4. 当只有一个参数的时候,如果参数类型能够被推断出来,可以不必使用(),比如 a -> a * a。
    5. lambda 书写语句部分能够有 0条,1条或多条语句。
    6. 当 lambda 书写语句部分只有1条语句时,可以不用书写 {},并且这个匿名函数的返回值就是表达式语句的结果。当书写语句部分不止1条语句时必须使用 {} 将这些语句包裹进来。

    函数接口

    函数接口也称为 Single Abstract Method interfaces (SAM Interfaces)。从名字可以看出,这种接口只允许有1个抽象方法。Java 8 提供了 @FunctionalInterface 注解,当使用这个注解标识一个接口的时候,这个接口如果不符合函数接口的规定,编译器会报错。

    举个例子

    @FunctionalInterface
    public interface MyFirstFunctionalInterface {
        public void firstWork();
    }
    

    注意,即使忽略@FunctionalInterface注释,函数接口也是有效的。 它仅用于通知编译器在接口内强制执行单一抽象方法。

    因为默认方法不是抽象方法,所以可以在函数接口中任意添加默认方法(你开心就好)。

    另外需要注意,一个接口声明了一个抽象方法重载了 java.lang.Object 类中的 public 方法,这个方法不算作接口的抽象方法,因为这个接口的任何实现都会有这些方法(Object 中声明的 public 方法)的实现,这些实现可能来自于 java.lang.Object 或其他类。例如下面这个函数接口任然合理。

    @FunctionalInterface
    public interface MyFirstFunctionalInterface{
        public void firstWork();
     
        @Override
        public String toString();                //Overridden from Object class
     
        @Override
        public boolean equals(Object obj);        //Overridden from Object class
    }
    

    默认方法

    Java 8 允许在接口中添加非抽象的方法。这些方法必须声明为默认方法。在 Java 8 中引入了默认方法来启用 lambda 表达式的功能。

    默认方法使您可以向库的接口添加新功能,并确保与为这些接口的旧版本编写的代码的二进制兼容性。最典型的例子就是 Java 8 中的 List 接口。

    举个例子

    public interface Moveable {
        default void move(){
           log.info("I am moving");
        }
    }
    

    Moveable 接口定义了move()方法并提供了 move() 方法的默认实现,如果任何类实现了 Moveable 这个接口,这个类不必实现 move() 方法,可以直接调用 instance.move() 方法。

    public class Animal implements Moveable {
        public static void main(String[] args){
            Animal tiger = new Animal();
            tiger.move();
        }
    }
      
    Output: I am moving
    

    如果类想要自己实现 move() 方法也可以重载这个方法。

    Streams

    另外一个主要改变就是 Java 8 的 Streams API,Stream API 提供了对数据集处理的一种机制,可以对数据集进行过滤、转换或者对应用程序可能有用的任何其他方式。

    举例说明, items 是 String 的集合,我们移除其中一些以某些前缀开始的项。

    List<String> items;
    String prefix;
    List<String> filteredList = items.stream().filter(e -> (!e.startsWith(prefix))).collect(Collectors.toList());
    

    items.stream() 表示我们希望使用 Stream API 来处理这个集合。

    Date/Time API 的变化

    Dates

    Date 类已经过时啦,在 Java 8 中使用 LocalDate, LocalTime and LocalDateTime 来替代原来的 Date 类。

    1. LocalDate 代表日期。没有时间或时区的含义。
    2. LocalTime 掉代表时间。没有日期或时区的含义。
    3. LocalDateTime 代表 日期和时间。没有时区的含义。

    如果想使用日期并且带上时区的信息, Lambda 提供可另外 3 个相似的类 OffsetDate, OffsetTime and OffsetDateTime。时区可以用 “+05:30” 或者 “Europe/Paris” 代表。可以使用 ZoneId 来完成。

    LocalDate localDate = LocalDate.now();
    LocalTime localTime = LocalTime.of(12, 20);
    LocalDateTime localDateTime = LocalDateTime.now();
    OffsetDateTime offsetDateTime = OffsetDateTime.now();
    ZonedDateTime zonedDateTime = ZonedDateTime.now(ZoneId.of("Europe/Paris"));
    
    ====
    输出
    12:20
    2018-04-12T22:21:01.597
    2018-04-12T22:21:01.598+08:00
    2018-04-12T16:21:01.601+02:00[Europe/Paris]
    

    Timestamp and Duration

    为了随时表示特定时间戳,需要使用 Instant 类。Instant 类表示一个瞬时,精度精确到了纳秒。 可以在 Instant 上进行加或减一段时间生成一个新的 Instant 类。

    Instant instant = Instant.now();
    Instant instant1 = instant.plus(Duration.ofMillis(5000));
    Instant instant2 = instant.minus(Duration.ofMillis(5000));
    Instant instant3 = instant.minusSeconds(10);
    

    Duration 类是 Java 语言中首次引入的全新概念。 它表示两个时间戳之间的时间差。

    Duration duration = Duration.ofMillis(5000);
    duration = Duration.ofSeconds(60);
    duration = Duration.ofMinutes(10);
    

    Duration 类适合处理诸如毫秒,秒,分钟和小时等小单位时间,这更世界与程序代码交互,如果想与人类进行交互,最好使用更大的时间单位,这是可以使用 Period 类来代表。

    Period period = Period.ofDays(6);
    period = Period.ofMonths(6);
    period = Period.between(LocalDate.now(), LocalDate.now().plusDays(60));
    

    相关文章

      网友评论

        本文标题:Java 8 | 简介

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