跳转到内容

Java 8新特性

来自代码酷

Java 8新特性[编辑 | 编辑源代码]

Java 8 是 Java 编程语言的一个重要版本,于2014年发布。它引入了许多革命性的新特性,旨在提高开发效率、代码可读性和性能。这些特性包括 Lambda 表达式、Stream API、新的日期时间 API、默认方法等。本章将详细介绍这些特性及其应用。

Lambda 表达式[编辑 | 编辑源代码]

Lambda 表达式是 Java 8 最显著的特性之一,它允许以简洁的方式实现函数式接口(Functional Interface)。Lambda 表达式使得代码更加简洁,并支持函数式编程风格。

语法[编辑 | 编辑源代码]

Lambda 表达式的语法如下:

(parameters) -> expression

(parameters) -> { statements; }

示例[编辑 | 编辑源代码]

以下是一个简单的 Lambda 表达式示例,用于实现 `Runnable` 接口:

// Java 7 之前的写法
Runnable r1 = new Runnable() {
    @Override
    public void run() {
        System.out.println("Hello World!");
    }
};

// Java 8 使用 Lambda 表达式
Runnable r2 = () -> System.out.println("Hello World!");

输出[编辑 | 编辑源代码]

Hello World!

解释[编辑 | 编辑源代码]

Lambda 表达式 `() -> System.out.println("Hello World!")` 替代了匿名内部类的冗长写法,使代码更加简洁。

Stream API[编辑 | 编辑源代码]

Stream API 是 Java 8 引入的一个新的抽象层,用于处理集合数据。它支持函数式编程风格,可以高效地进行过滤、映射、归约等操作。

示例[编辑 | 编辑源代码]

以下是一个使用 Stream API 过滤和打印列表元素的示例:

List<String> names = Arrays.asList("Alice", "Bob", "Charlie", "David");

// 使用 Stream 过滤并打印名字长度大于 3 的元素
names.stream()
     .filter(name -> name.length() > 3)
     .forEach(System.out::println);

输出[编辑 | 编辑源代码]

Alice
Charlie
David

解释[编辑 | 编辑源代码]

- `stream()` 方法将集合转换为流。 - `filter()` 方法过滤出满足条件的元素(这里条件是名字长度大于 3)。 - `forEach()` 方法遍历流中的元素并打印。

新的日期时间 API[编辑 | 编辑源代码]

Java 8 引入了 `java.time` 包,提供了全新的日期时间 API,解决了旧版 `java.util.Date` 和 `java.util.Calendar` 的诸多问题。

示例[编辑 | 编辑源代码]

以下是一个使用新日期时间 API 的示例:

// 获取当前日期
LocalDate today = LocalDate.now();
System.out.println("Today: " + today);

// 计算明天的日期
LocalDate tomorrow = today.plusDays(1);
System.out.println("Tomorrow: " + tomorrow);

// 格式化日期
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd-MM-yyyy");
String formattedDate = tomorrow.format(formatter);
System.out.println("Formatted Date: " + formattedDate);

输出[编辑 | 编辑源代码]

Today: 2023-10-01
Tomorrow: 2023-10-02
Formatted Date: 02-10-2023

解释[编辑 | 编辑源代码]

- `LocalDate` 表示不带时间的日期。 - `plusDays()` 方法用于计算未来日期。 - `DateTimeFormatter` 用于格式化日期。

默认方法[编辑 | 编辑源代码]

默认方法(Default Methods)允许接口包含具体实现的方法,而不仅仅是抽象方法。这是为了支持向后兼容性,特别是在为集合框架添加新功能时。

示例[编辑 | 编辑源代码]

以下是一个包含默认方法的接口示例:

interface Greeting {
    void sayHello(String name);

    default void sayBye(String name) {
        System.out.println("Goodbye, " + name);
    }
}

public class Main implements Greeting {
    @Override
    public void sayHello(String name) {
        System.out.println("Hello, " + name);
    }

    public static void main(String[] args) {
        Main main = new Main();
        main.sayHello("Alice");
        main.sayBye("Alice");
    }
}

输出[编辑 | 编辑源代码]

Hello, Alice
Goodbye, Alice

解释[编辑 | 编辑源代码]

- `Greeting` 接口定义了一个抽象方法 `sayHello` 和一个默认方法 `sayBye`。 - `Main` 类实现了 `Greeting` 接口,并可以选择是否重写默认方法。

方法引用[编辑 | 编辑源代码]

方法引用(Method References)是 Lambda 表达式的一种简化写法,用于直接引用已有方法。

示例[编辑 | 编辑源代码]

以下是一个使用方法引用的示例:

List<String> names = Arrays.asList("Alice", "Bob", "Charlie");

// 使用方法引用打印每个元素
names.forEach(System.out::println);

输出[编辑 | 编辑源代码]

Alice
Bob
Charlie

解释[编辑 | 编辑源代码]

`System.out::println` 是 `System.out.println()` 方法的方法引用,等效于 Lambda 表达式 `x -> System.out.println(x)`。

Optional 类[编辑 | 编辑源代码]

`Optional` 是 Java 8 引入的一个容器类,用于解决 `NullPointerException` 问题。它可以明确表示一个值可能为 `null`。

示例[编辑 | 编辑源代码]

以下是一个使用 `Optional` 的示例:

Optional<String> name = Optional.ofNullable(getName());
System.out.println(name.orElse("Default Name"));

String getName() {
    return null; // 模拟可能返回 null 的方法
}

输出[编辑 | 编辑源代码]

Default Name

解释[编辑 | 编辑源代码]

- `Optional.ofNullable()` 创建一个 `Optional` 对象,允许值为 `null`。 - `orElse()` 方法在值为 `null` 时返回默认值。

实际应用案例[编辑 | 编辑源代码]

以下是一个结合 Lambda 表达式和 Stream API 的实际案例,用于统计员工列表中薪资高于平均值的员工:

class Employee {
    String name;
    double salary;

    Employee(String name, double salary) {
        this.name = name;
        this.salary = salary;
    }

    public double getSalary() { return salary; }
    public String getName() { return name; }
}

public class Main {
    public static void main(String[] args) {
        List<Employee> employees = Arrays.asList(
            new Employee("Alice", 5000),
            new Employee("Bob", 6000),
            new Employee("Charlie", 7000)
        );

        double averageSalary = employees.stream()
                                       .mapToDouble(Employee::getSalary)
                                       .average()
                                       .orElse(0);

        System.out.println("Average Salary: " + averageSalary);

        employees.stream()
                .filter(e -> e.getSalary() > averageSalary)
                .forEach(e -> System.out.println(e.getName()));
    }
}

输出[编辑 | 编辑源代码]

Average Salary: 6000.0
Charlie

解释[编辑 | 编辑源代码]

- `mapToDouble()` 将员工对象映射为薪资值。 - `average()` 计算平均薪资。 - `filter()` 过滤出薪资高于平均值的员工。

总结[编辑 | 编辑源代码]

Java 8 的新特性极大地提升了开发效率和代码可读性。Lambda 表达式、Stream API、新的日期时间 API、默认方法等特性使得 Java 更适合现代编程需求。通过本章的学习,读者应能掌握这些特性的基本用法,并在实际项目中灵活运用。