这个系列主要罗列了 Java 8 的重要功能,并提供了此发行版中引入的示例。
Java SE 8 于 2014 年初发布,是目前在生产环境中使用最多,应用最广发的版本。在 Java 8 中,最受关注的功能是 lambda 表达式。除此之外,它还具有许多其它的功能,比如默认方法、流 API 和 新的日期/时间 API。下面让我们通过示例来了解 Java 8 中的这些新功能。
目录
1.Lambda 表达式
2.功能接口
3.默认方法
4.流
5.日期/时间 API 更改
1.Lambda 表达式
Lambda 表达式对于使用 Scala 等其他流行语言的人并不陌生。在 Java 编程语言中,Lambda 表达式(或函数)只是一个匿名函数,即不带名称且不受标识符限制的函数。它们只有在被需要的地方出现,一般作为其他函数的参数。
lambda 表达式的基本语法:
either
(parameters) -> expression
or
(parameters) -> { statements; }
or
() -> expression
典型的 lambda 表达式实例如下所示:
( x , y )-> x + y
请注意,根据 x 和 y 的数据类型,方法可能在多个地方使用。参数可以匹配 int 、Integer 和 String。根据上下文,它将累加整数或连接两个字符串。
编写 Lambda 表达式的规则
1.Lambda 表达式可以具有零个,一个或多个参数;
2.参数的类型可以显示声明,也可以从上下文推断出来;
3.多个参数强制用小括号括起来,并用逗号隔开。空括号用于表示空参数集;
4.当有单个参数时,如果推断出类型,则不强制使用括号,例如 a -> return a*a
5.Lambda 表达式的主体可以包含零个,一个或多个。
6.如果 Lambda 表达式的主体具有单个语句,则不必使用大括号,并且匿名函数的返回类型与主体表达式的类型相同。如果主体中的语句超过一个,则必须用大括号括起来。
2.Functional interface
Functional interface 也称为 单一抽象方法接口(SAM接口)。顾名思义,它们允许内部有一种抽象方法。Java 8 引入了一个新注解@FunctionalInterface,当你的接口定义违反功能接口的约定时,该注解可用于避免编译时的错误。
典型的功能接口示例:
@FunctionalInterface
public interface MyFirstFunctionalInterface{
public void firstWork();
}
请注意,即使省略了 @FunctionalInterface ,功能接口依然有效。该注解仅用于通知编译器在接口内部强制执行单个抽象方法。另外,由于默认方法不是抽象的,因此可以随意向功能接口添加任意数量的默认方法。
要记住另一个重点,如果接口声明的抽象方法覆盖的公共方法之一(java.lang.Object),则该方法不会计入接口的抽象方法数量,因为该接口的任何实现都将具有来自 java.lang.Object
其他地方的实现。例如,下面是完全有效的功能接口。
@FunctionalInterface
public interface MyFirstFunctionalInterface{
public void firstWork();
@override
public String toString(); //Override from Object class
@override
public boolean equals(Object obj); //Override from Object class
}
3.Default Method
Java 8允许我们在接口添加非抽象方法,这些方法必须声明为默认方法。Java 8中引入了默认方法以启用 lambda 表达式的可能。
默认方法让我们可以向库的的接口添加新功能,并确保与较早版本编写的代码兼容。让我们来看一个例子:
public interface Moveable {
default void move() {
System.out.println("I am moving!")
}
}
Moveable 接口定义了一种方法,move() 提供了默认实现。如果有任何类实现此接口,则无需实现它自己的 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() 方法的行为,那么它可以提供自己的自定义实现并覆盖该方法。
4.Java 8 stream
Java 8 stream API 引入了另一个重要的变化,它提供了一种以多种方式处理一组数据的机制,这些方式包括过滤、转换等操作。
Java 8中的 Stream API 支持不同类型的迭代,我们可以在其中简单的定义要处理的数据项,对每个数据执行操作,并存储操作的结果。
让我们来看一个示例。在这个示例中,item
是String
类型的集合,我们要删除以某些文本开头的item
。
List<String> items;
String prefix;
List<String> filteredList = items.stream().filter(e -> (!e.startsWith(prefix))).collect(Collections.toList());
此处 item.stream()
表示我们希望item
使用Stream API处理列表中的数据。
Java 8 Date/Time API 修改
新的 Date/Time API 类 (JSR-310),也称为 ThreeTen ,仅修改了在 Java 应用程序中处理日期的方式。
Date
Date
类基本已经过时了,取而代之的是LocalDate
、LocalTime
和 LocalDateTime
。
1.
LocalDate
仅代表一个日期,既不是表示时间也没有时区;
2.LocalTime
仅代表一个时间,既不是表示日期也没有时区;
3.LocalDateTime
仅代表一个日期和时间,没有时区;
如果希望使用区域信息的日期功能,那么Lambda
为我们提供了三个额外的类来实现,分别是OffsetDate
、OffsetTime
和OffsetDateTime
。时区偏移可以用"+05:50"或"Europe/Paris"来表示,这需要用到ZoneId
类。
LocalDate localDate = LocalDate.now();
LocalTime localTime = LocalTime.of(12 , 20);
LocalDateTime localDateTime = LocalDateTime.now();
OffsetDateTime offsetDateTime = OffsetDateTime.now();
ZoneDateTime zoneDateTime = ZoneDateTime.now( ZoneId.of("Europe/Paris"));
Timestamp and Duration
为了随时表示特定的时间戳,我们需要使用类 Instant
。Instant
表示纳秒级精度的瞬间时间,支持包括与另一个Instant
比较以及增加或减少持续时间。
Instant instant = Instant.now();
Instant instant1 = instant.plus(Duration.ofMillis(5000));
Instant instant2 = instant.minus(Duration.ofMillis(5000));
Instant instant3 = instant.minusSecond(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));
好了,本次分享就到这里,有任何问题欢迎在评论中留言。
全文毕
欢迎关注微信公众号:Javall咖啡屋
每天更新各种互联网技术(前后端、数据库、中间件、设计模式、数据结构、算法)学习心得体会
网友评论