Java 8于2014年初公布。本文列出了重要的 Java 8 个性,并提供了 lambda 表达式、Java 流、函数式接口、接口默认办法和日期工夫 API 更改等性能的代码示例。

1. Lambda表达式

应用Scala的同学曾经很相熟Lambda表达式了。在Java编程语言中,Lambda表达式只是一个匿名函数,就是没有名称并且没有任何修饰符的函数。

1.1 lambda语法

lambda 表达式的根本语法:

//如果 lambda 表达式的注释具备单个语句,则能够不要大括号//并且匿名函数的返回类型与注释表达式的返回类型雷同。(parameters) -> expression// 当注释中有多个语句时,这些语句必须括在大括号中。(parameters) -> { statements; }//空括号用于示意一组空参数 () -> expression

例如:

//这个lambda表达式接管两个参数并返回它们的和(x, y) -> x + y  

下面这个例子能够作为两个整型数字相加,也能够用于连贯两个字符串,Java会依据上下文主动进行类型匹配。

1.2 lambda编写规定

  • lambda 表达式能够有零个、一个或多个参数。
  • 参数的类型能够显式申明,也能够从上下文中推断进去。
  • 多个参数括在小括号中,并用逗号分隔。空括号用于示意一组空参数。
  • 当只有单个参数时,如果推断出其类型,则不用应用括号。
  • lambda 表达式的主体能够蕴含零个、一个或多个语句。
  • 如果 lambda 表达式的注释具备单个语句,则能够不要大括号,并且匿名函数的返回类型与注释表达式的返回类型雷同。当注释中有多个语句时,这些语句必须括在大括号中。

2. 函数式接口

函数式接口就是只有一个形象办法的接口,接口只容许有一个形象办法。

Java 8引入了新的注解@FunctionalInterface,咱们能够应用它来给出编译时谬误,测验性能接口是否违反了规约。

2.1 示例

//可选注解,也能够不写注解@FunctionalInterfacepublic interface MyFirstFunctionalInterface {    public void onlyOneMethod();}

即便省略正文@FunctionalInterface,函数式接口也是无效的。它仅用于告诉编译器在接口内强制施行单个形象办法。

另外,因为默认办法不是形象办法,其有一个默认实现,所以是合乎函数式接口的定义的。

要记住的另一个关键点是,如果函数接口笼罩了基类(java.lang.Object)的公共办法之一,则该办法也不计入接口的形象办法总数,因为该接口的任何实现都将具备来自(java.lang.Object)或其余中央的实现。

上面给出的是一个齐全无效的性能接口:

@FunctionalInterfacepublic interface MyFirstFunctionalInterface {    public void onlyOneMethod();     @Override    public String toString();               @Override    public boolean equals(Object obj); }

3. 默认办法

Java 8容许咱们在接口中增加非形象办法。这些办法必须申明为default办法。Java 8 中引入默认办法,以便更好的应用 lambda 表达式的性能。

默认办法使咱们可能为库的接口引入新性能,并确保与为这些接口的旧版本编写的代码的二进制兼容性。

让咱们通过一个例子来了解:

public interface Moveable {    default void move(){        System.out.println("I am moving");    }}

Moveable接口定义了一个move()办法,并提供了一个默认的实现。如果任何类实现此接口,则它不须要实现本人的move()办法,它能够间接调用实例后的move()办法。

例如:

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

如果类违心自定义move()办法的行为,那么它能够提供本人的自定义实现并重写该move()办法。

4. Java流

Java8另一个重大变动是引入了流,它提供了一种机制,用于以各种形式解决数据,包含过滤、转换或可能对应用程序有用的任何其余形式。

Java 8 中的 流(Streams) API 反对不同类型的迭代,在该迭代中,咱们定义了要解决的项集、要对每个项执行的操作以及要存储这些操作的输入地位。

4.1 示例

在上面这个示例中,咱们想要删除前缀有str的数据:

package cn.dayangshuo;import java.util.Arrays;import java.util.List;import java.util.stream.Collectors;/** * @author DAYANG */public class StreamTest {    public static void main(String[] args) {        List<String> items = Arrays.asList("str123", "dayang", "大阳");        String prefix = "str";        List<String> filteredList = items.stream()                .filter(e -> (!e.startsWith(prefix)))                .collect(Collectors.toList());        filteredList.forEach(System.out::println);    }}//打印内容://dayang//大阳

5. Java8工夫/日期API更改

新的日期和工夫 API/类 (JSR-310),也称为 ThreeTen,只是扭转了咱们在 java 应用程序中解决日期的形式。

5.1 日期类/时区类

Data类曾经过期了。用于替换 Date 类的新类是 LocalDate、LocalTime和LocalDateTime

  • LocalDate:示意一个日期,没有工夫或时区的信息
  • LocalTime:示意一个工夫,没有日期或时区的信息
  • LocalDateTime示意日期和工夫,没有时区信息

如果咱们想将日期性能与时区信息一起应用,那么 Lambda 为咱们提供了额定的三个类,相似于下面的一个类,即OffsetDate、OffsetTime 和OffsetDateTime。

示例:

//此刻日期LocalDate localDate = LocalDate.now();//工夫LocalTime localTime = LocalTime.of(12, 20);//此刻日期工夫LocalDateTime localDateTime = LocalDateTime.now(); //2017-03-13T11:28:29.247+08:00:东八区工夫OffsetDateTime offsetDateTime = OffsetDateTime.now();//2017-03-13T04:28:29.248+01:00[Europe/Paris]:欧洲巴黎工夫ZonedDateTime zonedDateTime = ZonedDateTime.now(ZoneId.of("Europe/Paris"));

5.2 工夫戳和持续时间类

为了示意任何时刻的特定工夫戳,须要应用的类是 Instant。该类示意精确度为纳秒的霎时。

示例:对Instant与另一个Instant进行比拟的操作,并增加或减去一些工夫

//2017-03-13T03:38:57.134ZInstant instant = Instant.now();//2017-03-13T03:38:57.134ZInstant instant1 = instant.plus(Duration.ofMillis(5000));//2017-03-13T03:38:47.134ZInstant instant2 = instant.minus(Duration.ofMillis(5000));//2017-03-13T03:38:42.134ZInstant instant3 = instant.minusSeconds(10);

Duration类(持续时间)是Java8中首次呈现的全新概念。它示意两个工夫戳之间的时间差。Duration解决一小段时间单位,如毫秒、秒、分钟和小时。它们更适宜与利用程序代码交互。

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

解决更大的工夫距离,能够应用Period

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