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));