java8新特性介绍

来源:互联网 发布:java怎么调试错误 编辑:程序博客网 时间:2024/04/25 00:33

Lambda Exception

Lambda被很多使用高级语言如scala的人所熟知。在程序中,一个Lambda表达式(或函数)仅仅是一个匿名函数,即一个没有名字没有边界标识符的函数。直接卸载需要的地方,通常作为其他函数的参数。

Lambda表达式的基础语法:

either(parameters) -> expressionor(parameters) -> {statements;}or() -> expression

一个典型的Lambda表达式的例子如下:

(x, y) -> x + y // 这个函数有两个参数,并且返回了相加值

Lambda表达式的写法

  1. Lambda表达式可以有0个、1个或多个参数
  2. 参数的类型被直接声明或者通过上下文推断
  3. 多个参数必须包含在()内并用逗号进行分割。无参使用空()代替。
  4. 当只有一个参数时,如果它的类型能够被推断,不强制使用(),即a -> return a*a。
  5. Lambda表达式的主体可以包含0条、1条或多条语句。
  6. 如果Lambda表达式主体中只有一条语句,则不强制使用{},并且匿名函数的return类型和主体表达式一致。

Functional Interface

功能接口也被称为单个抽象方法的接口(Single Abstract Method interfaces (SAM Interfaces))。就像名字说描述的,它们只允许一个抽象方法在接口中。Java 8 引入了一个注解@FunctionalInterface,能够在你的注解的接口违反了功能接口的约定时报编译器错误。

一个典型的功能接口例子:

@FunctionalInterfacepublic interface MyFirstFunctionalInterface {    public void firstWork();}

请注意一个功能接口即使在省略了@FunctionalInterface注解的情况下依然有效,此注解仅是通知编译器强制该接口仅能有一个抽象方法。

同样,默认方法如果不是抽象的,你能自由的向你的功能接口中添加你想要的默认方法。

另一个需要记住的重点是如果一个接口声明的抽象方法重写了java.lang.Object的public方法。也不计入接口的抽象方法计数中,因为任何接口的实现也会实现java.lang.Object。例如,下面完全有效的功能接口

@FunctionalInterfacepublic interface MyFirstFunctionalInterface{    public void firstWork();    @Override    public String toString();                //Overridden from Object class    @Override    public boolean equals(Object obj);        //Overridden from Object class}

Default Methods

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()方法的行为定制。它可以提供它自己定制的方法的实现和重写。

Streams

介绍另一个重要的改动点:Java 8 Stream API。它提供了一个能以各种方式(过滤、转换、或者其他应用程序可能会使用的方式)处理一组数据的机制。

Java 8 StreamAPI支持不同类型的迭代。只需要你简单的定义一组元素去处理,每一个元素要执行的操作,以及这些操作的输出存储到哪里。

一个streamAPI的例子。在这个例子中元素是字符串,并且你想要移除某些前缀的文本。

List<String> items;String prefix;List<String> filteredList = items.stream().filter(e -> (!e.startsWith(prefix))).collect(Collectors.toList());

Date/Time API Changes

新的日期和时间APIS/classes(JSR-310),也被称为ThreeTen,一种简单的在java应用中处理日期的方式。

Dates

Date类已经被废弃了。新的准备替代日期类的类是LocalDate,LocalTime,LocalDateTime
1. LocalDate代表日期,不代表时间或时区;
2. LocalTime代表时间,不代表日期或时区
3. LocalDateTime代表日期-时间,不代表时区
如果你想要使用带有时区信息的日期功能,那么Lambda提供给你额外的3个类,与上面提到的很类似。OffsetDate,OffsetTime,OffsetDateTime。时区补偿能使用“+05:30”或者“Europe/Paris”的格式代表。这是通过使用另一个类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"));

Timestamp and Duration

用于表示特定时间戳的类需要使用InstantInstant类表示一个纳秒精度的瞬时时间。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));

翻译来源:https://howtodoinjava.com/java-8-tutorial/