Java8介绍
Java8发布于2014早些时候,主要包括以下几个方面
- Lambda表达式
- 函数式接口
- 默认方法
- 流
- 日期/时间 API的变化
Lambda表达式
对于我们中一些使用类似Scala语言的来说,Lambda表达式并不是未知的。在Java语言中,Lambda表达式(或者函数)只是一个匿名函数,一个没有名字没有标识符的函数。他们可以写在任何需要的地方,通常作为一些其他函数的参数。
基本语法:
either
(parameters) -> expression
or
(parameters) -> { statements; }
or
() -> expression
典型应用:
(x, y) -> x + y //这个函数返回两个数的和
请注意x和y的类型,该方法可用用在很多地方。x和y的参数类型也可以是int,Integer,也可以是简单的String。基于上下文,它将添加两个整数或拼接两个字符串
编写Lambda表达式的基本原则
- 一个lambda表达式可以有0个,1个或者多个参数。
- 参数的类型可以显示声明,也可以从上下文中推。
- 多个参数必需用括号括起来,用逗号分隔。空括号用于表示一组空参数。
- 当存在单个参数时,如果推断其类型,则不强制使用括号.就像这样 -> return a*a。
- lambda 表达式的主体可以包含零、一个或多个语句。
- 当匿名函数的返回类型与正文表达式的返回类型相同时,不强制 lambda表达式正文必须具有单个大括号。当正文中有多个语句时,必须用大括号括起来.
函数式接口
函数式接口又被称作单独的抽象方法接口(SAM 接口)。顾名思义,他们允许里边正好一个抽象方法。Java8引入了注释,@FunctionalInterface,用来当已注释的接口违法该规定时,返回编译错误。
一个典型的函数式接口的例子:
@FunctionalInterface
public interface MyFirstFunctionalInterface {
public void firstWork();
}
请注意,即使省略@FunctionalInterface注释,功能接口也有效。它仅用于通知编译器在接口内强制实施单一抽象方法。
此外,由于默认方法不是抽象的,因此您可以随意将默认方法添加到函数式接口中。
另一个需要记住的要点是,如果接口声明一个抽象方法,重写 java.lang.object 的一种公共方法,那也不会计入接口的抽象方法,因为接口的任何实现都将从 java.lang.object.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
}
默认方法
Java8允许在接口中添加非抽象方法。这些方法可以被声明为默认方法。在java 8 中引入了默认方法,以启用 lambda 表达式的功能。
通过默认方法,您可以向库的接口添加新功能,并确保与为这些接口的旧版本编写的代码进行兼容。
让我来理解这个例子:
public interface Moveable {
default void move(){
System.out.println("I am moving");
}
}
Moveable interface defines a method move() and provided a default implementation as well. If any class implements this interface then it need not to implement it’s own version of move() method. It can directly call instance.move(). e.g.
Moveable接口定义了一个move()方法并且提供了一个默认的实现。如果任何类实现该接口,就不用再自己实现该方法。可以直接调用Mmove()方法。
public class Animal implements Moveable{
public static void main(String[] args){
Animal tiger = new Animal();
tiger.move();
}
}
Output: I am moving
如果类愿意自定义 move() 方法的行为,则可以提供其自己的自定义实现并重写该方法。
Java8 流
另一个主要的变化是Java 8的流 API,它提供了一种机制,用于以各种方式处理一组数据,包括筛选、转换或任何其他可能对应用程序有用的方法
Java 8 中的流 API 支持不同类型的迭代,其中您只需定义要处理的一组数据项、要对每个项执行的操作以及存储这些操作的输出的位置。
一个流API的例子。在这个例子中,数据项String的集合,然后您希望删除以"prefix"开头的数据。
List<String> items;
String prefix;
List<String> filteredList = items.stream().filter(e -> (!e.startsWith(prefix))).collect(Collectors.toList());
这里的items.stream()代表,我们希望用流API来处理集合中的数据
Java 8 日期/时间 API的改变
新的日期和时间类,也被称为"ThreeTen",改变了您在 java 应用程序中处理日期的方式。
日期
Date class has even become obsolete. The new classes intended to replace Date class are LocalDate, LocalTime and LocalDateTime.
日期类甚至已过时。打算替换日期类的新类是LocalDate, LocalTime和LocalDateTime。
- LocalDate类代表日期. 没有时间或时区的表示形式
- LocalTime类代表时间. 没有时间或时区的表示形式
- LocalDateTime类代表日期时间. 没有时区的表示形式
If you want to use the date functionality with zone information, then Lambda provide you extra 3 classes similar to above one i.e. OffsetDate, OffsetTime and OffsetDateTime. Timezone offset can be represented in “+05:30” or “Europe/Paris” formats. This is done via using another class i.e. ZoneId.
如果要将日期功能与区域信息一起使用,则 Lambda 会为您提供类似于上述 3 个类的额外类,即OffsetDate、OffsetTime和OffsetDateTime。时区偏移量可以表示为"+05:30"或"欧洲/巴黎"格式。
这是通过使用另一个类(即 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"));
时间戳和持续时间
为了表示特定的时间戳 ant,任何时刻,需要使用的类是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));
网友评论