JDK1.8新特性全解析

JDK 1.8 新特性详解:新增类与常用方法

一、概述

Java Development Kit (JDK) 1.8(也称为 Java 8)是 Java 语言发展历程中的一个里程碑式版本,于 2014 年 3 月发布。它引入了多项革命性的新特性,彻底改变了 Java 开发者的编码方式和思维模式。这些新特性不仅大幅提升了代码的简洁性和可读性,还为 Java 语言注入了函数式编程的强大能力。

本文将详细介绍 JDK 1.8 中新增的类以及常用方法,帮助开发者全面理解并掌握这些重要特性。


二、Lambda 表达式:函数式编程的基石

2.1 核心概念

Lambda 表达式是 Java 8 引入的最重要特性之一,它允许我们将一段代码(函数)作为参数传递给方法,而无需创建匿名内部类。Lambda 表达式的本质是函数式接口的实例

函数式接口 :只包含一个抽象方法的接口,例如RunnableComparator等。

2.2 语法结构

Lambda 表达式的基本语法格式为:

复制代码
(参数列表) -> {方法体}

语法简化规则

  • 参数列表的数据类型可以省略(类型推断)
  • 如果参数列表只有一个参数,括号可以省略
  • 如果方法体只有一条语句,大括号和分号可以省略
  • 如果方法体有返回值且只有一条语句,return关键字可以省略

2.3 常用示例

线程创建

复制代码
// 传统方式
new Thread(new Runnable() {
    @Override
    public void run() {
        System.out.println("Hello, Java 8!");
    }
}).start();

// Lambda表达式
new Thread(() -> System.out.println("Hello, Java 8!")).start();

集合排序

复制代码
List<String> list = Arrays.asList("apple", "banana", "cherry");

// 传统方式
Collections.sort(list, new Comparator<String>() {
    @Override
    public int compare(String s1, String s2) {
        return s1.length() - s2.length();
    }
});

// Lambda表达式
Collections.sort(list, (s1, s2) -> s1.length() - s2.length());

// 更简洁的方式(Java 8新增的List.sort()方法)
list.sort((s1, s2) -> s1.length() - s2.length());

2.4 核心特性

  1. 简洁性:大幅减少代码量,提高可读性
  2. 延迟执行:只有在被调用时才会执行
  3. 类型推断:编译器自动推断参数类型

三、Stream API:声明式集合处理

3.1 概念与优势

Stream API 是 Java 8 中用于处理集合的新 API,它借鉴了函数式编程的思想,提供了一种声明式的集合操作方式。

核心优势

  • 代码更简洁:无需手动编写循环逻辑
  • 可读性更强:专注于 "做什么" 而非 "怎么做"
  • 支持并行处理:充分利用多核 CPU 性能

3.2 操作流程

Stream API 的操作流程分为三个步骤:

  1. 创建 Stream :通过集合的stream()parallelStream()方法
  2. 中间操作:对 Stream 中的数据进行处理(惰性执行)
  3. 终止操作:触发计算并返回结果

3.3 常用中间操作

方法 功能描述
filter(Predicate<T> predicate) 过滤符合条件的元素
map(Function<T, R> mapper) 将元素映射为另一种类型
sorted() 自然排序
sorted(Comparator<T> comparator) 自定义排序
distinct() 去重
limit(long maxSize) 限制元素数量
skip(long n) 跳过前 n 个元素

3.4 常用终止操作

方法 功能描述
forEach(Consumer<T> action) 遍历元素
collect(Collector<T, A, R> collector) 收集结果到集合
count() 统计元素数量
max(Comparator<T> comparator) 求最大值
min(Comparator<T> comparator) 求最小值
reduce(T identity, BinaryOperator<T> accumulator) 归约操作
anyMatch(Predicate<T> predicate) 是否有任意元素匹配
allMatch(Predicate<T> predicate) 是否所有元素都匹配
noneMatch(Predicate<T> predicate) 是否没有元素匹配

3.5 实战示例

筛选偶数并计算平方和

复制代码
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9);
int sum = numbers.stream()
    .filter(n -> n % 2 == 0)    // 筛选偶数
    .map(n -> n * n)            // 计算平方
    .reduce(0, Integer::sum);   // 计算总和
System.out.println(sum); // 输出 120

复杂业务场景处理

复制代码
List<Order> orders = Arrays.asList(
    new Order("O001", "张三", 1200, LocalDate.of(2025, 2, 10)),
    new Order("O002", "李四", 800, LocalDate.of(2024, 12, 5)),
    new Order("O003", "王五", 1500, LocalDate.of(2025, 3, 15)),
    new Order("O004", "赵六", 2000, LocalDate.of(2025, 1, 20))
);

LocalDate thresholdDate = LocalDate.of(2025, 1, 1);
Map<String, String> resultMap = orders.stream()
    // 筛选2025年1月1日后创建且金额大于1000的订单
    .filter(order -> order.getCreateTime().isAfter(thresholdDate) && order.getAmount() > 1000)
    // 按金额降序排序
    .sorted((o1, o2) -> Double.compare(o2.getAmount(), o1.getAmount()))
    // 提取订单编号和客户姓名,收集到Map
    .collect(Collectors.toMap(Order::getOrderId, Order::getCustomerName));

四、Optional 类:优雅处理 null 值

4.1 设计目的

Optional类是一个可以为 null 的容器对象,设计用来帮助开发者更好地处理可能为 null 的值,从而避免空指针异常(NullPointerException)

4.2 常用方法

方法 功能描述
Optional.of(T value) 创建 Optional 实例(value 不能为 null)
Optional.ofNullable(T value) 创建 Optional 实例(value 可以为 null)
Optional.empty() 返回空的 Optional 实例
isPresent() 判断值是否存在
get() 获取值(值不存在时抛出异常)
orElse(T other) 值存在则返回该值,否则返回 other
orElseGet(Supplier<? extends T> other) 值存在则返回该值,否则返回 Supplier 提供的值
orElseThrow(Supplier<? extends X> exceptionSupplier) 值存在则返回该值,否则抛出指定异常
ifPresent(Consumer<? super T> consumer) 值存在时执行 Consumer 操作
map(Function<? super T, ? extends U> mapper) 映射值
flatMap(Function<? super T, Optional<U>> mapper) 扁平化映射

4.3 使用示例

复制代码
public class OptionalExample {
    public static void main(String[] args) {
        String name = null;
        
        // 使用Optional.ofNullable避免NullPointerException
        Optional<String> optionalName = Optional.ofNullable(name);
        
        // 判断是否存在
        if (optionalName.isPresent()) {
            System.out.println(optionalName.get());
        } else {
            System.out.println("Name is not present.");
        }
        
        // 使用orElse提供默认值
        String defaultName = optionalName.orElse("Default Name");
        System.out.println(defaultName);
        
        // 使用orElseGet提供默认值
        String defaultName2 = optionalName.orElseGet(() -> "Default Name from Supplier");
        System.out.println(defaultName2);
        
        // 使用orElseThrow抛出异常
        try {
            String requiredName = optionalName.orElseThrow(() -> 
                new IllegalArgumentException("Name must be provided"));
        } catch (IllegalArgumentException e) {
            e.printStackTrace();
        }
        
        // 使用ifPresent
        optionalName.ifPresent(System.out::println);
    }
}

五、新日期时间 API:java.time 包

5.1 设计理念

Java 8 引入了全新的日期时间 API(JSR 310),解决了旧版日期时间类(java.util.Datejava.util.Calendar)存在的诸多问题:

  • 不可变性:所有核心类都是不可变的
  • 领域驱动设计:精确建模不同的日期时间概念
  • 线程安全:所有类都是线程安全的
  • 支持 ISO 8601 标准

5.2 核心类

5.2.1 LocalDate

表示日期(年、月、日),不包含时间信息。

常用方法

  • LocalDate.now():获取当前日期
  • LocalDate.of(int year, int month, int dayOfMonth):创建指定日期
  • LocalDate.of(int year, Month month, int dayOfMonth):使用枚举创建日期
  • getYear():获取年份
  • getMonth():获取月份(枚举)
  • getMonthValue():获取月份(数字)
  • getDayOfMonth():获取日期
  • getDayOfWeek():获取星期几
  • plusDays(long daysToAdd):增加天数
  • minusMonths(long monthsToSubtract):减少月份
  • isAfter(ChronoLocalDate other):判断是否在指定日期之后
  • isBefore(ChronoLocalDate other):判断是否在指定日期之前
  • format(DateTimeFormatter formatter):格式化日期
5.2.2 LocalTime

表示时间(时、分、秒、纳秒),不包含日期信息。

常用方法

  • LocalTime.now():获取当前时间
  • LocalTime.of(int hour, int minute):创建指定时间
  • LocalTime.of(int hour, int minute, int second):创建指定时间
  • getHour():获取小时
  • getMinute():获取分钟
  • getSecond():获取秒
  • plusHours(long hoursToAdd):增加小时
  • minusMinutes(long minutesToSubtract):减少分钟
5.2.3 LocalDateTime

表示日期和时间,不包含时区信息。

常用方法

  • LocalDateTime.now():获取当前日期时间
  • LocalDateTime.of(LocalDate date, LocalTime time):创建指定日期时间
  • toLocalDate():转换为 LocalDate
  • toLocalTime():转换为 LocalTime
  • plusWeeks(long weeksToAdd):增加周数
5.2.4 ZonedDateTime

表示带时区的日期时间。

常用方法

  • ZonedDateTime.now():获取当前带时区的日期时间
  • ZonedDateTime.now(ZoneId zone):获取指定时区的日期时间
  • withZoneSameInstant(ZoneId zone):转换时区
  • getZone():获取时区
5.2.5 Instant

表示时间戳(从 1970-01-01T00:00:00Z 开始的秒数)。

常用方法

  • Instant.now():获取当前时间戳
  • toEpochMilli():转换为毫秒数
  • plusMillis(long millisToAdd):增加毫秒数
5.2.6 Period 和 Duration
  • Period:表示日期间隔(年、月、日)
  • Duration:表示时间间隔(时、分、秒、纳秒)

5.3 使用示例

复制代码
import java.time.*;
import java.time.format.DateTimeFormatter;

public class DateTimeExample {
    public static void main(String[] args) {
        // 获取当前日期
        LocalDate today = LocalDate.now();
        System.out.println("Today's date is " + today);
        
        // 获取当前时间
        LocalTime now = LocalTime.now();
        System.out.println("Current time is " + now);
        
        // 获取当前日期时间
        LocalDateTime nowDateTime = LocalDateTime.now();
        System.out.println("Current date and time is " + nowDateTime);
        
        // 设置特定日期
        LocalDate birthday = LocalDate.of(1990, Month.JANUARY, 1);
        System.out.println("Birthday is " + birthday);
        
        // 设置特定时间
        LocalTime meetingTime = LocalTime.of(13, 30);
        System.out.println("Meeting time is " + meetingTime);
        
        // 设置特定日期时间
        LocalDateTime appointment = LocalDateTime.of(2023, Month.APRIL, 15, 10, 0);
        System.out.println("Appointment is " + appointment);
        
        // 时区
        ZonedDateTime zonedDateTime = ZonedDateTime.now(ZoneId.of("America/New_York"));
        System.out.println("Current date and time in New York is " + zonedDateTime);
        
        // 时间戳
        Instant instant = Instant.now();
        System.out.println("Current timestamp is " + instant);
        
        // 日期间隔
        Period period = Period.between(LocalDate.of(2020, 1, 1), LocalDate.of(2021, 1, 1));
        System.out.println("Period between dates is " + period);
        
        // 时间间隔
        Duration duration = Duration.between(LocalTime.of(12, 0), LocalTime.of(13, 30));
        System.out.println("Duration between times is " + duration);
        
        // 日期格式化
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        String formattedDateTime = nowDateTime.format(formatter);
        System.out.println("Formatted date time: " + formattedDateTime);
    }
}

六、接口增强:默认方法与静态方法

6.1 接口默认方法

Java 8 允许在接口中定义带有实现的方法,使用default关键字修饰。

语法

复制代码
public interface MyInterface {
    default void myMethod() {
        // 默认方法的实现代码
    }
}

使用场景

  1. 为接口添加新方法,不破坏已有代码兼容性
  2. 提供默认实现,减少实现类的工作量

示例

复制代码
public interface Shape {
    double getArea();
    
    default double getPerimeter() {
        return 0;
    }
}

public class Circle implements Shape {
    private double radius;
    
    public Circle(double radius) {
        this.radius = radius;
    }
    
    @Override
    public double getArea() {
        return Math.PI * radius * radius;
    }
    
    @Override
    public double getPerimeter() {
        return 2 * Math.PI * radius;
    }
}

6.2 接口静态方法

Java 8 允许在接口中定义静态方法。

语法

复制代码
public interface MyInterface {
    static void myStaticMethod() {
        // 静态方法的实现代码
    }
}

使用场景

  • 提供与接口相关的工具方法
  • 可以直接通过接口名调用

示例

复制代码
public interface DateUtils {
    LocalDate getCurrentDate();
    
    static long getDaysBetween(LocalDate date1, LocalDate date2) {
        return ChronoUnit.DAYS.between(date1, date2);
    }
}

// 使用
LocalDate date1 = LocalDate.of(2022, 3, 1);
LocalDate date2 = LocalDate.of(2022, 3, 4);
long days = DateUtils.getDaysBetween(date1, date2);
System.out.println("Days between: " + days); // 输出 3

七、并发编程增强

7.1 CompletableFuture:异步编程的利器

CompletableFuture是 Java 8 中引入的异步编程工具,实现了FutureCompletionStage接口。

常用方法

7.1.1 创建 CompletableFuture
  • CompletableFuture.supplyAsync(Supplier<U> supplier):异步执行有返回值的任务
  • CompletableFuture.runAsync(Runnable runnable):异步执行无返回值的任务
  • CompletableFuture.completedFuture(U value):创建已完成的 CompletableFuture
7.1.2 结果处理方法
  • thenApply(Function<? super T,? extends U> fn):当任务完成时,应用函数到结果
  • thenAccept(Consumer<? super T> action):当任务完成时,消费结果
  • thenRun(Runnable action):当任务完成时,执行 Runnable
  • thenCompose(Function<? super T,? extends CompletionStage<U>> fn):组合两个 CompletableFuture
  • thenCombine(CompletionStage<? extends U> other, BiFunction<? super T,? super U,? extends V> fn):组合两个结果
  • exceptionally(Function<Throwable,? extends T> fn):处理异常
  • whenComplete(BiConsumer<? super T,? super Throwable> action):完成时处理结果或异常
7.1.3 示例
复制代码
// 异步执行任务
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
    // 模拟耗时操作
    try {
        Thread.sleep(1000);
    } catch (InterruptedException e) {
        throw new IllegalStateException(e);
    }
    return "Hello";
});

// 处理结果
future.thenApply(result -> result + " World")
      .thenAccept(System.out::println)
      .exceptionally(ex -> {
          ex.printStackTrace();
          return null;
      });

7.2 StampedLock:更灵活的锁机制

StampedLock是 Java 8 中引入的一种新型锁,支持三种锁模式:

  1. 写锁(Write Lock):独占锁
  2. 悲观读锁(Read Lock):共享锁
  3. 乐观读锁(Optimistic Read):非阻塞锁

常用方法

  • long writeLock():获取写锁
  • long readLock():获取悲观读锁
  • long tryOptimisticRead():尝试获取乐观读锁
  • boolean validate(long stamp):验证乐观读锁是否有效
  • void unlockWrite(long stamp):释放写锁
  • void unlockRead(long stamp):释放悲观读锁

示例

复制代码
public class StampedLockExample {
    private double x, y;
    private final StampedLock sl = new StampedLock();
    
    void move(double deltaX, double deltaY) {
        long stamp = sl.writeLock();
        try {
            x += deltaX;
            y += deltaY;
        } finally {
            sl.unlockWrite(stamp);
        }
    }
    
    double distanceFromOrigin() {
        long stamp = sl.tryOptimisticRead();
        double currentX = x, currentY = y;
        if (!sl.validate(stamp)) {
            stamp = sl.readLock();
            try {
                currentX = x;
                currentY = y;
            } finally {
                sl.unlockRead(stamp);
            }
        }
        return Math.sqrt(currentX * currentX + currentY * currentY);
    }
}

7.3 ConcurrentHashMap 增强

Java 8 对ConcurrentHashMap进行了重大改进,主要包括:

  1. 新的方法

    • computeIfAbsent(K key, Function<? super K,? extends V> mappingFunction)
    • computeIfPresent(K key, BiFunction<? super K,? super V,? extends V> remappingFunction)
    • compute(K key, BiFunction<? super K,? super V,? extends V> remappingFunction)
    • merge(K key, V value, BiFunction<? super V,? super V,? extends V> remappingFunction)
  2. 性能优化

    • 使用 CAS 操作代替锁
    • 红黑树代替链表存储冲突的键值对

示例

复制代码
ConcurrentHashMap<String, Integer> map = new ConcurrentHashMap<>();

// computeIfAbsent:键不存在时计算值
map.computeIfAbsent("key1", k -> 10);

// computeIfPresent:键存在时更新值
map.computeIfPresent("key1", (k, v) -> v + 5);

// merge:合并值
map.merge("key1", 3, Integer::sum);

八、方法引用:Lambda 的简化形式

8.1 概念

方法引用是 Lambda 表达式的一种简化形式,当 Lambda 表达式仅仅是调用一个已经存在的方法时,可以使用方法引用来简化代码。

8.2 四种类型

8.2.1 对象::实例方法
复制代码
// Lambda表达式
Consumer<String> consumer = s -> System.out.println(s);

// 方法引用
Consumer<String> consumer = System.out::println;
8.2.2 类::静态方法
复制代码
// Lambda表达式
Function<Integer, Integer> function = x -> Math.abs(x);

// 方法引用
Function<Integer, Integer> function = Math::abs;
8.2.3 类::实例方法
复制代码
// Lambda表达式
Comparator<String> comparator = (s1, s2) -> s1.compareTo(s2);

// 方法引用
Comparator<String> comparator = String::compareTo;
8.2.4 类::new(构造函数引用)
复制代码
// Lambda表达式
Supplier<List<String>> supplier = () -> new ArrayList<>();

// 方法引用
Supplier<List<String>> supplier = ArrayList::new;

8.3 使用场景

方法引用在 Stream API 中广泛使用:

复制代码
List<String> list = Arrays.asList("apple", "banana", "cherry");

// 使用方法引用遍历
list.forEach(System.out::println);

// 使用方法引用排序
list.sort(String::compareToIgnoreCase);

// 使用方法引用映射
List<Integer> lengths = list.stream()
    .map(String::length)
    .collect(Collectors.toList());

九、其他重要新特性

9.1 Base64 编码

Java 8 在java.util.Base64包中提供了 Base64 编码和解码的支持。

常用方法

  • Base64.getEncoder().encodeToString(byte[] src):编码
  • Base64.getDecoder().decode(String src):解码

示例

复制代码
String originalInput = "test input";
String encodedString = Base64.getEncoder().encodeToString(originalInput.getBytes());
byte[] decodedBytes = Base64.getDecoder().decode(encodedString);
String decodedString = new String(decodedBytes);

9.2 Nashorn JavaScript 引擎

Java 8 引入了 Nashorn JavaScript 引擎,替代了 Rhino 引擎。

示例

复制代码
ScriptEngineManager manager = new ScriptEngineManager();
ScriptEngine engine = manager.getEngineByName("JavaScript");

try {
    engine.eval("print('Hello, JavaScript!')");
} catch (ScriptException e) {
    e.printStackTrace();
}

9.3 并行数组排序

Java 8 新增了Arrays.parallelSort()方法,支持并行排序。

示例

复制代码
int[] array = {5, 3, 8, 1, 2};
Arrays.parallelSort(array);

9.4 OptionalInt、OptionalLong、OptionalDouble

Java 8 为基本数据类型提供了 Optional 版本:

复制代码
OptionalInt optionalInt = OptionalInt.of(10);
if (optionalInt.isPresent()) {
    System.out.println(optionalInt.getAsInt());
}

OptionalLong optionalLong = OptionalLong.empty();
long value = optionalLong.orElse(0L);

OptionalDouble optionalDouble = OptionalDouble.of(3.14);
optionalDouble.ifPresent(System.out::println);

十、总结

JDK 1.8 引入的新特性彻底改变了 Java 的编程方式,主要体现在以下几个方面:

  1. 函数式编程支持:Lambda 表达式和 Stream API 让 Java 支持函数式编程风格
  2. 更好的 null 值处理:Optional 类提供了优雅的 null 值处理方式
  3. 现代化的日期时间 API:解决了旧 API 的诸多问题
  4. 接口增强:默认方法和静态方法提供了更好的接口设计方式
  5. 并发编程改进:CompletableFuture、StampedLock 等提供了更强大的并发工具
  6. 性能优化:ConcurrentHashMap 等类的性能大幅提升

掌握这些新特性对于 Java 开发者来说已经成为必备技能。它们不仅能让代码更加简洁、优雅,还能提高开发效率和程序性能。

在实际开发中,应该根据具体需求选择合适的特性,合理运用 Lambda 表达式、Stream API 等新特性,写出更加优雅、高效的 Java 代码。

相关推荐
战南诚1 小时前
如何查看正在执行的事务
python·flask·sqlalchemy
上海好程序员1 小时前
Windows Server 2025/2022/2019/2016/2012/2008 各版本桌面/开始菜单预览
windows·server
@游子1 小时前
Python学习笔记-Day4
笔记·python·学习
特种加菲猫1 小时前
解码TCP:如何实现可靠的数据传输
linux·网络·网络协议·tcp/ip
艾莉丝努力练剑1 小时前
【Python基础:语法第二课】Python 流程控制详解:条件语句 + 循环语句 + 人生重开模拟器实战
人工智能·爬虫·python·pycharm
Dest1ny-安全1 小时前
CTF 及网络安全相关平台汇总表
java·运维·服务器·python·安全·web安全
java1234_小锋1 小时前
[免费]基于Python的深度学习人脸表情识别系统(Keras卷积神经网络+OpenCV+PyQt)【论文+源码+SQL脚本】
python·深度学习·keras·表情识别
萧鼎1 小时前
告别 PR!用 Python + MoviePy 自动化剪辑视频
python·自动化·音视频
云霄IT1 小时前
python轮子:适配requests.request的aiohttp异步请求
开发语言·python