乐趣区

关于java:Java8新特性及代码示例

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));
退出移动版