JDK1.8 的 8 种新特性(附代码示例)

目录

一、Lambda 表达式

1.1 Lambda表达式的形式

1.2 Lambda表达式的组成部分

1.3 Lambda表达式示例

二、Stream API

2.1 Stream API特点

2.2 Stream API 操作类型

2.3 Stream API 使用示例

三、接口的默认方法和静态方法

3.1 默认方法(Default Method)

3.2 静态方法(Static Method)

四、函数式接口

4.1 函数式接口特点

4.2 函数式接口的示例

五、Optional 类

5.1 Optional类特点和用法

5.2 Optional类使用示例

六、新的日期和时间 API

6.1 新的日期和时间 API 核心类

6.2 新的日期和时间 API 特点和优势

6.3 新的日期和时间 API 示例

七、CompletableFuture 类

7.1 CompletableFuture 特点和用法

7.2 CompletableFuture 类使用示例

八、新的重复注解和类型注解

8.1 重复注解(Repeated Annotations)

8.2 类型注解(Type Annotations)


Java 8是一个重要的版本,引入了许多新特性和改进,下面是一些显著的新特性和改进的介绍。

一、Lambda 表达式

Lambda表达式是Java 8引入的一项重要特性,它提供了一种简洁、便利的语法来实现函数式编程。Lambda表达式可以看作是一个匿名函数,它允许将函数作为参数传递给方法,或者在集合操作中以声明性的方式进行处理。

1.1 Lambda表达式的形式

Lambda表达式的一般形式如下:

(parameters) -> expression
    
或者
    
(parameters) -> { statements; }
1.2 Lambda表达式的组成部分

Lambda表达式由以下几个部分组成:

  • 参数列表:Lambda表达式可以接受零个或多个参数。
  • 箭头符号(->):箭头符号将参数列表和Lambda表达式的主体分隔开。
  • Lambda主体:可以是一个表达式或者一段代码块。如果是一个表达式,则不需要使用大括号,如果是一段代码块,则需要使用大括号。
1.3 Lambda表达式示例
  • Lambda表达式作为函数式接口的实例:
// 定义一个函数式接口
interface MyInterface {
    void myMethod(String s);
}

public class Main {
    public static void main(String[] args) {
        // 使用Lambda表达式实现函数式接口
        MyInterface myInterface = (String s) -> {
            System.out.println("Hello, " + s);
        };
        // 调用方法
        myInterface.myMethod("world");
    }
}
  • Lambda表达式作为参数传递给方法:
import java.util.ArrayList;
import java.util.List;

public class Main {
    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        list.add("apple");
        list.add("banana");
        list.add("orange");

        // 使用Lambda表达式遍历集合
        list.forEach(item -> System.out.println(item));
    }
}
  • Lambda表达式简化Comparator的使用:
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

public class Main {
    public static void main(String[] args) {
        List<String> list = Arrays.asList("apple", "banana", "orange");
        
        // 使用Lambda表达式排序集合
        Collections.sort(list, (String s1, String s2) -> s1.compareTo(s2));
        
        // 输出排序后的集合
        list.forEach(item -> System.out.println(item));
    }
}

二、Stream API

Stream API 是 Java 8 中引入的一个重要特性,它提供了一种便利和高效的方式来处理集合数据。Stream API 允许以声明性的方式对集合进行各种操作,如过滤、映射、排序、聚合等,而不需要显式地编写循环和条件语句。

2.1 Stream API特点
  • 流式操作:Stream API 使用流式操作,允许对数据进行流式处理,逐个处理每个元素而不是一次性处理整个集合。
  • 链式调用:Stream API 中的操作可以进行链式调用,使得代码更加简洁和易读。
  • 惰性求值:Stream API 中的操作通常是惰性求值的,只有在终端操作被调用时才会触发中间操作的执行,这有助于提高性能。
  • 支持并行:Stream API 支持并行操作,可以利用多核处理器进行并行计算,提高程序的性能。
2.2 Stream API 操作类型

Stream API 中的操作可以分为两种类型:中间操作和终端操作。

  • 中间操作用于对流中的元素进行处理和转换,如过滤、映射、排序等。
  • 终端操作用于触发流的执行,并产生最终的结果,如收集、计数、查找等。
2.3 Stream API 使用示例
  • 过滤和映射:
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

public class Main {
    public static void main(String[] args) {
        List<String> list = Arrays.asList("apple", "banana", "orange", "grape", "watermelon");
        
        // 过滤长度大于5的字符串
        List<String> filteredList = list.stream()
                                        .filter(str -> str.length() > 5)
                                        .collect(Collectors.toList());
        System.out.println("Filtered list: " + filteredList);
        
        // 映射转换大写并排序
        List<String> upperCaseList = list.stream()
                                         .map(String::toUpperCase)
                                         .sorted()
                                         .collect(Collectors.toList());
        System.out.println("Uppercase and sorted list: " + upperCaseList);
    }
}

  • 计数和查找:
import java.util.Arrays;
import java.util.List;

public class Main {
    public static void main(String[] args) {
        List<String> list = Arrays.asList("apple", "banana", "orange", "grape", "watermelon");
        
        // 计算集合中长度为5的字符串数量
        long count = list.stream()
                        .filter(str -> str.length() == 5)
                        .count();
        System.out.println("Number of strings with length 5: " + count);
        
        // 查找第一个以字母"g"开头的字符串
        String foundString = list.stream()
                                .filter(str -> str.startsWith("g"))
                                .findFirst()
                                .orElse(null);
        System.out.println("First string starts with 'g': " + foundString);
    }
}

三、接口的默认方法和静态方法

在Java 8中,接口(Interface)引入了默认方法(Default Method)和静态方法(Static Method)这两个新特性,使得接口具有了更多的灵活性和功能性。这两种方法的介绍如下:

3.1 默认方法(Default Method)
  • 默认方法是在接口中提供的具有默认实现的方法。它允许在不破坏现有实现的情况下,向接口添加新的方法。
  • 默认方法的声明使用 default 关键字,后面跟着方法的实现。默认方法可以被实现类直接继承或者重写,也可以被实现类选择性地覆盖。
  • 默认方法的存在使得接口的修改变得更加容易,可以向现有的接口添加新的功能,而不需要修改所有实现该接口的类。
  • 默认方法的典型应用场景包括扩展接口的功能、提供接口的默认行为等。

示例代码如下:

interface MyInterface {
    default void defaultMethod() {
        System.out.println("This is a default method.");
    }
}
3.2 静态方法(Static Method)
  • 静态方法是在接口中提供的静态方法实现,它可以直接通过接口名来调用,无需实现类的实例。
  • 静态方法的声明使用 static 关键字,后面跟着方法的实现。静态方法不能被实现类覆盖或重写。
  • 静态方法的存在使得接口可以提供一些工具方法或者辅助方法,而不需要为此创建实例。
  • 静态方法的典型应用场景包括提供工具方法、提供工厂方法等。

示例代码如下:

interface MyInterface {
    static void staticMethod() {
        System.out.println("This is a static method.");
    }
}

四、函数式接口

函数式接口是Java 8引入的一个重要概念,它是一个只包含一个抽象方法的接口。函数式接口可以使用Lambda表达式来实例化,从而实现函数式编程的特性。Java 8为函数式接口引入了一个新的注解 @FunctionalInterface,用于标识函数式接口。

4.1 函数式接口特点

函数式接口的主要特点包括:

  • 只包含一个抽象方法:函数式接口只能包含一个抽象方法,但可以包含多个默认方法或静态方法。
  • Lambda表达式实例化:函数式接口可以通过Lambda表达式来实例化,从而实现函数作为参数传递、函数式编程等功能。
  • 简化代码:函数式接口使得代码更加简洁和可读,特别是在处理回调函数、事件处理、集合操作等场景下。
4.2 函数式接口的示例

下面是一个简单的函数式接口的示例:

@FunctionalInterface
interface MyInterface {
    void myMethod();
}

在上面的示例中,MyInterface 是一个函数式接口,它只包含一个抽象方法 myMethod()。使用 @FunctionalInterface 注解标识了该接口是一个函数式接口。

接下来是如何使用Lambda表达式来实例化函数式接口的示例:

public class Main {
    public static void main(String[] args) {
        // 使用Lambda表达式实例化函数式接口
        MyInterface myInterface = () -> System.out.println("Hello, world!");
        
        // 调用函数式接口的抽象方法
        myInterface.myMethod();
    }
}

在上面的示例中,通过Lambda表达式实例化了 MyInterface 函数式接口,并在 myMethod() 方法中输出了 "Hello, world!"。

五、Optional 类

Optional 类是 Java 8 引入的一个重要类,它的目的是解决空指针异常(NullPointerException)问题。Optional 类可以用来包装一个可能为 null 的值,从而避免直接操作 null 值而导致的空指针异常。通过 Optional 类,我们可以更加优雅和安全地处理可能为 null 的值。

5.1 Optional类特点和用法

① 避免空指针异常

使用 Optional 类可以帮助我们更加安全地处理可能为 null 的值,避免出现空指针异常。通过 Optional 类,我们可以对可能为 null 的值进行包装和处理,从而使得代码更加健壮和可靠。

② 方法链操作

Optional 类提供了丰富的方法来进行操作,如 map、flatMap、filter、orElse、orElseGet 等。这些方法可以通过方法链的方式来组合使用,从而实现对包装值的各种操作和转换。

③ 提倡使用 Optional 类

Java 8 开始,官方提倡在返回值可能为 null 的情况下,使用 Optional 类作为方法的返回值类型,以便提醒调用者可能会得到空值,并且鼓励调用者使用 Optional 类来处理返回值。

④ 不鼓励在字段上使用

虽然 Optional 类对于方法的返回值是非常适用的,但是对于字段(成员变量)的使用却不太合适。官方不推荐在字段上直接使用 Optional 类,因为这样可能会增加额外的复杂性。

5.2 Optional类使用示例
import java.util.Optional;

public class Main {
    public static void main(String[] args) {
        // 创建一个包装值为空的Optional对象
        Optional<String> emptyOptional = Optional.empty();
        
        // 创建一个包装非空值的Optional对象
        Optional<String> nonEmptyOptional = Optional.of("Hello, world!");
        
        // 创建一个可能为null的Optional对象
        String str = null;
        Optional<String> nullableOptional = Optional.ofNullable(str);
        
        // 检查Optional对象是否包含值
        System.out.println("Is empty optional? " + emptyOptional.isEmpty()); // true
        System.out.println("Is non-empty optional? " + nonEmptyOptional.isPresent()); // true
        System.out.println("Is nullable optional? " + nullableOptional.isPresent()); // false
        
        // 获取Optional对象中的值
        String value = nonEmptyOptional.get();
        System.out.println("Value: " + value); // "Hello, world!"
        
        // 使用orElse方法获取值,如果值为空则返回默认值
        String defaultValue = nullableOptional.orElse("Default Value");
        System.out.println("Default value: " + defaultValue); // "Default Value"
    }
}

通过 Optional 类,可以更加安全和优雅地处理可能为 null 的值,避免了直接操作 null 值而导致的空指针异常。这使得代码更加健壮和可靠,提高了程序的稳定性和可维护性。

六、新的日期和时间 API

Java 8 引入了全新的日期和时间 API(java.time包),用于取代旧的 Date 和 Calendar 类,提供了更加简洁、易用和功能强大的日期和时间处理功能。

6.1 新的日期和时间 API 核心类
  • LocalDate:用于表示日期,不包含时间和时区信息。
  • LocalTime:用于表示时间,不包含日期和时区信息。
  • LocalDateTime:用于表示日期和时间,不包含时区信息。
  • Instant:表示时间戳,与 Unix 时间类似,精确到纳秒。
  • Duration:表示两个时间点之间的时间间隔。
  • Period:表示两个日期之间的时间间隔,以年、月、日为单位。
  • ZoneId:用于表示时区。
  • ZonedDateTime:带有时区的日期和时间。
6.2 新的日期和时间 API 特点和优势
  • 不可变性:日期和时间类都是不可变的(immutable),保证了线程安全性。
  • 清晰易用:提供了丰富的方法来进行日期和时间的操作和计算,代码更加清晰易读。
  • 丰富的功能:提供了诸如日期加减、格式化、解析、时区转换等丰富的功能,适用于各种日期和时间处理场景。
  • 线程安全:新的日期和时间 API 是线程安全的,可以放心在多线程环境中使用。
6.3 新的日期和时间 API 示例

下面是一些使用新的日期和时间 API 的示例:

import java.time.LocalDate;
import java.time.LocalTime;
import java.time.LocalDateTime;
import java.time.Month;
import java.time.format.DateTimeFormatter;

public class Main {
    public static void main(String[] args) {
        // 获取当前日期
        LocalDate currentDate = LocalDate.now();
        System.out.println("Current Date: " + currentDate);
        
        // 获取当前时间
        LocalTime currentTime = LocalTime.now();
        System.out.println("Current Time: " + currentTime);
        
        // 获取当前日期和时间
        LocalDateTime currentDateTime = LocalDateTime.now();
        System.out.println("Current Date and Time: " + currentDateTime);
        
        // 根据指定日期和时间创建对象
        LocalDate date = LocalDate.of(2022, Month.FEBRUARY, 14);
        LocalTime time = LocalTime.of(12, 30, 0);
        LocalDateTime dateTime = LocalDateTime.of(date, time);
        System.out.println("Custom Date and Time: " + dateTime);
        
        // 格式化日期和时间
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        String formattedDateTime = currentDateTime.format(formatter);
        System.out.println("Formatted Date and Time: " + formattedDateTime);
    }
}

新的日期和时间 API 提供了更加现代化和强大的日期和时间处理功能,使得日期和时间的操作更加简单、直观和安全。它是 Java 8 中一个重要的新增特性,也是 Java 编程中不可或缺的一部分。

七、CompletableFuture 类

CompletableFuture 类是 Java 8 引入的一个重要的异步编程工具,用于支持异步任务的执行和结果处理。它提供了一种简单、灵活和强大的方式来执行异步任务,并支持依赖关系、异常处理、回调函数等功能。CompletableFuture 类可以用于编写高效的并发程序,提高程序的性能和响应性。

7.1 CompletableFuture 特点和用法

CompletableFuture 类的主要特点和用法包括:

① 异步执行

CompletableFuture 类支持异步执行任务,可以通过 supplyAsync()、runAsync() 等静态方法来创建一个异步任务,并返回一个 CompletableFuture 对象,该对象表示了任务的执行状态和结果。

② 依赖关系

CompletableFuture 类支持任务之间的依赖关系,可以通过 thenApply()、thenAccept()、thenCompose() 等方法来构建任务之间的依赖关系,实现任务的串行或并行执行。

③ 异常处理

CompletableFuture 类提供了丰富的方法来处理异步任务的异常情况,如 exceptionally()、handle() 等方法可以处理任务执行过程中抛出的异常,并返回默认值或执行备选操作。

④ 回调函数

CompletableFuture 类支持回调函数的方式来处理异步任务的结果,如 thenApply()、thenAccept()、thenRun() 等方法可以在任务执行完成后自动调用指定的回调函数。

⑤ 组合操作

CompletableFuture 类支持各种组合操作,如 allOf()、anyOf() 等静态方法可以组合多个 CompletableFuture 对象,实现一组任务的并行执行或等待任意一个任务的完成。

⑥ 支持并行

CompletableFuture 类可以利用多核处理器进行并行计算,提高程序的性能和响应性,从而加速任务的执行和结果的获取。

7.2 CompletableFuture 类使用示例

下面是一个简单的示例,演示了如何使用 CompletableFuture 类来执行异步任务和处理任务的结果:

import java.util.concurrent.CompletableFuture;

public class Main {
    public static void main(String[] args) {
        // 异步执行任务
        CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
            // 模拟耗时任务
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return "Task Result";
        });
        
        // 处理任务的结果
        future.thenAccept(result -> {
            System.out.println("Task Result: " + result);
        });
        
        // 主线程等待异步任务完成
        try {
            future.join();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

通过 CompletableFuture 类,可以更加灵活和高效地执行异步任务,并实现对任务结果的处理和管理。可以编写高响应性和高性能的并发程序,提高了程序的可扩展性和并发能力。

八、新的重复注解和类型注解

Java 8 引入了新的重复注解和类型注解,这两个特性为Java的注解提供了更多的灵活性和功能性。

8.1 重复注解(Repeated Annotations)

重复注解允许在同一个元素上多次使用相同的注解,而不需要使用容器注解的方式。在 Java 8 之前,如果要在同一个元素上使用多个相同的注解,必须使用容器注解(Container Annotation),将多个注解包装在一个容器注解中。而在 Java 8 中,可以直接使用相同的注解多次注解同一个元素。

示例代码如下:

import java.lang.annotation.*;

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Repeatable(MyAnnotations.class)
public @interface MyAnnotation {
    String value();
}

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface MyAnnotations {
    MyAnnotation[] value();
}

在上面的示例中,MyAnnotation 注解使用 @Repeatable 注解声明可重复,然后通过 MyAnnotations 注解来容纳多个 MyAnnotation 注解。

8.2 类型注解(Type Annotations)

类型注解允许在任何类型使用的地方使用注解,例如类、接口、字段、方法、参数、局部变量等。在 Java 8 之前,注解只能应用于声明的语法结构上,而类型注解允许在任何类型使用的地方使用注解,从而提供了更加精细的注解控制。

示例代码如下:

import java.lang.annotation.*;

@Target(ElementType.TYPE_PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyTypeAnnotation {}

class MyClass<@MyTypeAnnotation T> {
    public void method(@MyTypeAnnotation String str) {
        @MyTypeAnnotation String localVar = "local";
    }
}

在上面的示例中,@MyTypeAnnotation 注解被应用于类型参数 T、方法参数 str、局部变量 localVar,从而实现了对这些类型的注解控制。

重复注解和类型注解为Java的注解机制增加了更多的灵活性和功能性,使得注解在代码中的应用更加丰富和广泛。它们为开发者提供了更多的选择,能够更好地满足不同场景下的需求。

  • 59
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值