Java8特性汇总

  |   0 评论   |   0 浏览

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 示例

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

即使省略注释@FunctionalInterface,函数式接口也是有效的。它仅用于通知编译器在接口内强制实施单个抽象方法。

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

要记住的另一个关键点是,如果函数接口覆盖了基类(java.lang.Object)的公共方法之一,则该方法也不计入接口的抽象方法总数,因为该接口的任何实现都将具有来自(java.lang.Object)或其他地方的实现。

下面给出的是一个完全有效的功能接口:

 @FunctionalInterface
 public 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.134Z
 Instant instant = Instant.now();
 //2017-03-13T03:38:57.134Z
 Instant instant1 = instant.plus(Duration.ofMillis(5000));
 //2017-03-13T03:38:47.134Z
 Instant instant2 = instant.minus(Duration.ofMillis(5000));
 //2017-03-13T03:38:42.134Z
 Instant 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));

转自https://zhuanlan.zhihu.com/p/480165849


标题:Java8特性汇总
作者:michael
地址:https://blog.junxworks.cn/articles/2022/09/29/1664430476747.html